Skip to content

Commit

Permalink
Release Flutter SDK version 9.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
hokstuff committed Apr 9, 2024
1 parent 322dad4 commit 5f0c9f7
Show file tree
Hide file tree
Showing 18 changed files with 788 additions and 76 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
## 9.0.0

##### Breaking
- Updates the native iOS bridge [from Braze Swift SDK 7.7.0 to 8.4.0](https://github.com/braze-inc/braze-swift-sdk/compare/7.7.0...8.4.0#diff-06572a96a58dc510037d5efa622f9bec8519bc1beab13c9f251e97e657a9d4ed).
- The minimum iOS deployment target has been updated to 12.0.
- Updates the native Android bridge [from Braze Android SDK 29.0.1 to 30.3.0](https://github.com/braze-inc/braze-android-sdk/compare/v29.0.1...v30.3.0#diff-06572a96a58dc510037d5efa622f9bec8519bc1beab13c9f251e97e657a9d4ed).
- The minimum supported Dart version is `2.15.0`.

##### Added
- Push notification payloads are now accessible in the Dart layer by calling `subscribeToPushNotificationEvents(void Function(BrazePushEvent) onEvent)`. This allows you to run custom Dart code after a push is received or when a push is clicked.
- On iOS, this callback can only be triggered for push click events.
- Reference our [Flutter Push Notification documentation](https://www.braze.com/docs/developer_guide/platform_integration_guides/flutter/push_notifications) with details on how to utilize this feature.
- This feature is compatible with the `replayCallbacksConfigKey` to replay the push event callback for any notifications that were received prior to calling `subscribeToPushNotificationEvents`.
- Adds support for Braze tracking properties.
- Adds the `updateTrackingPropertyAllowList(allowList)` method to dynamically configure Braze tracking properties.
- For further usage details, refer to the [Swift privacy manifest documentation](https://www.braze.com/docs/developer_guide/platform_integration_guides/swift/privacy_manifest/).
- Deprecates `setGoogleAdvertisingId(id, adTrackingEnabled)` in favor of `setAdTrackingEnabled(adTrackingEnabled, id)`.

## 8.2.0

##### Added
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ Please reach out to support@braze.com regarding any questions or issues.
The `/example` folder contains a sample app illustrating how to integrate and use this package's APIs.

### Requirements
- Dart SDK 2.12.0+
- Dart SDK 2.15.0+
- Flutter SDK 1.10.0+
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ android {

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "com.braze:android-sdk-ui:29.0.1"
implementation "com.braze:android-sdk-ui:30.3.0"
}
80 changes: 78 additions & 2 deletions android/src/main/kotlin/com/braze/brazeplugin/BrazePlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ package com.braze.brazeplugin
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.annotation.NonNull
import com.braze.enums.Gender
import com.braze.enums.Month
import com.braze.enums.NotificationSubscriptionType
import com.braze.enums.BrazePushEventType
import com.braze.models.cards.Card
import com.braze.models.outgoing.AttributionData
import com.braze.Braze
import com.braze.BrazeUser
import com.braze.events.BrazeSdkAuthenticationErrorEvent
import com.braze.events.SimpleValueCallback
import com.braze.events.BrazePushEvent
import com.braze.models.FeatureFlag
import com.braze.models.inappmessage.IInAppMessage
import com.braze.models.inappmessage.IInAppMessageImmersive
Expand All @@ -21,6 +24,7 @@ import com.braze.support.BrazeLogger.Priority.I
import com.braze.support.BrazeLogger.Priority.W
import com.braze.support.BrazeLogger.brazelog
import com.braze.ui.activities.ContentCardsActivity
import com.braze.Constants
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
Expand Down Expand Up @@ -115,6 +119,61 @@ class BrazePlugin : MethodCallHandler, FlutterPlugin, ActivityAware {
}
}

/**
* Used to pass in Push Notification event data from
* the Braze SDK native layer to the Flutter layer.
*/
@JvmStatic
fun processPushNotificationEvent(event: BrazePushEvent) {
if (activePlugins.isEmpty()) {
brazelog(W) { "There are no active Braze Plugins. Not calling 'handleBrazePushNotificationEvent'." }
return
}

val pushType = when (event.eventType) {
BrazePushEventType.NOTIFICATION_RECEIVED -> "push_received"
BrazePushEventType.NOTIFICATION_OPENED -> "push_opened"
else -> return Unit
}
val eventData = event.notificationPayload

val data = JSONObject().apply {
put("payload_type", pushType)
put("url", eventData.deeplink)
put("title", eventData.titleText)
put("body", eventData.contentText)
put("summary_text", eventData.summaryText)
eventData.notificationBadgeNumber?.let { put("badge_count", it) }
eventData.notificationExtras.getLong("braze_push_received_timestamp")
.takeUnless { it == 0L }?.let {
put("timestamp", it.toLong())
}
put(
"use_webview",
eventData.notificationExtras.getString("ab_use_webview") == "true"
)
put(
"is_silent", eventData.titleText == null && eventData.contentText == null
)
put(
"is_braze_internal",
eventData.isUninstallTrackingPush
|| eventData.shouldSyncGeofences
|| eventData.shouldRefreshFeatureFlags
)
put("image_url", eventData.bigImageUrl)
put("android", convertToMap(eventData.notificationExtras))
}
val brazePropertiesMap =
convertToMap(eventData.brazeExtras, setOf(Constants.BRAZE_PUSH_BIG_IMAGE_URL_KEY))
data.put("braze_properties", brazePropertiesMap)
val pushEventMap = hashMapOf("pushEvent" to data.toString())

executeOnAllPlugins {
it.channel.invokeMethod("handleBrazePushNotificationEvent", pushEventMap)
}
}

/**
* Used to pass in Feature Flag data from the Braze
* SDK native layer to the Flutter layer.
Expand All @@ -141,6 +200,15 @@ class BrazePlugin : MethodCallHandler, FlutterPlugin, ActivityAware {
}
}
}

private fun convertToMap(bundle: Bundle, filteringKeys: Set<String> = emptySet()): JSONObject {
val map = JSONObject()
bundle.keySet()
.filter { !filteringKeys.contains(it) }
.associateWith { @Suppress("deprecation") bundle[it] }
.forEach { map.put(it.key, it.value) }
return map
}
}

//--
Expand Down Expand Up @@ -512,6 +580,14 @@ class BrazePlugin : MethodCallHandler, FlutterPlugin, ActivityAware {
val adTrackingEnabled = call.argument<Boolean>("adTrackingEnabled") ?: return
Braze.getInstance(context).setGoogleAdvertisingId(id, adTrackingEnabled)
}
"setAdTrackingEnabled" -> {
val adTrackingEnabled = call.argument<Boolean>("adTrackingEnabled") ?: return
val id = call.argument<String>("id") ?: return
Braze.getInstance(context).setGoogleAdvertisingId(id, adTrackingEnabled)
}
"updateTrackingPropertyAllowList" -> {
// No-op on Android
}
"wipeData" -> {
Braze.wipeData(context)
}
Expand Down Expand Up @@ -618,8 +694,8 @@ class BrazePlugin : MethodCallHandler, FlutterPlugin, ActivityAware {
}
}

private fun getMonth(month: Int): Month {
val month = Month.getMonth(month - 1)
private fun getMonth(value: Int): Month {
val month = Month.getMonth(value - 1)
if (month == null) {
brazelog(W) { "Invalid `null` month. Defaulting to January." }
return Month.JANUARY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.app.Application
import android.content.Context
import com.braze.Braze
import com.braze.BrazeActivityLifecycleCallbackListener
import com.braze.events.BrazePushEvent
import com.braze.events.ContentCardsUpdatedEvent
import com.braze.events.FeatureFlagsUpdatedEvent
import com.braze.events.IEventSubscriber
Expand All @@ -17,38 +18,79 @@ object IntegrationInitializer {
var isUninitialized = true
private var contentCardsUpdatedSubscriber: IEventSubscriber<ContentCardsUpdatedEvent>? = null
private var featureFlagsUpdatedSubscriber: IEventSubscriber<FeatureFlagsUpdatedEvent>? = null
private var pushNotificationsUpdatedSubscriber: IEventSubscriber<BrazePushEvent>? = null

internal fun initializePlugin(application: Application, config: FlutterCachedConfiguration) {
application.registerActivityLifecycleCallbacks(BrazeActivityLifecycleCallbackListener())
val ctx = application.applicationContext
subscribeToContentCardsUpdatedEvent(ctx)
subscribeToFeatureFlagsUpdatedEvent(ctx)
subscribeToPushNotificationEvents(ctx)

BrazeInAppMessageManager.getInstance().setCustomInAppMessageManagerListener(
BrazeInAppMessageManagerListener(config.automaticIntegrationInAppMessageOperation())
)
BrazeInAppMessageManager.getInstance()
.setCustomInAppMessageManagerListener(
BrazeInAppMessageManagerListener(
config.automaticIntegrationInAppMessageOperation()
)
)
isUninitialized = false
}

private fun subscribeToContentCardsUpdatedEvent(ctx: Context) {
Braze.getInstance(ctx).removeSingleSubscription(contentCardsUpdatedSubscriber, ContentCardsUpdatedEvent::class.java)
contentCardsUpdatedSubscriber = IEventSubscriber { BrazePlugin.processContentCards(it.allCards) }
contentCardsUpdatedSubscriber?.let { Braze.getInstance(ctx).subscribeToContentCardsUpdates(it) }
Braze.getInstance(ctx)
.removeSingleSubscription(
contentCardsUpdatedSubscriber,
ContentCardsUpdatedEvent::class.java
)
contentCardsUpdatedSubscriber = IEventSubscriber {
BrazePlugin.processContentCards(it.allCards)
}
contentCardsUpdatedSubscriber?.let {
Braze.getInstance(ctx).subscribeToContentCardsUpdates(it)
}
Braze.getInstance(ctx).requestContentCardsRefresh(true)
}

private fun subscribeToPushNotificationEvents(ctx: Context) {
Braze.getInstance(ctx)
.removeSingleSubscription(
pushNotificationsUpdatedSubscriber,
BrazePushEvent::class.java
)
pushNotificationsUpdatedSubscriber = IEventSubscriber {
BrazePlugin.processPushNotificationEvent(it)
}
pushNotificationsUpdatedSubscriber?.let {
Braze.getInstance(ctx).subscribeToPushNotificationEvents(it)
}
}

private fun subscribeToFeatureFlagsUpdatedEvent(ctx: Context) {
Braze.getInstance(ctx).removeSingleSubscription(featureFlagsUpdatedSubscriber, FeatureFlagsUpdatedEvent::class.java)
featureFlagsUpdatedSubscriber = IEventSubscriber { BrazePlugin.processFeatureFlags(it.featureFlags) }
featureFlagsUpdatedSubscriber?.let { Braze.getInstance(ctx).subscribeToFeatureFlagsUpdates(it) }
Braze.getInstance(ctx)
.removeSingleSubscription(
featureFlagsUpdatedSubscriber,
FeatureFlagsUpdatedEvent::class.java
)
featureFlagsUpdatedSubscriber = IEventSubscriber {
BrazePlugin.processFeatureFlags(it.featureFlags)
}
featureFlagsUpdatedSubscriber?.let {
Braze.getInstance(ctx).subscribeToFeatureFlagsUpdates(it)
}
Braze.getInstance(ctx).refreshFeatureFlags()
}

private class BrazeInAppMessageManagerListener(val defaultInAppMessageOperation: InAppMessageOperation) : DefaultInAppMessageManagerListener() {
override fun beforeInAppMessageDisplayed(inAppMessage: IInAppMessage): InAppMessageOperation {
private class BrazeInAppMessageManagerListener(
val defaultInAppMessageOperation: InAppMessageOperation
) : DefaultInAppMessageManagerListener() {
override fun beforeInAppMessageDisplayed(
inAppMessage: IInAppMessage
): InAppMessageOperation {
super.beforeInAppMessageDisplayed(inAppMessage)
BrazePlugin.processInAppMessage(inAppMessage)
brazelog { "Returning $defaultInAppMessageOperation in Flutter automatic integration IInAppMessageManagerListener#beforeInAppMessageDisplayed()" }
brazelog {
"Returning $defaultInAppMessageOperation in Flutter automatic integration IInAppMessageManagerListener#beforeInAppMessageDisplayed()"
}
return defaultInAppMessageOperation
}
}
Expand Down
2 changes: 1 addition & 1 deletion example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'androidx.multidex:multidex:2.0.1'

implementation "com.braze:android-sdk-ui:29.0.1"
implementation "com.braze:android-sdk-ui:30.3.0"
implementation "com.google.firebase:firebase-messaging:+"
}
apply plugin: 'com.google.gms.google-services'
2 changes: 1 addition & 1 deletion example/ios/Flutter/AppFrameworkInfo.plist
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>11.0</string>
<string>12.0</string>
</dict>
</plist>
2 changes: 1 addition & 1 deletion example/ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
platform :ios, '11.0'
platform :ios, '12.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
Expand Down
Loading

0 comments on commit 5f0c9f7

Please sign in to comment.