Skip to content

Commit

Permalink
Release Flutter SDK version 11.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
hokstuff committed Sep 5, 2024
1 parent 30ac2ed commit c7158e9
Show file tree
Hide file tree
Showing 21 changed files with 391 additions and 56 deletions.
75 changes: 75 additions & 0 deletions .github/ISSUE_TEMPLATE/bug.yml
Original file line number Diff line number Diff line change
@@ -0,0 1,75 @@
name: 🐞 Bug report
description: File a Bug Report for unexpected or incorrect SDK Behavior
title: '[Bug]: '
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report! Please consider contacting [email protected] for faster integration troubleshooting and to avoid leaking private information to our public Github issues.
- type: dropdown
id: platform
attributes:
label: Which Platforms?
multiple: false
options:
- iOS
- Android
- Both
validations:
required: true
- type: input
id: platform_version
attributes:
label: Which Flutter Version?
placeholder: ex. 3.4.3
validations:
required: true
- type: input
id: sdk_version
attributes:
label: Which Braze Flutter SDK version?
placeholder: ex. 10.1.0
validations:
required: true
- type: input
id: repro_rate
attributes:
label: Repro Rate
description: How often can you reproduce this bug?
placeholder: ex. 100% of the time
validations:
required: true
- type: textarea
id: repro_steps
attributes:
label: Steps To Reproduce
description: Please provide a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example)
value:
validations:
required: true
- type: textarea
id: expected_behavior
attributes:
label: Expected Behavior
description: What was supposed to happen?
validations:
required: true
- type: textarea
id: actual_behavior
attributes:
label: Actual Incorrect Behavior
description: What incorrect behavior happened instead?
validations:
required: true
- type: textarea
id: verbose_logs
attributes:
label: Verbose Logs
description: Please copy and paste verbose log output. This will be automatically formatted into code, so no need for backticks.
render: shell
- type: textarea
id: other_info
attributes:
label: Additional Information
description: Anything else you'd like to share?
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 1,8 @@
blank_issues_enabled: false
contact_links:
- name: Braze Support
url: https://support.braze.com/
about: Contact Braze Support for company or campaign-specific troubleshooting
- name: Security Issues
url: https://www.braze.com/docs/developer_guide/disclosures/security_and_vulnerability_disclosure/
about: Please report security vulnerabilities here.
39 changes: 39 additions & 0 deletions .github/ISSUE_TEMPLATE/feature.yml
Original file line number Diff line number Diff line change
@@ -0,0 1,39 @@
name: ✅ Feature Request
description: Request New SDK Features
title: '[Feature]: '
labels: ["feature-request"]
body:
- type: markdown
attributes:
value: |
Did you know: You can also submit feature requests in our [Public Roadmap Portal](https://dashboard.braze.com/resources/roadmap)
- type: textarea
id: problem
attributes:
label: What problem are you facing?
description: Help us understand what you're unable to accomplish, or what's difficult with your integration
placeholder: |
ex: I am unable to accomplish XYZ today, since the SDK does not allow me to...
validations:
required: true
- type: textarea
id: workarounds
attributes:
label: Workarounds
description: Are there any workarounds you can use? How complicated are they?
validations:
required: true
- type: textarea
id: ideal_solution
attributes:
label: Ideal Solution
description: What would your ideal solution look like?
validations:
required: false
- type: textarea
id: other_information
attributes:
label: Other Information
description: Any additional information you'd like to share?
validations:
required: false
Binary file added .github/assets/logo-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/assets/logo-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 1,24 @@
⚠️ In version 3.0.0, we changed the iOS bridge from AppboyKit, which is written in Objective-C, to the new [Swift SDK](https://github.com/braze-inc/braze-swift-sdk). If you are upgrading from a version below 3.0.0 to a version above 3.0.0, please read [the instructions](https://github.com/braze-inc/braze-flutter-sdk/blob/master/CHANGELOG.md#300) to ensure a smooth transition and backward compatibility.

## 11.0.0

##### Breaking
- Updates the native Android bridge [from Braze Android SDK 30.4.0 to 32.1.0](https://github.com/braze-inc/braze-android-sdk/compare/v30.4.0...v32.1.0#diff-06572a96a58dc510037d5efa622f9bec8519bc1beab13c9f251e97e657a9d4ed).
- Changes the behavior of `wipeData()` on Android to retain external subscriptions (like `subscribeToContentCards()`) after being called.
- Updates the native iOS bridge [from Braze Swift SDK 9.0.0 to 10.2.0](https://github.com/braze-inc/braze-swift-sdk/compare/9.0.0...10.2.0#diff-06572a96a58dc510037d5efa622f9bec8519bc1beab13c9f251e97e657a9d4ed).

##### Added
- Adds support for 3 new Feature Flag property types:
- `featureFlag.getTimestampProperty(String key)` for accessing Int Unix UTC millisecond timestamps as `int?`s.
- `featureFlag.getJSONProperty(String key)` for accessing JSON objects as `Map<String, dynamic>?` types.
- `featureFlag.getImageProperty(String key)` for accessing image URLs as `String?`s.
- Adds the `getUserId()` method to get the ID of the current user. This method will return `null` if the current user is anonymous.
- Adds the `hideCurrentInAppMessage()` method, which dismisses the currently displayed in-app message.

##### Fixed
- Fixes an issue on Android where push notification stream subscriptions were not receiving events after clicking on a push notification when the app was in a terminated state.
- Thank you @Neelansh-ns for the contribution!

## 10.1.0

##### Added
Expand All @@ -24,6 43,7 @@
##### 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.
- The minimum supported Xcode version is 15.2.
- 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`.

Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 1,7 @@
<img src="https://raw.githubusercontent.com/Appboy/appboy-ios-sdk/master/braze-logo.png" width="300" title="Braze Logo" />
<p align="center">
<img width="480" alt="Braze Logo" src=".github/assets/logo-light.png#gh-light-mode-only" />
<img width="480" alt="Braze Logo" src=".github/assets/logo-dark.png#gh-dark-mode-only" />
</p>

# Braze Flutter SDK

Expand Down
4 changes: 2 additions & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 25,7 @@ apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

android {
compileSdkVersion 33
compileSdkVersion 34
namespace 'com.braze.brazeplugin'

sourceSets {
Expand All @@ -52,7 52,7 @@ android {

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "com.braze:android-sdk-ui:30.4.0"
implementation "com.braze:android-sdk-ui:32.1.0"

androidTestImplementation "org.mockito:mockito-android:3.12.4"
androidTestImplementation "junit:junit:4.13.2"
Expand Down
1 change: 0 additions & 1 deletion android/src/androidTest/kotlin/FlutterConfigurationTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 35,6 @@ class FlutterConfigurationTest {
@Test
fun whenBooleanValueDoesNotExistInResources_isAutomaticInitializationEnabled_returnsTrue() {
val key = "com_braze_flutter_enable_automatic_integration_initializer"
val testResId = 1234
val testPackageName = "foo.bar.braze"
val mockResources = mock<Resources>() {
on { getIdentifier(key, "bool", testPackageName) } doReturn 0
Expand Down
68 changes: 59 additions & 9 deletions android/src/main/kotlin/com/braze/brazeplugin/BrazePlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 25,7 @@ import com.braze.support.BrazeLogger.Priority.W
import com.braze.support.BrazeLogger.brazelog
import com.braze.ui.activities.ContentCardsActivity
import com.braze.Constants
import com.braze.ui.inappmessage.BrazeInAppMessageManager
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 @@ -61,7 62,7 @@ class BrazePlugin : MethodCallHandler, FlutterPlugin, ActivityAware {
}
}

override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
this.initPlugin(flutterPluginBinding.applicationContext, flutterPluginBinding.binaryMessenger)
}

Expand All @@ -74,6 75,12 @@ class BrazePlugin : MethodCallHandler, FlutterPlugin, ActivityAware {
// Contains all plugins that have been initialized and are attached to a Flutter engine.
var activePlugins = mutableListOf<BrazePlugin>()

// Contains all push events that have been received before the plugin was initialized.
var pendingPushEvents = mutableListOf<BrazePushEvent>()

// Indicates if the Dart layer has finished initializing
private var brazePluginIsReady: Boolean = false

//--
// Braze public APIs
//--
Expand Down Expand Up @@ -122,14 129,40 @@ class BrazePlugin : MethodCallHandler, FlutterPlugin, ActivityAware {
/**
* Used to pass in Push Notification event data from
* the Braze SDK native layer to the Flutter layer.
*
* If there are no active Braze Plugins, it stores
* the event for later processing.
*/
@JvmStatic
fun processPushNotificationEvent(event: BrazePushEvent) {
if (activePlugins.isEmpty()) {
brazelog(W) { "There are no active Braze Plugins. Not calling 'handleBrazePushNotificationEvent'." }
if (activePlugins.isEmpty() || !brazePluginIsReady) {
brazelog(W) { "There are no active Braze Plugins. Not calling 'handleBrazePushNotificationEvent'. Storing the event for later processing." }
// Store the event for later processing.
pendingPushEvents.add(event)
return
}

handlePushEvent(event)
}

/**
* Reprocesses all pending push events if there are any active plugins
* and the Dart layer has finished initializing.
*/
private fun reprocessPendingPushEvents() {
if (pendingPushEvents.isNotEmpty() && activePlugins.isNotEmpty() && brazePluginIsReady) {
for (event in pendingPushEvents) {
handlePushEvent(event)
}
pendingPushEvents.clear()
}
}

/**
* Handles the push event by converting it to a JSON object
* and sending it to the Dart layer.
*/
private fun handlePushEvent(event: BrazePushEvent) {
val pushType = when (event.eventType) {
BrazePushEventType.NOTIFICATION_RECEIVED -> "push_received"
BrazePushEventType.NOTIFICATION_OPENED -> "push_opened"
Expand Down Expand Up @@ -229,6 262,7 @@ class BrazePlugin : MethodCallHandler, FlutterPlugin, ActivityAware {
brazelog(I) { "Running Flutter BrazePlugin automatic initialization" }
this.activity?.application?.let { IntegrationInitializer.initializePlugin(it, flutterConfiguration) }
}
reprocessPendingPushEvents()
}

override fun onDetachedFromActivityForConfigChanges() {
Expand All @@ -251,14 285,27 @@ class BrazePlugin : MethodCallHandler, FlutterPlugin, ActivityAware {
Braze.getInstance(context).changeUser(userId, sdkAuthSignature)
}
}
"getUserId" -> {
Braze.getInstance(context).runOnUser {
if (it.userId.isBlank()) {
result.success(null)
} else {
result.success(it.userId)
}
}
}
"setSdkAuthenticationSignature" -> {
val sdkAuthSignature = call.argument<String>("sdkAuthSignature")
if (sdkAuthSignature != null) {
Braze.getInstance(context).setSdkAuthenticationSignature(sdkAuthSignature)
}
}
"setBrazePluginIsReady" -> {
brazePluginIsReady = true
reprocessPendingPushEvents()
}
"requestContentCardsRefresh" -> {
Braze.getInstance(context).requestContentCardsRefresh(false)
Braze.getInstance(context).requestContentCardsRefresh()
}
"launchContentCards" -> {
if (this.activity != null) {
Expand Down Expand Up @@ -312,6 359,9 @@ class BrazePlugin : MethodCallHandler, FlutterPlugin, ActivityAware {
}
}
}
"hideCurrentInAppMessage" -> {
BrazeInAppMessageManager.getInstance().hideCurrentlyDisplayingInAppMessage(true)
}
"addAlias" -> {
val aliasName = call.argument<String>("aliasName")
val aliasLabel = call.argument<String>("aliasLabel")
Expand Down Expand Up @@ -361,7 411,7 @@ class BrazePlugin : MethodCallHandler, FlutterPlugin, ActivityAware {
}
"setNestedCustomUserAttribute" -> {
val key = call.argument<String>("key")
val value = JSONObject(call.argument<Map<String, *>>("value"))
val value = call.argument<Map<String, *>>("value")?.let { JSONObject(it) }
val merge = call.argument<Boolean>("merge") ?: false
if (key == null || value == null) {
brazelog(W) { "Unexpected null parameter(s) in `setNestedCustomUserAttribute`." }
Expand All @@ -381,7 431,7 @@ class BrazePlugin : MethodCallHandler, FlutterPlugin, ActivityAware {
"setCustomUserAttributeArrayOfObjects" -> {
val key = call.argument<String>("key")
val value = JSONArray(call.argument<List<Map<String, *>>>("value")?.map { JSONObject(it) })
if (key == null || value == null) {
if (key == null) {
brazelog(W) { "Unexpected null parameter(s) in `setCustomUserAttributeArrayOfObjects`." }
return;
}
Expand Down Expand Up @@ -678,9 728,9 @@ class BrazePlugin : MethodCallHandler, FlutterPlugin, ActivityAware {
*/
private fun Braze.runOnUser(block: (user: BrazeUser) -> Unit) {
this.getCurrentUser(object : SimpleValueCallback<BrazeUser>() {
override fun onSuccess(user: BrazeUser) {
super.onSuccess(user)
block(user)
override fun onSuccess(value: BrazeUser) {
super.onSuccess(value)
block(value)
}
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 48,7 @@ object IntegrationInitializer {
contentCardsUpdatedSubscriber?.let {
Braze.getInstance(ctx).subscribeToContentCardsUpdates(it)
}
Braze.getInstance(ctx).requestContentCardsRefresh(true)
Braze.getInstance(ctx).requestContentCardsRefreshFromCache()
}

private fun subscribeToPushNotificationEvents(ctx: Context) {
Expand Down
3 changes: 2 additions & 1 deletion example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 88,7 @@ android {
disable 'InvalidPackage'
}
namespace 'braze.com.brazepluginexample'
compileSdk 34
}

flutter {
Expand All @@ -102,7 103,7 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'androidx.multidex:multidex:2.0.1'

implementation "com.braze:android-sdk-ui:30.4.0"
implementation "com.braze:android-sdk-ui:32.1.0"
implementation "com.google.firebase:firebase-messaging: "
}
apply plugin: 'com.google.gms.google-services'
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 38,9 @@ class MainActivity : FlutterActivity() {

private fun handleDeepLink(intent: Intent) {
val binaryMessenger = flutterEngine?.dartExecutor?.binaryMessenger
if (intent?.action == Intent.ACTION_VIEW && binaryMessenger != null) {
if (intent.action == Intent.ACTION_VIEW && binaryMessenger != null) {
MethodChannel(binaryMessenger, "deepLinkChannel")
.invokeMethod("receivedLink", intent?.data.toString())
.invokeMethod("receivedLink", intent.data.toString())
}
}
}
2 changes: 1 addition & 1 deletion example/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 60;
objectVersion = 54;
objects = {

/* Begin PBXBuildFile section */
Expand Down
Loading

0 comments on commit c7158e9

Please sign in to comment.