From 81e429094b49861e5920897496af8747911e4c4b Mon Sep 17 00:00:00 2001 From: Denis Chilik Date: Fri, 13 Mar 2026 12:07:43 -0400 Subject: [PATCH 1/2] feat: copy Braze 39 kit from braze-38 --- kits/braze/braze-39/README.md | 72 + kits/braze/braze-39/build.gradle | 72 + kits/braze/braze-39/consumer-proguard.pro | 8 + kits/braze/braze-39/example/build.gradle | 66 + .../example/src/main/AndroidManifest.xml | 43 + .../kits/braze/example/MainActivity.java | 13 + .../drawable-v24/ic_launcher_foreground.xml | 34 + .../res/drawable/ic_launcher_background.xml | 170 ++ .../src/main/res/layout/activity_main.xml | 18 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2963 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 4905 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2060 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2783 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4490 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 6895 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6387 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 10413 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9128 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 15132 bytes .../example/src/main/res/values/appboy.xml | 4 + .../example/src/main/res/values/colors.xml | 6 + .../example/src/main/res/values/strings.xml | 3 + .../example/src/main/res/values/styles.xml | 11 + kits/braze/braze-39/gradle.properties | 4 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59821 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + kits/braze/braze-39/gradlew | 234 +++ kits/braze/braze-39/gradlew.bat | 89 + kits/braze/braze-39/libs/java-json.jar | Bin 0 -> 84697 bytes kits/braze/braze-39/settings.gradle.kts | 2 + .../braze-39/src/main/AndroidManifest.xml | 1 + .../kotlin/com/mparticle/kits/AppboyKit.kt | 1396 +++++++++++++++ .../src/test/kotlin/com/braze/Braze.kt | 63 + .../src/test/kotlin/com/braze/BrazeUser.kt | 95 + .../braze/models/outgoing/BrazeProperties.kt | 55 + .../com/mparticle/kits/AppboyKitTests.kt | 1557 +++++++++++++++++ .../com/mparticle/kits/BrazePurchase.kt | 12 + .../com/mparticle/kits/TypeDetectionTests.kt | 91 + .../com/mparticle/kits/mocks/MockAppboyKit.kt | 29 + .../mparticle/kits/mocks/MockApplication.kt | 39 + .../com/mparticle/kits/mocks/MockContext.kt | 500 ++++++ .../kits/mocks/MockContextApplication.kt | 19 + .../mparticle/kits/mocks/MockCoreCallbacks.kt | 70 + .../kits/mocks/MockKitConfiguration.kt | 84 + .../kits/mocks/MockKitManagerImpl.kt | 71 + .../com/mparticle/kits/mocks/MockResources.kt | 40 + .../kits/mocks/MockSharedPreferences.kt | 88 + .../com/mparticle/kits/mocks/MockUser.kt | 53 + settings-kits.gradle | 1 + 51 files changed, 5128 insertions(+) create mode 100644 kits/braze/braze-39/README.md create mode 100644 kits/braze/braze-39/build.gradle create mode 100644 kits/braze/braze-39/consumer-proguard.pro create mode 100644 kits/braze/braze-39/example/build.gradle create mode 100644 kits/braze/braze-39/example/src/main/AndroidManifest.xml create mode 100644 kits/braze/braze-39/example/src/main/java/com/mparticle/kits/braze/example/MainActivity.java create mode 100644 kits/braze/braze-39/example/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 kits/braze/braze-39/example/src/main/res/drawable/ic_launcher_background.xml create mode 100644 kits/braze/braze-39/example/src/main/res/layout/activity_main.xml create mode 100644 kits/braze/braze-39/example/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 kits/braze/braze-39/example/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 kits/braze/braze-39/example/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 kits/braze/braze-39/example/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 kits/braze/braze-39/example/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 kits/braze/braze-39/example/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 kits/braze/braze-39/example/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 kits/braze/braze-39/example/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 kits/braze/braze-39/example/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 kits/braze/braze-39/example/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 kits/braze/braze-39/example/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 kits/braze/braze-39/example/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 kits/braze/braze-39/example/src/main/res/values/appboy.xml create mode 100644 kits/braze/braze-39/example/src/main/res/values/colors.xml create mode 100644 kits/braze/braze-39/example/src/main/res/values/strings.xml create mode 100644 kits/braze/braze-39/example/src/main/res/values/styles.xml create mode 100644 kits/braze/braze-39/gradle.properties create mode 100644 kits/braze/braze-39/gradle/wrapper/gradle-wrapper.jar create mode 100644 kits/braze/braze-39/gradle/wrapper/gradle-wrapper.properties create mode 100755 kits/braze/braze-39/gradlew create mode 100644 kits/braze/braze-39/gradlew.bat create mode 100755 kits/braze/braze-39/libs/java-json.jar create mode 100644 kits/braze/braze-39/settings.gradle.kts create mode 100644 kits/braze/braze-39/src/main/AndroidManifest.xml create mode 100644 kits/braze/braze-39/src/main/kotlin/com/mparticle/kits/AppboyKit.kt create mode 100644 kits/braze/braze-39/src/test/kotlin/com/braze/Braze.kt create mode 100644 kits/braze/braze-39/src/test/kotlin/com/braze/BrazeUser.kt create mode 100644 kits/braze/braze-39/src/test/kotlin/com/braze/models/outgoing/BrazeProperties.kt create mode 100644 kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/AppboyKitTests.kt create mode 100644 kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/BrazePurchase.kt create mode 100644 kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/TypeDetectionTests.kt create mode 100644 kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockAppboyKit.kt create mode 100644 kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockApplication.kt create mode 100644 kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockContext.kt create mode 100644 kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockContextApplication.kt create mode 100644 kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockCoreCallbacks.kt create mode 100644 kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockKitConfiguration.kt create mode 100644 kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockKitManagerImpl.kt create mode 100644 kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockResources.kt create mode 100644 kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockSharedPreferences.kt create mode 100644 kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockUser.kt diff --git a/kits/braze/braze-39/README.md b/kits/braze/braze-39/README.md new file mode 100644 index 000000000..505038e74 --- /dev/null +++ b/kits/braze/braze-39/README.md @@ -0,0 +1,72 @@ +# Braze (formerly Appboy) Kit Integration + +This repository contains the [Braze](https://www.braze.com/) integration for the [mParticle Android SDK](https://github.com/mParticle/mparticle-android-sdk). + +## Example App + +This repository contains an [example app](https://github.com/mparticle-integrations/mparticle-android-integration-appboy/tree/master/example) showing how to implement mParticle, Braze, and Firebase Cloud Messaging. The key changes you need to make to your app are below, and please also reference mParticle and Braze's documentation: + +- [Instrumenting Push](https://docs.mparticle.com/developers/sdk/android/push-notifications) +- [Braze Documentation](https://docs.mparticle.com/integrations/braze/event) + +## 1. Adding the integration + +[See a full build.gradle example here](https://github.com/mparticle-integrations/mparticle-android-integration-appboy/blob/master/example/build.gradle) + +1. The Braze Kit requires that you add Braze's Maven server to your buildscript: + + ```groovy + repositories { + maven { url "https://appboy.github.io/appboy-android-sdk/sdk" } + //Braze's library depends on the Google Support Library + google() + ... + } + ``` + +2. Add the kit dependency to your app's `build.gradle`: + + ```groovy + dependencies { + implementation 'com.mparticle:android-appboy-kit:5+' + } + ``` + +## 2. Registering for Push + +mParticle's SDK takes care of registering for push notifications and passing tokens or instance IDs to the Braze SDK. [Follow the mParticle push notification documentation](https://docs.mparticle.com/developers/sdk/android/push-notifications#register-for-push-notifications) to instrument the SDK for push registration. You can skip over [this section of Braze's documentation](https://www.braze.com/docs/developer_guide/platform_integration_guides/android/push_notifications/integration/#registering-for-push). + +## 3. Displaying Push + +[See a full example of an AndroidManifest.xml here](https://github.com/mparticle-integrations/mparticle-android-integration-appboy/blob/master/example/src/main/AndroidManifest.xml). + +mParticle's SDK also takes care of capturing incoming push notifications and passing the resulting `Intent` to Braze's `BrazePushReceiver`. Follow the [mParticle push notification documentation](https://docs.mparticle.com/developers/sdk/android/push-notifications#display-push-notifications) to ensure you add the correct services and receivers to your app's AndroidManifest.xml. + +## 4. Reacting to Push and Deeplinking + +There are a wide variety of implementation options available in Braze to deeplink a user when they tap a notification. There are **two specific requirements** to ensure automatic deeplinking works as intended. + +- `BrazePushReceiver` + + Whereas up until now you should have nothing Braze-specific in your `AndroidManifest.xml`, using Braze's automatic deeplinking does require you to add their `BrazePushReceiver`. Note that you do not need to specify any Intent filters (for example to receive push tokens, since mParticle takes care of that). You just need to add the following: + + ```xml + + ``` + +- `braze.xml` + + For automatic deep-linking, you need to add a boolean resource named `com_braze_handle_push_deep_links_automatically`. This can be in any resource file, or you can name it `braze.xml`: + + ```xml + + + true + + ``` + +From here you should be able to successfully test push via Braze! Braze offers many client-side configurable options via xml resources and otherwise. Please see review the rest of [their documentation here](https://www.braze.com/docs/developer_guide/platform_integration_guides/android/push_notifications/integration/#step-3-add-deep-links) for more information. + +## License + +[Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) diff --git a/kits/braze/braze-39/build.gradle b/kits/braze/braze-39/build.gradle new file mode 100644 index 000000000..b00ecfc9d --- /dev/null +++ b/kits/braze/braze-39/build.gradle @@ -0,0 +1,72 @@ +buildscript { + ext.kotlin_version = '2.0.20' + if (!project.hasProperty('version') || project.version.equals('unspecified')) { + project.version = '+' + } + + repositories { + google() + mavenLocal() + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:8.1.4' + classpath 'com.mparticle:android-kit-plugin:' + project.version + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +plugins { + id "org.sonarqube" version "3.5.0.2730" + id "org.jlleitschuh.gradle.ktlint" version "13.0.0" +} + +sonarqube { + properties { + property "sonar.projectKey", "mparticle-android-integration-appboy" + property "sonar.organization", "mparticle" + property "sonar.host.url", "https://sonarcloud.io" + } +} + +apply plugin: 'org.jlleitschuh.gradle.ktlint' +apply plugin: 'kotlin-android' +apply plugin: 'com.mparticle.kit' + +android { + namespace 'com.mparticle.kits.appboy' + buildFeatures { + buildConfig = true + } + defaultConfig { + minSdkVersion 21 + } + lint { + // Workaround for lint internal crash + abortOnError false + // Ignore obsolete custom lint checks from older fragment library + disable 'ObsoleteLintCustomCheck' + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + kotlinOptions { + jvmTarget = '17' + } + testOptions { + unitTests.all { + jvmArgs += ['--add-opens', 'java.base/java.lang=ALL-UNNAMED'] + } + } +} + +repositories { + mavenCentral() +} + +dependencies { + compileOnly 'com.google.firebase:firebase-messaging:[10.2.1, )' + api 'com.braze:android-sdk-ui:37.0.0' + testImplementation files('libs/java-json.jar') +} diff --git a/kits/braze/braze-39/consumer-proguard.pro b/kits/braze/braze-39/consumer-proguard.pro new file mode 100644 index 000000000..84babb199 --- /dev/null +++ b/kits/braze/braze-39/consumer-proguard.pro @@ -0,0 +1,8 @@ +# These are the proguard rules specified by the Appboy SDK's documentation + +-dontwarn com.amazon.device.messaging.** +-dontwarn bo.app.** +-dontwarn com.braze.ui.** +-dontwarn com.google.android.gms.** +-keep class bo.app.** { *; } +-keep class com.braze.** { *; } \ No newline at end of file diff --git a/kits/braze/braze-39/example/build.gradle b/kits/braze/braze-39/example/build.gradle new file mode 100644 index 000000000..b52ca8d32 --- /dev/null +++ b/kits/braze/braze-39/example/build.gradle @@ -0,0 +1,66 @@ +/** + * + * Example app build.gradle for using mParticle + Braze + Firebase Cloud Messaging + * Please see the inline comments below. + * + */ + + +apply plugin: 'com.android.application' + +android { + compileSdk 31 + + defaultConfig { + applicationId "com.mparticle.com.mparticle.kits.braze.example" + minSdk 16 + targetSdk 31 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + + } + + buildTypes { + release { + minifyEnabled false + } + } +} + +repositories { + mavenCentral() + maven { url "https://appboy.github.io/appboy-android-sdk/sdk" } //REQUIRED: Braze isn't available in jCenter or Maven Central - so you need to add their Maven Server + google() +} + +buildscript { + repositories { + //REQUIRED: com.google.gms:google-services requires both jCenter and Google's Maven :rollseyes: + mavenCentral() + google() + } + dependencies { + classpath 'com.google.gms:google-services:4.2.0' //REQUIRED for Firebase + } +} +dependencies { + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support:support-v4:28.0.0' + implementation 'com.android.support:support-media-compat:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + + // REQUIRED: Add the Braze (formerly Appboy) kit here + // this will also pull in mParticle's Core SDK (com.mparticle:android-core) as a transitive dependency + implementation 'com.mparticle:android-appboy-kit:5.6.5' + + // REQUIRED for Firebase + implementation 'com.google.firebase:firebase-messaging:17.3.4' + + // Not strictly required but strongly recommended so that mParticle and Braze can query for the Android Advertising ID + implementation 'com.google.android.gms:play-services-ads-identifier:16.0.0' + +} + +apply plugin: 'com.google.gms.google-services' //REQUIRED for Firebase diff --git a/kits/braze/braze-39/example/src/main/AndroidManifest.xml b/kits/braze/braze-39/example/src/main/AndroidManifest.xml new file mode 100644 index 000000000..d8192e240 --- /dev/null +++ b/kits/braze/braze-39/example/src/main/AndroidManifest.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kits/braze/braze-39/example/src/main/java/com/mparticle/kits/braze/example/MainActivity.java b/kits/braze/braze-39/example/src/main/java/com/mparticle/kits/braze/example/MainActivity.java new file mode 100644 index 000000000..e6254cd12 --- /dev/null +++ b/kits/braze/braze-39/example/src/main/java/com/mparticle/kits/braze/example/MainActivity.java @@ -0,0 +1,13 @@ +package com.mparticle.kits.braze.example; + +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; + +public class MainActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + } +} diff --git a/kits/braze/braze-39/example/src/main/res/drawable-v24/ic_launcher_foreground.xml b/kits/braze/braze-39/example/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 000000000..1f6bb2906 --- /dev/null +++ b/kits/braze/braze-39/example/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/kits/braze/braze-39/example/src/main/res/drawable/ic_launcher_background.xml b/kits/braze/braze-39/example/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 000000000..0d025f9bf --- /dev/null +++ b/kits/braze/braze-39/example/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kits/braze/braze-39/example/src/main/res/layout/activity_main.xml b/kits/braze/braze-39/example/src/main/res/layout/activity_main.xml new file mode 100644 index 000000000..73ddbe136 --- /dev/null +++ b/kits/braze/braze-39/example/src/main/res/layout/activity_main.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/kits/braze/braze-39/example/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/kits/braze/braze-39/example/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 000000000..eca70cfe5 --- /dev/null +++ b/kits/braze/braze-39/example/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/kits/braze/braze-39/example/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/kits/braze/braze-39/example/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 000000000..eca70cfe5 --- /dev/null +++ b/kits/braze/braze-39/example/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/kits/braze/braze-39/example/src/main/res/mipmap-hdpi/ic_launcher.png b/kits/braze/braze-39/example/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..898f3ed59ac9f3248734a00e5902736c9367d455 GIT binary patch literal 2963 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 JPDHLkV1g@XpTGbB literal 0 HcmV?d00001 diff --git a/kits/braze/braze-39/example/src/main/res/mipmap-hdpi/ic_launcher_round.png b/kits/braze/braze-39/example/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..dffca3601eba7bf5f409bdd520820e2eb5122c75 GIT binary patch literal 4905 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 lV%Z2*hu);6rydA(}wUDXPCF_W1vnaRBK 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 literal 0 HcmV?d00001 diff --git a/kits/braze/braze-39/example/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/kits/braze/braze-39/example/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..14ed0af35023e4f1901cf03487b6c524257b8483 GIT binary patch literal 6895 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 literal 0 HcmV?d00001 diff --git a/kits/braze/braze-39/example/src/main/res/mipmap-xxhdpi/ic_launcher.png b/kits/braze/braze-39/example/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..b0907cac3bfd8fbfdc46e1108247f0a1055387ec GIT binary patch literal 6387 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 literal 0 HcmV?d00001 diff --git a/kits/braze/braze-39/example/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/kits/braze/braze-39/example/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..d8ae03154975f397f8ed1b84f2d4bf9783ecfa26 GIT binary patch literal 10413 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 XdJ+W}DiIkV00000NkvXXu0mjfKBlg6 literal 0 HcmV?d00001 diff --git a/kits/braze/braze-39/example/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/kits/braze/braze-39/example/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..2c18de9e66108411737e910f5c1972476f03ddbf GIT binary patch literal 9128 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 I20H400LcNok^lez literal 0 HcmV?d00001 diff --git a/kits/braze/braze-39/example/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/kits/braze/braze-39/example/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..beed3cdd2c32af5114a7dc70b9ef5b698eb8797e GIT binary patch literal 15132 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 literal 0 HcmV?d00001 diff --git a/kits/braze/braze-39/example/src/main/res/values/appboy.xml b/kits/braze/braze-39/example/src/main/res/values/appboy.xml new file mode 100644 index 000000000..21ef222fa --- /dev/null +++ b/kits/braze/braze-39/example/src/main/res/values/appboy.xml @@ -0,0 +1,4 @@ + + + true + \ No newline at end of file diff --git a/kits/braze/braze-39/example/src/main/res/values/colors.xml b/kits/braze/braze-39/example/src/main/res/values/colors.xml new file mode 100644 index 000000000..69b22338c --- /dev/null +++ b/kits/braze/braze-39/example/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #008577 + #00574B + #D81B60 + diff --git a/kits/braze/braze-39/example/src/main/res/values/strings.xml b/kits/braze/braze-39/example/src/main/res/values/strings.xml new file mode 100644 index 000000000..b6c2f04cd --- /dev/null +++ b/kits/braze/braze-39/example/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Braze Example + diff --git a/kits/braze/braze-39/example/src/main/res/values/styles.xml b/kits/braze/braze-39/example/src/main/res/values/styles.xml new file mode 100644 index 000000000..5885930df --- /dev/null +++ b/kits/braze/braze-39/example/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/kits/braze/braze-39/gradle.properties b/kits/braze/braze-39/gradle.properties new file mode 100644 index 000000000..56fb79f85 --- /dev/null +++ b/kits/braze/braze-39/gradle.properties @@ -0,0 +1,4 @@ +android.enableJetifier=true +android.useAndroidX=true +org.gradle.daemon=true + diff --git a/kits/braze/braze-39/gradle/wrapper/gradle-wrapper.jar b/kits/braze/braze-39/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..41d9927a4d4fb3f96a785543079b8df6723c946b GIT binary patch literal 59821 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 literal 0 HcmV?d00001 diff --git a/kits/braze/braze-39/gradle/wrapper/gradle-wrapper.properties b/kits/braze/braze-39/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..e1bef7e87 --- /dev/null +++ b/kits/braze/braze-39/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/kits/braze/braze-39/gradlew b/kits/braze/braze-39/gradlew new file mode 100755 index 000000000..1b6c78733 --- /dev/null +++ b/kits/braze/braze-39/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/kits/braze/braze-39/gradlew.bat b/kits/braze/braze-39/gradlew.bat new file mode 100644 index 000000000..107acd32c --- /dev/null +++ b/kits/braze/braze-39/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/kits/braze/braze-39/libs/java-json.jar b/kits/braze/braze-39/libs/java-json.jar new file mode 100755 index 0000000000000000000000000000000000000000..2f211e3660a0f7637cd055e3dfb011fcc5b4f167 GIT binary patch literal 84697 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%0A^eARL~vZq+#%}VrSrx_m=pVc%a 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

8NQ;9Ans?P}n^>gcO>e>oYyAlbCB*-T|9&C$M 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%0A{lnE||A9G*TwwATGQ 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 CY#!SH literal 0 HcmV?d00001 diff --git a/kits/braze/braze-39/settings.gradle.kts b/kits/braze/braze-39/settings.gradle.kts new file mode 100644 index 000000000..f49fd9f1b --- /dev/null +++ b/kits/braze/braze-39/settings.gradle.kts @@ -0,0 +1,2 @@ +rootProject.name = "android-appboy-kit" +include(":") diff --git a/kits/braze/braze-39/src/main/AndroidManifest.xml b/kits/braze/braze-39/src/main/AndroidManifest.xml new file mode 100644 index 000000000..c4e6c98d7 --- /dev/null +++ b/kits/braze/braze-39/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/kits/braze/braze-39/src/main/kotlin/com/mparticle/kits/AppboyKit.kt b/kits/braze/braze-39/src/main/kotlin/com/mparticle/kits/AppboyKit.kt new file mode 100644 index 000000000..c44edcf3b --- /dev/null +++ b/kits/braze/braze-39/src/main/kotlin/com/mparticle/kits/AppboyKit.kt @@ -0,0 +1,1396 @@ +package com.mparticle.kits + +import android.app.Application +import android.app.Application.ActivityLifecycleCallbacks +import android.content.Context +import android.content.Intent +import android.os.Handler +import com.braze.Braze +import com.braze.BrazeActivityLifecycleCallbackListener +import com.braze.BrazeUser +import com.braze.configuration.BrazeConfig +import com.braze.enums.BrazeSdkMetadata +import com.braze.enums.Gender +import com.braze.enums.Month +import com.braze.enums.NotificationSubscriptionType +import com.braze.enums.SdkFlavor +import com.braze.events.IValueCallback +import com.braze.models.outgoing.BrazeProperties +import com.braze.push.BrazeFirebaseMessagingService +import com.braze.push.BrazeNotificationUtils.isBrazePushMessage +import com.google.firebase.messaging.RemoteMessage +import com.mparticle.MPEvent +import com.mparticle.MParticle +import com.mparticle.MParticle.IdentityType +import com.mparticle.MParticle.UserAttributes +import com.mparticle.commerce.CommerceEvent +import com.mparticle.commerce.Impression +import com.mparticle.commerce.Product +import com.mparticle.commerce.Promotion +import com.mparticle.consent.ConsentState +import com.mparticle.identity.MParticleUser +import com.mparticle.internal.Logger +import com.mparticle.kits.CommerceEventUtils.OnAttributeExtracted +import com.mparticle.kits.KitIntegration.AttributeListener +import com.mparticle.kits.KitIntegration.CommerceListener +import com.mparticle.kits.KitIntegration.EventListener +import com.mparticle.kits.KitIntegration.IdentityListener +import com.mparticle.kits.KitIntegration.PushListener +import com.mparticle.kits.KitIntegration.UserAttributeListener +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject +import java.math.BigDecimal +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Date +import java.util.EnumSet +import java.util.LinkedList +import kotlin.collections.HashMap + +/** + * mParticle client-side Appboy integration + */ +open class AppboyKit : + KitIntegration(), + AttributeListener, + CommerceListener, + KitIntegration.EventListener, + PushListener, + IdentityListener, + KitIntegration.UserAttributeListener { + var enableTypeDetection = false + var bundleCommerceEvents = false + var isMpidIdentityType = false + var identityType: IdentityType? = null + var subscriptionGroupIds: MutableMap? = mutableMapOf() + private val dataFlushHandler = Handler() + private var dataFlushRunnable: Runnable? = null + private var forwardScreenViews = false + private lateinit var updatedInstanceId: String + + override fun getName() = NAME + + public override fun onKitCreate( + settings: Map, + context: Context, + ): List? { + val key = settings[APPBOY_KEY] + require(!KitUtils.isEmpty(key)) { "Braze key is empty." } + + // try to get endpoint from the host setting + val authority = settings[HOST] + if (!KitUtils.isEmpty(authority)) { + setAuthority(authority) + } + val enableDetectionType = settings[ENABLE_TYPE_DETECTION] + if (!KitUtils.isEmpty(enableDetectionType)) { + try { + enableTypeDetection = enableDetectionType.toBoolean() + } catch (e: Exception) { + Logger.warning("Braze, unable to parse \"enableDetectionType\"") + } + } + val bundleCommerce = settings[BUNDLE_COMMERCE_EVENTS] + if (!KitUtils.isEmpty(bundleCommerce)) { + try { + bundleCommerceEvents = bundleCommerce.toBoolean() + } catch (e: Exception) { + bundleCommerceEvents = false + } + } + forwardScreenViews = settings[FORWARD_SCREEN_VIEWS].toBoolean() + subscriptionGroupIds = + settings[SUBSCRIPTION_GROUP_MAPPING] + ?.let { + getSubscriptionGroupIds(it) + } + if (key != null) { + val config = + BrazeConfig + .Builder() + .setApiKey(key) + .setSdkFlavor(SdkFlavor.MPARTICLE) + .setSdkMetadata(EnumSet.of(BrazeSdkMetadata.MPARTICLE)) + .build() + Braze.configure(context, config) + } + dataFlushRunnable = + Runnable { + if (kitManager.isBackgrounded) { + Braze.getInstance(getContext()).requestImmediateDataFlush() + } + } + queueDataFlush() + if (setDefaultAppboyLifecycleCallbackListener) { + (context.applicationContext as Application).registerActivityLifecycleCallbacks( + BrazeActivityLifecycleCallbackListener() as ActivityLifecycleCallbacks, + ) + } + setIdentityType(settings) + + val user = MParticle.getInstance()?.Identity()?.currentUser + if (user != null) { + updateUser(user) + } + val userConsentState = currentUser?.consentState + userConsentState?.let { + setConsent(currentUser.consentState) + } + return null + } + + fun setIdentityType(settings: Map) { + val userIdentificationType = settings[USER_IDENTIFICATION_TYPE] + if (!KitUtils.isEmpty(userIdentificationType)) { + if (userIdentificationType == "MPID") { + isMpidIdentityType = true + } else { + identityType = userIdentificationType?.let { IdentityType.valueOf(it) } + } + } + } + + override fun setOptOut(optedOut: Boolean): List = emptyList() + + override fun leaveBreadcrumb(breadcrumb: String): List = emptyList() + + override fun logError( + message: String, + errorAttributes: Map, + ): List = emptyList() + + override fun logException( + exception: Exception, + exceptionAttributes: Map, + message: String, + ): List = emptyList() + + override fun logEvent(event: MPEvent): List { + val newAttributes: MutableMap = HashMap() + if (event.customAttributes == null) { + Braze.getInstance(context).logCustomEvent(event.eventName) + } else { + val properties = BrazeProperties() + val brazePropertiesSetter = BrazePropertiesSetter(properties, enableTypeDetection) + event.customAttributeStrings?.let { it -> + for ((key, value) in it) { + newAttributes[key] = brazePropertiesSetter.parseValue(key, value) + } + } + Braze.getInstance(context).logCustomEvent(event.eventName, properties) + Braze + .getInstance(context) + .getCurrentUser( + object : IValueCallback { + override fun onSuccess(value: BrazeUser) { + val userAttributeSetter = UserAttributeSetter(value, enableTypeDetection) + event.customAttributeStrings?.let { it -> + for ((key, attributeValue) in it) { + val hashedKey = + KitUtils.hashForFiltering(event.eventType.value.toString() + event.eventName + key) + + configuration.eventAttributesAddToUser?.get(hashedKey)?.let { + value.addToCustomAttributeArray(it, attributeValue) + } + configuration.eventAttributesRemoveFromUser?.get(hashedKey)?.let { + value.removeFromCustomAttributeArray(it, attributeValue) + } + configuration.eventAttributesSingleItemUser?.get(hashedKey)?.let { + userAttributeSetter.parseValue(it, attributeValue) + } + } + } + } + + override fun onError() { + Logger.warning("unable to acquire user to add or remove custom user attributes from events") + } + }, + ) + } + queueDataFlush() + return listOf(ReportingMessage.fromEvent(this, event).setAttributes(newAttributes)) + } + + override fun logScreen( + screenName: String, + screenAttributes: Map?, + ): List = + if (forwardScreenViews) { + if (screenAttributes == null) { + Braze.getInstance(context).logCustomEvent(screenName) + } else { + val properties = BrazeProperties() + val propertyParser = BrazePropertiesSetter(properties, enableTypeDetection) + for ((key, value) in screenAttributes) { + propertyParser.parseValue(key, value) + } + Braze.getInstance(context).logCustomEvent(screenName, properties) + } + queueDataFlush() + val messages: MutableList = LinkedList() + messages.add( + ReportingMessage( + this, + ReportingMessage.MessageType.SCREEN_VIEW, + System.currentTimeMillis(), + screenAttributes, + ), + ) + messages + } else { + emptyList() + } + + override fun logLtvIncrease( + valueIncreased: BigDecimal, + valueTotal: BigDecimal, + eventName: String, + contextInfo: Map, + ): List = emptyList() + + override fun logEvent(event: CommerceEvent): List { + val messages: MutableList = LinkedList() + if (!KitUtils.isEmpty(event.productAction) && + event.productAction.equals( + Product.PURCHASE, + true, + ) && + !event.products.isNullOrEmpty() + ) { + if (bundleCommerceEvents) { + logOrderLevelTransaction(event) + messages.add(ReportingMessage.fromEvent(this, event)) + } else { + val productList = event.products + productList?.let { + for (product in productList) { + logTransaction(event, product) + } + } + } + messages.add(ReportingMessage.fromEvent(this, event)) + } else { + if (bundleCommerceEvents) { + logOrderLevelTransaction(event) + messages.add(ReportingMessage.fromEvent(this, event)) + } else { + val eventList = CommerceEventUtils.expand(event) + if (eventList != null) { + for (i in eventList.indices) { + try { + val e = eventList[i] + val map = mutableMapOf() + event.customAttributeStrings?.let { map.putAll(it) } + for (pair in map) { + e.customAttributes?.put(pair.key, pair.value) + } + logEvent(e) + messages.add(ReportingMessage.fromEvent(this, event)) + } catch (e: Exception) { + Logger.warning("Failed to call logCustomEvent to Appboy kit: $e") + } + } + } + } + } + queueDataFlush() + return messages + } + + override fun setUserAttribute( + keyIn: String, + attributeValue: String, + ) { + var key = keyIn + Braze + .getInstance(context) + .getCurrentUser( + object : IValueCallback { + override fun onSuccess(value: BrazeUser) { + val userAttributeSetter = UserAttributeSetter(value, enableTypeDetection) + + when (key) { + UserAttributes.CITY -> value.setHomeCity(attributeValue) + UserAttributes.COUNTRY -> value.setCountry(attributeValue) + UserAttributes.FIRSTNAME -> value.setFirstName(attributeValue) + UserAttributes.LASTNAME -> value.setLastName(attributeValue) + UserAttributes.MOBILE_NUMBER -> value.setPhoneNumber(attributeValue) + UserAttributes.ZIPCODE -> value.setCustomUserAttribute("Zip", attributeValue) + UserAttributes.AGE -> { + val calendar = getCalendarMinusYears(attributeValue) + if (calendar != null) { + value.setDateOfBirth(calendar[Calendar.YEAR], Month.JANUARY, 1) + } else { + Logger.warning("unable to set DateOfBirth for " + UserAttributes.AGE + " = " + value) + } + } + EMAIL_SUBSCRIBE -> { + when (attributeValue) { + OPTED_IN -> value.setEmailNotificationSubscriptionType(NotificationSubscriptionType.OPTED_IN) + UNSUBSCRIBED -> value.setEmailNotificationSubscriptionType(NotificationSubscriptionType.UNSUBSCRIBED) + SUBSCRIBED -> value.setEmailNotificationSubscriptionType(NotificationSubscriptionType.SUBSCRIBED) + else -> { + Logger.warning("unable to set email_subscribe with invalid value: " + value) + } + } + } + PUSH_SUBSCRIBE -> { + when (attributeValue) { + OPTED_IN -> value.setPushNotificationSubscriptionType(NotificationSubscriptionType.OPTED_IN) + UNSUBSCRIBED -> value.setPushNotificationSubscriptionType(NotificationSubscriptionType.UNSUBSCRIBED) + SUBSCRIBED -> value.setPushNotificationSubscriptionType(NotificationSubscriptionType.SUBSCRIBED) + else -> { + Logger.warning("unable to set push_subscribe with invalid value: " + value) + } + } + } + DOB -> useDobString(attributeValue, value) + UserAttributes.GENDER -> { + if (attributeValue.contains("fe")) { + value.setGender(Gender.FEMALE) + } else { + value.setGender(Gender.MALE) + } + } + else -> { + if (subscriptionGroupIds?.containsKey(key) == true) { + val groupId = subscriptionGroupIds?.get(key) + when (attributeValue.lowercase()) { + "true" -> { + groupId?.let { value.addToSubscriptionGroup(it) } + } + + "false" -> { + groupId?.let { value.removeFromSubscriptionGroup(it) } + } + + else -> { + Logger.warning( + "Unable to set Subscription Group ID for user attribute: $key due to invalid value data type. Expected Boolean.", + ) + } + } + } else { + if (key.startsWith("$")) { + key = key.substring(1) + } + userAttributeSetter?.parseValue(key, attributeValue) + } + } + } + queueDataFlush() + } + + override fun onError() { + Logger.warning("unable to set key: " + key + " with value: " + attributeValue) + } + }, + ) + } + + // Expected Date Format @"yyyy'-'MM'-'dd" + private fun useDobString( + value: String, + user: BrazeUser, + ) { + val dateFormat = SimpleDateFormat("yyyy-MM-dd") + try { + val calendar = Calendar.getInstance() + calendar.time = dateFormat.parse(value) as Date + val year = calendar[Calendar.YEAR] + val monthNum = calendar[Calendar.MONTH] + val month = Month.values()[monthNum] // + val day = calendar[Calendar.DAY_OF_MONTH] + user.setDateOfBirth(year, month, day) + } catch (e: Exception) { + Logger.warning("unable to set DateOfBirth for \"dob\" = " + value + ". Exception: " + e.message) + } + } + + override fun setUserAttributeList( + key: String, + list: List, + ) { + Braze + .getInstance(context) + .getCurrentUser( + object : IValueCallback { + override fun onSuccess(value: BrazeUser) { + val array = list.toTypedArray() + value.setCustomAttributeArray(key, array) + queueDataFlush() + } + + override fun onError() { + Logger.warning("unable to set key: " + key + " with User Attribute List: " + list) + } + }, + ) + } + + override fun onIncrementUserAttribute( + key: String?, + incrementedBy: Number?, + value: String?, + user: FilteredMParticleUser?, + ) { + } + + override fun onRemoveUserAttribute( + key: String?, + user: FilteredMParticleUser?, + ) { + } + + override fun onSetUserAttribute( + key: String?, + value: Any?, + user: FilteredMParticleUser?, + ) { + } + + override fun onSetUserTag( + key: String?, + user: FilteredMParticleUser?, + ) { + } + + override fun onSetUserAttributeList( + attributeKey: String?, + attributeValueList: MutableList?, + user: FilteredMParticleUser?, + ) { + } + + override fun onSetAllUserAttributes( + userAttributes: MutableMap?, + userAttributeLists: MutableMap>?, + user: FilteredMParticleUser?, + ) { + } + + override fun supportsAttributeLists(): Boolean = true + + override fun onConsentStateUpdated( + oldState: ConsentState, + newState: ConsentState, + user: FilteredMParticleUser, + ) { + setConsent(newState) + } + + private fun setConsent(consentState: ConsentState) { + val clientConsentSettings = parseToNestedMap(consentState.toString()) + + parseConsentMapping(settings[CONSENT_MAPPING_SDK]).iterator().forEach { currentConsent -> + val isConsentAvailable = + searchKeyInNestedMap(clientConsentSettings, key = currentConsent.key) + + if (isConsentAvailable != null) { + val isConsentGranted: Boolean = + JSONObject(isConsentAvailable.toString()).opt("consented") as Boolean + + when (currentConsent.value) { + "google_ad_user_data" -> + setConsentValueToBraze( + KEY_GOOGLE_AD_USER_DATA, + isConsentGranted, + ) + + "google_ad_personalization" -> + setConsentValueToBraze( + KEY_GOOGLE_AD_PERSONALIZATION, + isConsentGranted, + ) + } + } + } + } + + private fun setConsentValueToBraze( + key: String, + value: Boolean, + ) { + Braze + .getInstance(context) + .getCurrentUser( + object : IValueCallback { + override fun onSuccess(brazeUser: BrazeUser) { + brazeUser.setCustomUserAttribute(key, value) + } + + override fun onError() { + super.onError() + } + }, + ) + } + + private fun parseConsentMapping(json: String?): Map { + if (json.isNullOrEmpty()) { + return emptyMap() + } + val jsonWithFormat = json.replace("\\", "") + + return try { + JSONArray(jsonWithFormat) + .let { jsonArray -> + (0 until jsonArray.length()) + .associate { + val jsonObject = jsonArray.getJSONObject(it) + val map = jsonObject.getString("map") + val value = jsonObject.getString("value") + map to value + } + } + } catch (jse: JSONException) { + Logger.warning( + jse, + "The Braze kit threw an exception while searching for the configured consent purpose mapping in the current user's consent status.", + ) + emptyMap() + } + } + + private fun parseToNestedMap(jsonString: String): Map { + val topLevelMap = mutableMapOf() + try { + val jsonObject = JSONObject(jsonString) + + for (key in jsonObject.keys()) { + val value = jsonObject.get(key) + if (value is JSONObject) { + topLevelMap[key] = parseToNestedMap(value.toString()) + } else { + topLevelMap[key] = value + } + } + } catch (e: Exception) { + Logger.error(e, "The Braze kit was unable to parse the user's ConsentState, consent may not be set correctly on the Braze SDK") + } + return topLevelMap + } + + private fun searchKeyInNestedMap( + map: Map<*, *>, + key: Any, + ): Any? { + if (map.isNullOrEmpty()) { + return null + } + try { + for ((mapKey, mapValue) in map) { + if (mapKey.toString().equals(key.toString(), ignoreCase = true)) { + return mapValue + } + if (mapValue is Map<*, *>) { + val foundValue = searchKeyInNestedMap(mapValue, key) + if (foundValue != null) { + return foundValue + } + } + } + } catch (e: Exception) { + Logger.error( + e, + "The Braze kit threw an exception while searching for the configured consent purpose mapping in the current user's consent status.", + ) + } + return null + } + + protected open fun queueDataFlush() { + dataFlushRunnable?.let { dataFlushHandler.removeCallbacks(it) } + dataFlushRunnable?.let { dataFlushHandler.postDelayed(it, FLUSH_DELAY.toLong()) } + } + + /** + * This is called when the Kit is added to the mParticle SDK, typically on app-startup. + */ + override fun setAllUserAttributes( + attributes: Map, + attributeLists: Map>, + ) { + if (!kitPreferences.getBoolean(PREF_KEY_HAS_SYNCED_ATTRIBUTES, false)) { + for ((key, value) in attributes) { + setUserAttribute(key, value) + } + for ((key, value) in attributeLists) { + setUserAttributeList(key, value) + } + kitPreferences.edit().putBoolean(PREF_KEY_HAS_SYNCED_ATTRIBUTES, true).apply() + } + } + + override fun removeUserAttribute(keyIn: String) { + var key = keyIn + Braze + .getInstance(context) + .getCurrentUser( + object : IValueCallback { + override fun onSuccess(value: BrazeUser) { + if (UserAttributes.CITY == key) { + value.setHomeCity(null) + } else if (UserAttributes.COUNTRY == key) { + value.setCountry(null) + } else if (UserAttributes.FIRSTNAME == key) { + value.setFirstName(null) + } else if (UserAttributes.LASTNAME == key) { + value.setLastName(null) + } else if (UserAttributes.MOBILE_NUMBER == key) { + value.setPhoneNumber(null) + } else { + if (key.startsWith("$")) { + key = key.substring(1) + } + value.unsetCustomUserAttribute(key) + } + queueDataFlush() + } + + override fun onError() { + Logger.warning("unable to remove User Attribute with key: " + key) + } + }, + ) + } + + override fun setUserIdentity( + identityType: IdentityType, + identity: String, + ) {} + + override fun removeUserIdentity(identityType: IdentityType) {} + + override fun logout(): List = emptyList() + + fun logTransaction( + event: CommerceEvent?, + product: Product, + ) { + val purchaseProperties = BrazeProperties() + val currency = arrayOfNulls(1) + val commerceTypeParser: StringTypeParser = + BrazePropertiesSetter( + purchaseProperties, + enableTypeDetection, + ) + val onAttributeExtracted: OnAttributeExtracted = + object : OnAttributeExtracted { + override fun onAttributeExtracted( + key: String, + value: String, + ) { + if (!checkCurrency(key, value)) { + commerceTypeParser.parseValue(key, value) + } + } + + override fun onAttributeExtracted( + key: String, + value: Double, + ) { + if (!checkCurrency(key, value)) { + purchaseProperties.addProperty(key, value) + } + } + + override fun onAttributeExtracted( + key: String, + value: Int, + ) { + purchaseProperties.addProperty(key, value) + } + + override fun onAttributeExtracted(attributes: Map) { + for ((key, value) in attributes) { + if (!checkCurrency(key, value)) { + commerceTypeParser.parseValue(key, value) + } + } + } + + private fun checkCurrency( + key: String, + value: Any?, + ): Boolean = + if (CommerceEventUtils.Constants.ATT_ACTION_CURRENCY_CODE == + key + ) { + currency[0] = value?.toString() + true + } else { + false + } + } + CommerceEventUtils.extractActionAttributes(event, onAttributeExtracted) + var currencyValue = currency[0] + if (KitUtils.isEmpty(currencyValue)) { + currencyValue = CommerceEventUtils.Constants.DEFAULT_CURRENCY_CODE + } + + event?.customAttributes?.let { + for ((key, value) in it) { + purchaseProperties.addProperty(key, value) + } + } + + product.couponCode?.let { + purchaseProperties.addProperty( + CommerceEventUtils.Constants.ATT_PRODUCT_COUPON_CODE, + it, + ) + } + product.brand?.let { + purchaseProperties.addProperty(CommerceEventUtils.Constants.ATT_PRODUCT_BRAND, it) + } + product.category?.let { + purchaseProperties.addProperty(CommerceEventUtils.Constants.ATT_PRODUCT_CATEGORY, it) + } + product.name.let { + purchaseProperties.addProperty(CommerceEventUtils.Constants.ATT_PRODUCT_NAME, it) + } + product.variant?.let { + purchaseProperties.addProperty(CommerceEventUtils.Constants.ATT_PRODUCT_VARIANT, it) + } + product.position?.let { + purchaseProperties.addProperty(CommerceEventUtils.Constants.ATT_PRODUCT_POSITION, it) + } + product.customAttributes?.let { + for ((key, value) in it) { + purchaseProperties.addProperty(key, value) + } + } + + var sanitizedProductName: String = product.sku + try { + if (settings[REPLACE_SKU_AS_PRODUCT_NAME] == "True") { + sanitizedProductName = product.name + } + } catch (e: Exception) { + Logger.error(e, "The Braze kit threw an exception while searching for forward sku as product name flag.") + } + + Braze.Companion.getInstance(context).logPurchase( + sanitizedProductName, + currencyValue, + BigDecimal(product.unitPrice), + product.quantity.toInt(), + purchaseProperties, + ) + } + + fun logOrderLevelTransaction(event: CommerceEvent?) { + val properties = BrazeProperties() + val currency = arrayOfNulls(1) + val commerceTypeParser: StringTypeParser = + BrazePropertiesSetter( + properties, + enableTypeDetection, + ) + val onAttributeExtracted: OnAttributeExtracted = + object : OnAttributeExtracted { + override fun onAttributeExtracted( + key: String, + value: String, + ) { + if (!checkCurrency(key, value)) { + commerceTypeParser.parseValue(key, value) + } + } + + override fun onAttributeExtracted( + key: String, + value: Double, + ) { + if (!checkCurrency(key, value)) { + properties.addProperty(key, value) + } + } + + override fun onAttributeExtracted( + key: String, + value: Int, + ) { + properties.addProperty(key, value) + } + + override fun onAttributeExtracted(attributes: Map) { + for ((key, value) in attributes) { + if (!checkCurrency(key, value)) { + commerceTypeParser.parseValue(key, value) + } + } + } + + private fun checkCurrency( + key: String, + value: Any?, + ): Boolean = + if (CommerceEventUtils.Constants.ATT_ACTION_CURRENCY_CODE == + key + ) { + currency[0] = value?.toString() + true + } else { + false + } + } + CommerceEventUtils.extractActionAttributes(event, onAttributeExtracted) + var currencyValue = currency[0] + if (KitUtils.isEmpty(currencyValue)) { + currencyValue = CommerceEventUtils.Constants.DEFAULT_CURRENCY_CODE + } + + event?.customAttributes?.let { + properties.addProperty(CUSTOM_ATTRIBUTES_KEY, it) + } + + val productList = event?.products + productList?.let { + val productArray = getProductListParameters(it) + properties.addProperty(PRODUCT_KEY, productArray) + } + + val promotionList = event?.promotions + promotionList?.let { + val promotionArray = getPromotionListParameters(it) + properties.addProperty(PROMOTION_KEY, promotionArray) + } + + val impressionList = event?.impressions + impressionList?.let { + val impressionArray = getImpressionListParameters(it) + properties.addProperty(IMPRESSION_KEY, impressionArray) + } + + val eventName = "eCommerce - %s" + if (!KitUtils.isEmpty(event?.productAction) && + event?.productAction.equals(Product.PURCHASE, true) + ) { + Braze.Companion.getInstance(context).logPurchase( + String.format(eventName, event?.productAction), + currencyValue, + event?.transactionAttributes?.revenue?.let { BigDecimal(it) } ?: BigDecimal(0), + 1, + properties, + ) + } else { + if (!KitUtils.isEmpty(event?.productAction)) { + Braze + .getInstance(context) + .logCustomEvent( + String.format(eventName, event?.productAction), + properties, + ) + } else if (!KitUtils.isEmpty(event?.promotionAction)) { + Braze + .getInstance(context) + .logCustomEvent( + String.format(eventName, event?.promotionAction), + properties, + ) + } else { + Braze + .getInstance(context) + .logCustomEvent( + String.format(eventName, "Impression"), + properties, + ) + } + } + } + + override fun willHandlePushMessage(intent: Intent): Boolean = + if (!(settings[PUSH_ENABLED].toBoolean())) { + false + } else { + intent.isBrazePushMessage() + } + + override fun onPushMessageReceived( + context: Context, + pushIntent: Intent, + ) { + if (settings[PUSH_ENABLED].toBoolean()) { + BrazeFirebaseMessagingService.handleBrazeRemoteMessage( + context, + RemoteMessage(pushIntent.extras), + ) + } + } + + override fun onPushRegistration( + instanceId: String, + senderId: String, + ): Boolean = + if (settings[PUSH_ENABLED].toBoolean()) { + updatedInstanceId = instanceId + Braze.getInstance(context).registeredPushToken = instanceId + queueDataFlush() + true + } else { + false + } + + protected open fun setAuthority(authority: String?) { + Braze.setEndpointProvider { appboyEndpoint -> + appboyEndpoint + .buildUpon() + .authority(authority) + .build() + } + } + + override fun onIdentifyCompleted( + mParticleUser: MParticleUser, + filteredIdentityApiRequest: FilteredIdentityApiRequest?, + ) { + updateUser(mParticleUser) + } + + override fun onLoginCompleted( + mParticleUser: MParticleUser, + filteredIdentityApiRequest: FilteredIdentityApiRequest?, + ) { + updateUser(mParticleUser) + } + + override fun onLogoutCompleted( + mParticleUser: MParticleUser, + filteredIdentityApiRequest: FilteredIdentityApiRequest?, + ) { + updateUser(mParticleUser) + } + + override fun onModifyCompleted( + mParticleUser: MParticleUser, + filteredIdentityApiRequest: FilteredIdentityApiRequest?, + ) { + updateUser(mParticleUser) + } + + private fun updateUser(mParticleUser: MParticleUser) { + val identity = getIdentity(isMpidIdentityType, identityType, mParticleUser) + val email = mParticleUser.userIdentities[IdentityType.Email] + identity?.let { setId(it) } + email?.let { setEmail(it) } + } + + fun getIdentity( + isMpidIdentityType: Boolean, + identityType: IdentityType?, + mParticleUser: MParticleUser?, + ): String? { + var identity: String? = null + if (isMpidIdentityType && mParticleUser != null) { + identity = mParticleUser.id.toString() + } else if (identityType != null && mParticleUser != null) { + identity = mParticleUser.userIdentities[identityType] + } + return identity + } + + protected open fun setId(customerId: String) { + Braze + .getInstance(context) + .getCurrentUser( + object : IValueCallback { + override fun onSuccess(value: BrazeUser) { + if (value.userId != customerId) { + Braze.getInstance(context).changeUser(customerId) + queueDataFlush() + } + } + + override fun onError() { + Logger.warning("unable to change user to customer ID: " + customerId) + } + }, + ) + } + + protected open fun setEmail(email: String) { + if (email != kitPreferences.getString(PREF_KEY_CURRENT_EMAIL, null)) { + Braze + .getInstance(context) + .getCurrentUser( + object : IValueCallback { + override fun onSuccess(value: BrazeUser) { + value.setEmail(email) + queueDataFlush() + kitPreferences + .edit() + .putString(PREF_KEY_CURRENT_EMAIL, email) + .apply() + } + + override fun onError() { + Logger.warning("unable to set email with value: " + email) + } + }, + ) + } + } + + override fun onUserIdentified(mParticleUser: MParticleUser) { + if (updatedInstanceId.isNotEmpty()) { + Braze.getInstance(context).registeredPushToken = updatedInstanceId + } + } + + fun addToProperties( + properties: BrazeProperties, + key: String, + value: String, + ) { + try { + if ("true".equals(value, true) || + "false".equals( + value, + true, + ) + ) { + properties.addProperty(key, (value).toBoolean()) + } else { + val doubleValue = value.toDouble() + if (doubleValue % 1 == 0.0) { + properties.addProperty(key, value.toInt()) + } else { + properties.addProperty(key, doubleValue) + } + } + } catch (e: Exception) { + properties.addProperty(key, value) + } + } + + fun getCalendarMinusYears(yearsString: String): Calendar? { + try { + val years = yearsString.toInt() + return getCalendarMinusYears(years) + } catch (ignored: NumberFormatException) { + try { + val years = yearsString.toDouble() + return getCalendarMinusYears(years.toInt()) + } catch (ignoredToo: NumberFormatException) { + } + } + return null + } + + fun getCalendarMinusYears(years: Int): Calendar? = + if (years >= 0) { + val calendar = Calendar.getInstance() + calendar[Calendar.YEAR] = calendar[Calendar.YEAR] - years + calendar + } else { + null + } + + fun getProductListParameters(productList: List): JSONArray { + val productArray = JSONArray() + for ((i, product) in productList.withIndex()) { + val productProperties = JSONObject() + + product.customAttributes?.let { + productProperties.put(CUSTOM_ATTRIBUTES_KEY, it) + } + product.couponCode?.let { + productProperties.put( + CommerceEventUtils.Constants.ATT_PRODUCT_COUPON_CODE, + it, + ) + } + product.brand?.let { + productProperties.put(CommerceEventUtils.Constants.ATT_PRODUCT_BRAND, it) + } + product.category?.let { + productProperties.put(CommerceEventUtils.Constants.ATT_PRODUCT_CATEGORY, it) + } + product.name?.let { + productProperties.put(CommerceEventUtils.Constants.ATT_PRODUCT_NAME, it) + } + product.sku?.let { + productProperties.put(CommerceEventUtils.Constants.ATT_PRODUCT_ID, it) + } + product.variant?.let { + productProperties.put(CommerceEventUtils.Constants.ATT_PRODUCT_VARIANT, it) + } + product.position?.let { + productProperties.put(CommerceEventUtils.Constants.ATT_PRODUCT_POSITION, it) + } + productProperties.put( + CommerceEventUtils.Constants.ATT_PRODUCT_PRICE, + product.unitPrice, + ) + productProperties.put( + CommerceEventUtils.Constants.ATT_PRODUCT_QUANTITY, + product.quantity, + ) + productProperties.put( + CommerceEventUtils.Constants.ATT_PRODUCT_TOTAL_AMOUNT, + product.totalAmount, + ) + + productArray.put(productProperties) + } + return productArray + } + + fun getPromotionListParameters(promotionList: List): JSONArray { + val promotionArray = JSONArray() + for ((i, promotion) in promotionList.withIndex()) { + val promotionProperties = JSONObject() + promotion.creative?.let { + promotionProperties.put( + CommerceEventUtils.Constants.ATT_PROMOTION_CREATIVE, + it, + ) + } + promotion.id?.let { + promotionProperties.put(CommerceEventUtils.Constants.ATT_PROMOTION_ID, it) + } + promotion.name?.let { + promotionProperties.put(CommerceEventUtils.Constants.ATT_PROMOTION_NAME, it) + } + promotion.position?.let { + promotionProperties.put( + CommerceEventUtils.Constants.ATT_PROMOTION_POSITION, + it, + ) + } + promotionArray.put(promotionProperties) + } + return promotionArray + } + + private fun getSubscriptionGroupIds(subscriptionGroupMap: String): MutableMap { + val subscriptionGroupIds = mutableMapOf() + + if (subscriptionGroupMap.isEmpty()) { + return subscriptionGroupIds + } + + val subscriptionGroupsArray = JSONArray(subscriptionGroupMap) + + return try { + for (i in 0 until subscriptionGroupsArray.length()) { + val subscriptionGroup = subscriptionGroupsArray.getJSONObject(i) + val key = subscriptionGroup.getString("map") + val value = subscriptionGroup.getString("value") + subscriptionGroupIds[key] = value + } + subscriptionGroupIds + } catch (e: JSONException) { + Logger.warning("Braze, unable to parse \"subscriptionGroup\"") + mutableMapOf() + } + } + + fun getImpressionListParameters(impressionList: List): JSONArray { + val impressionArray = JSONArray() + for ((i, impression) in impressionList.withIndex()) { + val impressionProperties = JSONObject() + impression.listName?.let { + impressionProperties.put("Product Impression List", it) + } + impression.products?.let { + val productArray = getProductListParameters(it) + impressionProperties.put(PRODUCT_KEY, productArray) + } + impressionArray.put(impressionProperties) + } + return impressionArray + } + + internal abstract class StringTypeParser( + var enableTypeDetection: Boolean, + ) { + fun parseValue( + key: String, + value: String, + ): Any { + if (!enableTypeDetection) { + toString(key, value) + return value + } + return if ( + true.toString().equals(value, true) || + false.toString().equals( + value, + true, + ) + ) { + val newBool = (value).toBoolean() + toBoolean(key, newBool) + newBool + } else { + try { + if (value.contains(".")) { + val doubleValue = value.toDouble() + toDouble(key, doubleValue) + doubleValue + } else { + val newLong = value.toLong() + if (newLong <= Int.MAX_VALUE && newLong >= Int.MIN_VALUE) { + val newInt = newLong.toInt() + toInt(key, newInt) + newInt + } else { + toLong(key, newLong) + newLong + } + } + } catch (nfe: NumberFormatException) { + toString(key, value) + value + } + } + } + + abstract fun toInt( + key: String, + value: Int, + ) + + abstract fun toLong( + key: String, + value: Long, + ) + + abstract fun toDouble( + key: String, + value: Double, + ) + + abstract fun toBoolean( + key: String, + value: Boolean, + ) + + abstract fun toString( + key: String, + value: String, + ) + } + + internal inner class BrazePropertiesSetter( + private var properties: BrazeProperties, + enableTypeDetection: Boolean, + ) : StringTypeParser(enableTypeDetection) { + override fun toInt( + key: String, + value: Int, + ) { + properties.addProperty(key, value) + } + + override fun toLong( + key: String, + value: Long, + ) { + properties.addProperty(key, value) + } + + override fun toDouble( + key: String, + value: Double, + ) { + properties.addProperty(key, value) + } + + override fun toBoolean( + key: String, + value: Boolean, + ) { + properties.addProperty(key, value) + } + + override fun toString( + key: String, + value: String, + ) { + properties.addProperty(key, value) + } + } + + internal inner class UserAttributeSetter( + private var brazeUser: BrazeUser, + enableTypeDetection: Boolean, + ) : StringTypeParser(enableTypeDetection) { + override fun toInt( + key: String, + value: Int, + ) { + brazeUser.setCustomUserAttribute(key, value) + } + + override fun toLong( + key: String, + value: Long, + ) { + brazeUser.setCustomUserAttribute(key, value) + } + + override fun toDouble( + key: String, + value: Double, + ) { + brazeUser.setCustomUserAttribute(key, value) + } + + override fun toBoolean( + key: String, + value: Boolean, + ) { + brazeUser.setCustomUserAttribute(key, value) + } + + override fun toString( + key: String, + value: String, + ) { + brazeUser.setCustomUserAttribute(key, value) + } + } + + companion object { + const val APPBOY_KEY = "apiKey" + const val FORWARD_SCREEN_VIEWS = "forwardScreenViews" + const val USER_IDENTIFICATION_TYPE = "userIdentificationType" + const val ENABLE_TYPE_DETECTION = "enableTypeDetection" + const val BUNDLE_COMMERCE_EVENTS = "bundleCommerceEventData" + const val SUBSCRIPTION_GROUP_MAPPING = "subscriptionGroupMapping" + const val HOST = "host" + const val PUSH_ENABLED = "push_enabled" + const val NAME = "Appboy" + + // if this flag is true, kit will send Product name as sku + const val REPLACE_SKU_AS_PRODUCT_NAME = "replaceSkuWithProductName" + private const val PREF_KEY_HAS_SYNCED_ATTRIBUTES = "appboy::has_synced_attributes" + private const val PREF_KEY_CURRENT_EMAIL = "appboy::current_email" + private const val FLUSH_DELAY = 5000 + var setDefaultAppboyLifecycleCallbackListener = true + + private const val EMAIL_SUBSCRIBE = "email_subscribe" + private const val PUSH_SUBSCRIBE = "push_subscribe" + private const val DOB = "dob" + + private const val OPTED_IN = "opted_in" + private const val UNSUBSCRIBED = "unsubscribed" + private const val SUBSCRIBED = "subscribed" + + // Constants for Read Consent + private const val CONSENT_MAPPING_SDK = "consentMappingSDK" + private const val KEY_GOOGLE_AD_USER_DATA = "\$google_ad_user_data" + private const val KEY_GOOGLE_AD_PERSONALIZATION = "\$google_ad_personalization" + + const val CUSTOM_ATTRIBUTES_KEY = "Attributes" + const val PRODUCT_KEY = "products" + const val PROMOTION_KEY = "promotions" + const val IMPRESSION_KEY = "impressions" + } +} diff --git a/kits/braze/braze-39/src/test/kotlin/com/braze/Braze.kt b/kits/braze/braze-39/src/test/kotlin/com/braze/Braze.kt new file mode 100644 index 000000000..f2ebeffe7 --- /dev/null +++ b/kits/braze/braze-39/src/test/kotlin/com/braze/Braze.kt @@ -0,0 +1,63 @@ +package com.braze + +import android.content.Context +import com.braze.configuration.BrazeConfig +import com.braze.events.IValueCallback +import com.braze.models.outgoing.BrazeProperties +import com.mparticle.kits.BrazePurchase +import java.math.BigDecimal + +class Braze { + fun getCurrentUser(): BrazeUser = Companion.currentUser + + fun getCustomAttributeArray(): java.util.HashMap> = Companion.currentUser.getCustomAttribute() + + fun getCurrentUser(callback: IValueCallback) { + callback.onSuccess(currentUser) + } + + fun logCustomEvent( + key: String, + brazeProperties: BrazeProperties, + ) { + events[key] = brazeProperties + } + + fun logCustomEvent(key: String) { + events[key] = BrazeProperties() + } + + fun logPurchase( + sku: String, + currency: String, + unitPrice: BigDecimal, + quantity: Int, + purchaseProperties: BrazeProperties, + ) { + purchases.add(BrazePurchase(sku, currency, unitPrice, quantity, purchaseProperties)) + } + + companion object { + val purchases: MutableList = ArrayList() + val events: MutableMap = HashMap() + + fun clearPurchases() { + purchases.clear() + } + + fun clearEvents() { + events.clear() + } + + val currentUser = BrazeUser() + + @JvmStatic + fun configure( + context: Context?, + config: BrazeConfig?, + ) = true + + @JvmStatic + fun getInstance(context: Context?): Braze = Braze() + } +} diff --git a/kits/braze/braze-39/src/test/kotlin/com/braze/BrazeUser.kt b/kits/braze/braze-39/src/test/kotlin/com/braze/BrazeUser.kt new file mode 100644 index 000000000..13983911e --- /dev/null +++ b/kits/braze/braze-39/src/test/kotlin/com/braze/BrazeUser.kt @@ -0,0 +1,95 @@ +package com.braze + +import com.braze.enums.Month + +class BrazeUser { + var dobYear = -1 + var dobMonth: Month? = null + var dobDay = -1 + + fun setDateOfBirth( + year: Int, + month: Month?, + day: Int, + ): Boolean { + dobYear = year + dobMonth = month + dobDay = day + return true + } + + val customAttributeArray = HashMap>() + val customUserAttributes = HashMap() + + fun addToCustomAttributeArray( + key: String, + value: String, + ): Boolean { + var customArray = customAttributeArray[key] + if (customArray == null) { + customArray = ArrayList() + } + customArray.add(value) + customAttributeArray[key] = customArray + return true + } + + fun removeFromCustomAttributeArray( + key: String, + value: String, + ): Boolean = + try { + if (customAttributeArray.containsKey(key)) { + customAttributeArray.remove(key) + } + true + } catch (npe: NullPointerException) { + false + } + + fun setCustomUserAttribute( + key: String, + value: String, + ): Boolean { + customUserAttributes[key] = value + return true + } + + fun setCustomUserAttribute( + key: String, + value: Boolean, + ): Boolean { + customUserAttributes[key] = value + return true + } + + fun setCustomUserAttribute( + key: String, + value: Int, + ): Boolean { + customUserAttributes[key] = value + return true + } + + fun setCustomUserAttribute( + key: String, + value: Double, + ): Boolean { + customUserAttributes[key] = value + return true + } + + fun addToSubscriptionGroup(key: String): Boolean { + customUserAttributes[key] = true + return true + } + + fun removeFromSubscriptionGroup(key: String): Boolean { + customUserAttributes[key] = false + return true + } + + fun getCustomAttribute(): HashMap> = customAttributeArray + + fun getCustomUserAttribute(): HashMap = customUserAttributes +} diff --git a/kits/braze/braze-39/src/test/kotlin/com/braze/models/outgoing/BrazeProperties.kt b/kits/braze/braze-39/src/test/kotlin/com/braze/models/outgoing/BrazeProperties.kt new file mode 100644 index 000000000..e36de6578 --- /dev/null +++ b/kits/braze/braze-39/src/test/kotlin/com/braze/models/outgoing/BrazeProperties.kt @@ -0,0 +1,55 @@ +package com.braze.models.outgoing + +import java.util.HashMap + +class BrazeProperties { + val properties = HashMap() + + fun addProperty( + key: String, + value: Long, + ): BrazeProperties { + properties[key] = value + return this + } + + fun addProperty( + key: String, + value: Int, + ): BrazeProperties { + properties[key] = value + return this + } + + fun addProperty( + key: String, + value: String, + ): BrazeProperties { + properties[key] = value + return this + } + + fun addProperty( + key: String, + value: Double, + ): BrazeProperties { + properties[key] = value + return this + } + + fun addProperty( + key: String, + value: Boolean, + ): BrazeProperties { + properties[key] = value + return this + } + + fun addProperty( + key: String, + value: Any, + ): BrazeProperties { + properties[key] = value + return this + } +} diff --git a/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/AppboyKitTests.kt b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/AppboyKitTests.kt new file mode 100644 index 000000000..bbcf6419b --- /dev/null +++ b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/AppboyKitTests.kt @@ -0,0 +1,1557 @@ +package com.mparticle.kits + +import android.util.SparseBooleanArray +import com.braze.Braze +import com.braze.models.outgoing.BrazeProperties +import com.mparticle.MPEvent +import com.mparticle.MParticle +import com.mparticle.MParticle.IdentityType +import com.mparticle.MParticleOptions +import com.mparticle.commerce.CommerceEvent +import com.mparticle.commerce.Impression +import com.mparticle.commerce.Product +import com.mparticle.commerce.Promotion +import com.mparticle.commerce.TransactionAttributes +import com.mparticle.consent.ConsentState +import com.mparticle.consent.GDPRConsent +import com.mparticle.identity.IdentityApi +import com.mparticle.identity.MParticleUser +import com.mparticle.kits.mocks.MockAppboyKit +import com.mparticle.kits.mocks.MockContextApplication +import com.mparticle.kits.mocks.MockKitConfiguration +import com.mparticle.kits.mocks.MockUser +import junit.framework.TestCase +import org.json.JSONArray +import org.json.JSONObject +import org.junit.Assert +import org.junit.Before +import org.junit.Test +import org.mockito.Mock +import org.mockito.Mockito +import org.mockito.MockitoAnnotations +import java.lang.reflect.Method +import java.math.BigDecimal +import java.security.SecureRandom +import java.util.Calendar +import java.util.Locale + +class AppboyKitTests { + private var random = SecureRandom() + + private lateinit var braze: Braze.Companion + + @Mock + private val mTypeFilters: SparseBooleanArray? = null + + @Mock + lateinit var filteredMParticleUser: FilteredMParticleUser + + @Mock + lateinit var user: MParticleUser + + private val kit: AppboyKit + get() = AppboyKit() + + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + Braze.clearPurchases() + Braze.clearEvents() + Braze.currentUser.customUserAttributes.clear() + MParticle.setInstance(Mockito.mock(MParticle::class.java)) + Mockito.`when`(MParticle.getInstance()!!.Identity()).thenReturn( + Mockito.mock( + IdentityApi::class.java, + ), + ) + braze = Braze + } + + @Test + @Throws(Exception::class) + fun testGetName() { + val name = kit.name + Assert.assertTrue(name.isNotEmpty()) + } + + /** + * Kit *should* throw an exception when they're initialized with the wrong settings. + */ + @Test + @Throws(Exception::class) + fun testOnKitCreate() { + var e: Exception? = null + try { + val kit: KitIntegration = kit + val settings = HashMap() + settings["fake setting"] = "fake" + kit.onKitCreate(settings, MockContextApplication()) + } catch (ex: Exception) { + e = ex + } + Assert.assertNotNull(e) + } + + @Test + @Throws(Exception::class) + fun testClassName() { + val options = Mockito.mock(MParticleOptions::class.java) + val factory = KitIntegrationFactory(options) + val integrations = factory.supportedKits.values + val className = kit.javaClass.name + for (integration in integrations) { + if (integration.name == className) { + return + } + } + Assert.fail("$className not found as a known integration.") + } + + private var hostName = "aRandomHost" + + @Test + @Throws(Exception::class) + fun testHostSetting() { + val settings = HashMap() + settings[AppboyKit.HOST] = hostName + settings[AppboyKit.APPBOY_KEY] = "key" + val kit = MockAppboyKit() + kit.onKitCreate(settings, MockContextApplication()) + Assert.assertTrue(kit.calledAuthority[0] == hostName) + } + + @Test + @Throws(Exception::class) + fun testHostSettingNull() { + // test that the key is set when it is passed in by the settings map + val missingSettings = HashMap() + missingSettings[AppboyKit.APPBOY_KEY] = "key" + val kit = MockAppboyKit() + try { + kit.onKitCreate(missingSettings, MockContextApplication()) + } catch (e: Exception) { + } + Assert.assertTrue(kit.calledAuthority[0] == null) + } + + @Test + @Throws(Exception::class) + fun testHostSettingEmpty() { + var nullSettings = HashMap() + nullSettings[AppboyKit.HOST] = null + nullSettings[AppboyKit.APPBOY_KEY] = "key" + var kit = MockAppboyKit() + try { + kit.onKitCreate(nullSettings, MockContextApplication()) + } catch (e: Exception) { + } + Assert.assertTrue(kit.calledAuthority[0] == null) + nullSettings = HashMap() + nullSettings[AppboyKit.HOST] = "" + nullSettings[AppboyKit.APPBOY_KEY] = "key" + kit = MockAppboyKit() + try { + kit.onKitCreate(nullSettings, MockContextApplication()) + } catch (e: Exception) { + } + Assert.assertTrue(kit.calledAuthority[0] == null) + } + + @Test + fun testOnModify() { + // make sure it doesn't crash if there is no email or customerId + var e: Exception? = null + try { + AppboyKit().onModifyCompleted(MockUser(HashMap()), null) + } catch (ex: Exception) { + e = ex + } + Assert.assertNull(e) + for (i in 0..3) { + val values = arrayOfNulls(2) + val mockEmail = "mockEmail$i" + val mockCustomerId = "12345$i" + val kit: AppboyKit = + object : AppboyKit() { + override fun setId(customerId: String) { + values[0] = customerId + } + + override fun setEmail(email: String) { + if (values[0] == null) { + Assert.fail("customerId should have been set first") + } + values[1] = email + } + } + kit.identityType = IdentityType.CustomerId + val map = HashMap() + map[IdentityType.Email] = mockEmail + map[IdentityType.Alias] = "alias" + map[IdentityType.Facebook] = "facebook" + map[IdentityType.Facebook] = "fb" + map[IdentityType.CustomerId] = mockCustomerId + when (i) { + 0 -> { + kit.onModifyCompleted(MockUser(map), null) + kit.onIdentifyCompleted(MockUser(map), null) + kit.onLoginCompleted(MockUser(map), null) + kit.onLogoutCompleted(MockUser(map), null) + } + 1 -> { + kit.onIdentifyCompleted(MockUser(map), null) + kit.onLoginCompleted(MockUser(map), null) + kit.onLogoutCompleted(MockUser(map), null) + } + 2 -> { + kit.onLoginCompleted(MockUser(map), null) + kit.onLogoutCompleted(MockUser(map), null) + } + 3 -> kit.onLogoutCompleted(MockUser(map), null) + } + Assert.assertEquals(mockCustomerId, values[0]) + Assert.assertEquals(mockEmail, values[1]) + } + } + + @Test + fun testAgeToDob() { + val kit: AppboyKit = MockAppboyKit() + val currentYear = Calendar.getInstance()[Calendar.YEAR] + var calendar = kit.getCalendarMinusYears("5") + calendar + ?.get(Calendar.YEAR) + ?.let { Assert.assertEquals((currentYear - 5).toLong(), it.toLong()) } + calendar = kit.getCalendarMinusYears(22) + calendar + ?.get(Calendar.YEAR) + ?.let { Assert.assertEquals((currentYear - 22).toLong(), it.toLong()) } + +// round down doubles + calendar = kit.getCalendarMinusYears("5.001") + calendar + ?.get(Calendar.YEAR) + ?.let { Assert.assertEquals((currentYear - 5).toLong(), it.toLong()) } + calendar = kit.getCalendarMinusYears("5.9") + calendar + ?.get(Calendar.YEAR) + ?.let { Assert.assertEquals((currentYear - 5).toLong(), it.toLong()) } + + // invalid ages (negative, non numeric), don't get set + Assert.assertNull(kit.getCalendarMinusYears("asdv")) + Assert.assertNull(kit.getCalendarMinusYears(-1)) + } + + @Test + fun testSetSubscriptionGroupIds() { + val settings = HashMap() + settings[AppboyKit.APPBOY_KEY] = "key" + settings[AppboyKit.HOST] = hostName + settings["subscriptionGroupMapping"] = + "[{\"jsmap\":null,\"map\":\"test1\",\"maptype\":\"UserAttributeClass.Name\"," + + "\"value\":\"00000000-0000-0000-0000-000000000000\"}," + + "{\"jsmap\":null,\"map\":\"test2\",\"maptype\":\"UserAttributeClass.Name\"," + + "\"value\":\"00000000-0000-0000-0000-000000000001\"}," + + "{\"jsmap\":null,\"map\":\"test3\",\"maptype\":\"UserAttributeClass.Name\"," + + "\"value\":\"00000000-0000-0000-0000-000000000002\"}]" + val kit = MockAppboyKit() + val currentUser = braze.currentUser + + kit.onKitCreate(settings, MockContextApplication()) + kit.setUserAttribute("test1", "true") + kit.setUserAttribute("test2", "false") + kit.setUserAttribute("test3", "notABoolean") + Assert.assertEquals(2, currentUser.getCustomUserAttribute().size.toLong()) + } + +// @Test +// fun testSetUserAttributeAge() { +// val currentYear = Calendar.getInstance()[Calendar.YEAR] +// val kit: AppboyKit = MockAppboyKit() +// val currentUser = Braze.currentUser +// Assert.assertEquals(-1, currentUser.dobDay.toLong()) +// Assert.assertEquals(-1, currentUser.dobYear.toLong()) +// Assert.assertNull(currentUser.dobMonth) +// kit.setUserAttribute(MParticle.UserAttributes.AGE, "100") +// Assert.assertEquals((currentYear - 100).toLong(), currentUser.dobYear.toLong()) +// Assert.assertEquals(1, currentUser.dobDay.toLong()) +// Assert.assertEquals(Month.JANUARY, currentUser.dobMonth) +// } + +// @Test +// fun testSetUserDoB() { +// val kit = MockAppboyKit() +// val currentUser = Braze.currentUser +// val errorMessage = arrayOfNulls(1) +// Logger.setLogHandler(object : DefaultLogHandler() { +// override fun log(priority: LogLevel, error: Throwable?, messages: String) { +// if (priority == LogLevel.WARNING) { +// errorMessage[0] = messages +// } +// } +// }) +// +// //valid +// kit.setUserAttribute("dob", "1999-11-05") +// Assert.assertEquals(1999, currentUser.dobYear.toLong()) +// Assert.assertEquals(5, currentUser.dobDay.toLong()) +// Assert.assertEquals(Month.NOVEMBER, currentUser.dobMonth) +// Assert.assertNull(errorMessage[0]) +// +// //future +// kit.setUserAttribute("dob", "2999-2-15") +// Assert.assertEquals(2999, currentUser.dobYear.toLong()) +// Assert.assertEquals(15, currentUser.dobDay.toLong()) +// Assert.assertEquals(Month.FEBRUARY, currentUser.dobMonth) +// Assert.assertNull(errorMessage[0]) +// +// +// //bad format (shouldn't crash, but should message) +// var ex: Exception? = null +// try { +// kit.setUserAttribute("dob", "2kjb.21h045") +// Assert.assertEquals(2999, currentUser.dobYear.toLong()) +// Assert.assertEquals(15, currentUser.dobDay.toLong()) +// Assert.assertEquals(Month.FEBRUARY, currentUser.dobMonth) +// Assert.assertNotNull(errorMessage[0]) +// } catch (e: Exception) { +// ex = e +// } +// Assert.assertNull(ex) +// } + + @Test + fun setIdentityType() { + val possibleValues = + arrayOf( + "Other", + "CustomerId", + "Facebook", + "Twitter", + "Google", + "Microsoft", + "Yahoo", + "Email", + "Alias", + ) + val mpid = "MPID" + for (`val` in possibleValues) { + val kit = kit + val settings = HashMap() + settings[AppboyKit.USER_IDENTIFICATION_TYPE] = `val` + kit.setIdentityType(settings) + Assert.assertNotNull(kit.identityType) + Assert.assertEquals( + `val`.lowercase(Locale.getDefault()), + kit.identityType?.name?.lowercase(Locale.getDefault()), + ) + Assert.assertFalse(kit.isMpidIdentityType) + } + val settings = HashMap() + settings[AppboyKit.USER_IDENTIFICATION_TYPE] = mpid + val kit = kit + kit.setIdentityType(settings) + Assert.assertNull(kit.identityType) + Assert.assertTrue(kit.isMpidIdentityType) + } + + @Test + fun setId() { + val userIdentities = HashMap() + val user = Mockito.mock(MParticleUser::class.java) + Mockito.`when`(user.userIdentities).thenReturn(userIdentities) + val mockId = random.nextLong() + Mockito.`when`(user.id).thenReturn(mockId) + Assert.assertEquals(mockId.toString(), kit.getIdentity(true, null, user)) + for (identityType in IdentityType.values()) { + val identityValue = random.nextLong().toString() + userIdentities[identityType] = identityValue + Assert.assertEquals(identityValue, kit.getIdentity(false, identityType, user)) + } + Assert.assertNull(kit.getIdentity(false, null, null)) + } + +// @Test +// fun addRemoveAttributeFromEventTest() { +// val kit = MockAppboyKit() +// val currentUser = Braze.currentUser +// kit.configuration = object : MockKitConfiguration() { +// +// override fun getEventAttributesAddToUser(): Map { +// val map = HashMap() +// map[KitUtils.hashForFiltering( +// MParticle.EventType.Navigation.toString() + "Navigation Event" + "key1" +// )] = "output" +// return map +// } +// +// override fun getEventAttributesRemoveFromUser(): Map { +// val map = HashMap() +// map[KitUtils.hashForFiltering( +// MParticle.EventType.Location.toString() + "location event" + "key1" +// )] = "output" +// return map +// } +// +// } +// val customAttributes = HashMap() +// customAttributes["key1"] = "value1" +// kit.logEvent( +// MPEvent.Builder("Navigation Event", MParticle.EventType.Navigation) +// .customAttributes(customAttributes) +// .build() +// ) +// var attributes = currentUser.customAttributeArray["output"] +// if (attributes != null) { +// Assert.assertEquals(1, attributes.size) +// Assert.assertEquals("value1", attributes[0]) +// } +// kit.logEvent( +// MPEvent.Builder("location event", MParticle.EventType.Location) +// .customAttributes(customAttributes) +// .build() +// ) +// attributes = currentUser.customAttributeArray["output"] +// +// if (attributes != null) { +// Assert.assertEquals(0, attributes.size) +// } +// } + + @Test + fun testPurchaseCurrency() { + val kit = MockAppboyKit() + val product = + Product + .Builder("product name", "sku1", 4.5) + .build() + val commerceEvent = + CommerceEvent + .Builder(Product.CHECKOUT, product) + .currency("Moon Dollars") + .build() + kit.logTransaction(commerceEvent, product) + val braze = Braze + val purchases = braze.purchases + Assert.assertEquals(1, purchases.size.toLong()) + val purchase = purchases[0] + Assert.assertEquals("Moon Dollars", purchase.currency) + Assert.assertNull( + purchase.purchaseProperties.properties[CommerceEventUtils.Constants.ATT_ACTION_CURRENCY_CODE], + ) + } + + @Test + fun testPurchaseDefaultCurrency() { + val kit = MockAppboyKit() + val product = + Product + .Builder("product name", "sku1", 4.5) + .build() + val commerceEvent = + CommerceEvent + .Builder(Product.CHECKOUT, product) + .build() + kit.logTransaction(commerceEvent, product) + val braze = Braze + val purchases = braze.purchases + Assert.assertEquals(1, purchases.size.toLong()) + val purchase = purchases[0] + Assert.assertEquals(CommerceEventUtils.Constants.DEFAULT_CURRENCY_CODE, purchase.currency) + Assert.assertNull( + purchase.purchaseProperties.properties[CommerceEventUtils.Constants.ATT_ACTION_CURRENCY_CODE], + ) + } + + @Test + fun testPurchase() { + val kit = MockAppboyKit() + val customAttributes = HashMap() + customAttributes["key1"] = "value1" + customAttributes["key #2"] = "value #3" + val productCustomAttributes = HashMap() + productCustomAttributes["productKey1"] = "value1" + productCustomAttributes["productKey2"] = "value2" + val transactionAttributes = + TransactionAttributes("the id") + .setTax(100.0) + .setShipping(12.0) + .setRevenue(99.0) + .setCouponCode("coupon code") + .setAffiliation("the affiliation") + val product = + Product + .Builder("product name", "sku1", 4.5) + .quantity(5.0) + .brand("testBrand") + .variant("testVariant") + .position(1) + .category("testCategory") + .customAttributes(productCustomAttributes) + .build() + val commerceEvent = + CommerceEvent + .Builder(Product.PURCHASE, product) + .currency("Moon Dollars") + .productListName("product list name") + .productListSource("the source") + .customAttributes(customAttributes) + .transactionAttributes(transactionAttributes) + .build() + kit.logTransaction(commerceEvent, product) + val braze = Braze + val purchases = braze.purchases + Assert.assertEquals(1, purchases.size.toLong()) + val purchase = purchases[0] + Assert.assertEquals("Moon Dollars", purchase.currency) + Assert.assertEquals(5.0, purchase.quantity.toDouble(), 0.01) + Assert.assertEquals("sku1", purchase.sku) + Assert.assertEquals(BigDecimal(4.5), purchase.unitPrice) + Assert.assertNotNull(purchase.purchaseProperties) + val properties = purchase.purchaseProperties.properties + Assert.assertEquals(properties.remove(CommerceEventUtils.Constants.ATT_SHIPPING), 12.0) + Assert.assertEquals( + properties.remove(CommerceEventUtils.Constants.ATT_ACTION_PRODUCT_LIST_SOURCE), + "the source", + ) + Assert.assertEquals(properties.remove(CommerceEventUtils.Constants.ATT_TAX), 100.0) + Assert.assertEquals(properties.remove(CommerceEventUtils.Constants.ATT_TOTAL), 99.0) + Assert.assertEquals( + properties.remove(CommerceEventUtils.Constants.ATT_ACTION_PRODUCT_ACTION_LIST), + "product list name", + ) + Assert.assertEquals( + properties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_COUPON_CODE), + "coupon code", + ) + Assert.assertEquals( + properties.remove(CommerceEventUtils.Constants.ATT_TRANSACTION_ID), + "the id", + ) + Assert.assertEquals( + properties.remove(CommerceEventUtils.Constants.ATT_AFFILIATION), + "the affiliation", + ) + Assert.assertEquals( + properties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_NAME), + "product name", + ) + Assert.assertEquals( + properties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_CATEGORY), + "testCategory", + ) + Assert.assertEquals( + properties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_BRAND), + "testBrand", + ) + Assert.assertEquals( + properties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_POSITION), + 1, + ) + Assert.assertEquals( + properties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_VARIANT), + "testVariant", + ) + + // Custom Attributes + Assert.assertEquals(properties.remove("key1"), "value1") + Assert.assertEquals(properties.remove("key #2"), "value #3") + + // Product Custom Attributes + Assert.assertEquals(properties.remove("productKey1"), "value1") + Assert.assertEquals(properties.remove("productKey2"), "value2") + + val emptyAttributes = HashMap() + Assert.assertEquals(emptyAttributes, properties) + } + + @Test + fun testEnhancedPurchase() { + val emptyAttributes = HashMap() + val kit = MockAppboyKit() + val customAttributes = HashMap() + customAttributes["key1"] = "value1" + customAttributes["key #2"] = "value #3" + val transactionAttributes = + TransactionAttributes("the id") + .setTax(100.0) + .setShipping(12.0) + .setRevenue(99.0) + .setCouponCode("coupon code") + .setAffiliation("the affiliation") + val product = + Product + .Builder("product name", "sku1", 4.5) + .quantity(5.0) + .build() + val commerceEvent = + CommerceEvent + .Builder(Product.PURCHASE, product) + .currency("Moon Dollars") + .productListName("product list name") + .productListSource("the source") + .customAttributes(customAttributes) + .transactionAttributes(transactionAttributes) + .build() + kit.logOrderLevelTransaction(commerceEvent) + val braze = Braze + val purchases = braze.purchases + Assert.assertEquals(1, purchases.size.toLong()) + val purchase = purchases[0] + Assert.assertEquals("Moon Dollars", purchase.currency) + Assert.assertEquals(1.0, purchase.quantity.toDouble(), 0.01) + Assert.assertEquals("eCommerce - purchase", purchase.sku) + Assert.assertEquals(BigDecimal(99.0), purchase.unitPrice) + Assert.assertNotNull(purchase.purchaseProperties) + val properties = purchase.purchaseProperties.properties + val productArray = properties.remove(AppboyKit.PRODUCT_KEY) + Assert.assertTrue(productArray is JSONArray) + if (productArray is Array<*>) { + Assert.assertEquals(1, productArray.size.toLong()) + val productBrazeProperties = productArray[0] + if (productBrazeProperties is BrazeProperties) { + val productProperties = productBrazeProperties.properties + Assert.assertEquals( + productProperties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_TOTAL_AMOUNT), + 22.5, + ) + Assert.assertEquals( + productProperties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_PRICE), + 4.5, + ) + Assert.assertEquals( + productProperties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_QUANTITY), + 5.0, + ) + Assert.assertEquals( + productProperties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_ID), + "sku1", + ) + Assert.assertEquals( + productProperties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_NAME), + "product name", + ) + Assert.assertEquals(emptyAttributes, productProperties) + } + } + Assert.assertEquals(properties.remove(CommerceEventUtils.Constants.ATT_SHIPPING), 12.0) + Assert.assertEquals(properties.remove(CommerceEventUtils.Constants.ATT_TAX), 100.0) + Assert.assertEquals( + properties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_COUPON_CODE), + "coupon code", + ) + Assert.assertEquals( + properties.remove(CommerceEventUtils.Constants.ATT_AFFILIATION), + "the affiliation", + ) + Assert.assertEquals( + properties.remove(CommerceEventUtils.Constants.ATT_ACTION_PRODUCT_LIST_SOURCE), + "the source", + ) + Assert.assertEquals(properties.remove(CommerceEventUtils.Constants.ATT_TOTAL), 99.0) + Assert.assertEquals( + properties.remove(CommerceEventUtils.Constants.ATT_ACTION_PRODUCT_ACTION_LIST), + "product list name", + ) + Assert.assertEquals( + properties.remove(CommerceEventUtils.Constants.ATT_TRANSACTION_ID), + "the id", + ) + + val brazeCustomAttributesDictionary = properties.remove(AppboyKit.CUSTOM_ATTRIBUTES_KEY) + if (brazeCustomAttributesDictionary is BrazeProperties) { + val customAttributesDictionary = brazeCustomAttributesDictionary.properties + Assert.assertEquals(customAttributesDictionary.remove("key1"), "value1") + Assert.assertEquals(customAttributesDictionary.remove("key #2"), "value #3") + Assert.assertEquals(emptyAttributes, customAttributesDictionary) + } + Assert.assertEquals(emptyAttributes, properties) + } + +// @Test +// fun testPromotion() { +// val emptyAttributes = HashMap() +// val kit = MockAppboyKit() +// kit.configuration = MockKitConfiguration() +// val customAttributes = HashMap() +// customAttributes["key1"] = "value1" +// customAttributes["key #2"] = "value #3" +// val promotion = Promotion().apply { +// id = "my_promo_1" +// creative = "sale_banner_1" +// name = "App-wide 50% off sale" +// position ="dashboard_bottom" +// } +// val commerceEvent = CommerceEvent.Builder(Promotion.VIEW, promotion) +// .customAttributes(customAttributes) +// .build() +// kit.logEvent(commerceEvent) +// +// val braze = Braze +// val events = braze.events +// Assert.assertEquals(1, events.size.toLong()) +// val event = events.values.iterator().next() +// Assert.assertNotNull(event.properties) +// val properties = event.properties +// +// Assert.assertEquals(properties.remove("Id"), "my_promo_1") +// Assert.assertEquals(properties.remove("Name"), "App-wide 50% off sale") +// Assert.assertEquals(properties.remove("Position"), "dashboard_bottom") +// Assert.assertEquals(properties.remove("Creative"), "sale_banner_1") +// Assert.assertEquals(properties.remove("key1"), "value1") +// Assert.assertEquals(properties.remove("key #2"), "value #3") +// +// Assert.assertEquals(emptyAttributes, properties) +// } + + @Test + fun testEnhancedPromotion() { + val emptyAttributes = HashMap() + val kit = MockAppboyKit() + kit.configuration = MockKitConfiguration() + val customAttributes = HashMap() + customAttributes["key1"] = "value1" + customAttributes["key #2"] = "value #3" + val promotion = + Promotion().apply { + id = "my_promo_1" + creative = "sale_banner_1" + name = "App-wide 50% off sale" + position = "dashboard_bottom" + } + val commerceEvent = + CommerceEvent + .Builder(Promotion.VIEW, promotion) + .customAttributes(customAttributes) + .build() + kit.logOrderLevelTransaction(commerceEvent) + val braze = Braze + val events = braze.events + Assert.assertEquals(1, events.size.toLong()) + val event = events.values.iterator().next() + Assert.assertNotNull(event.properties) + val properties = event.properties + + val promotionArray = properties.remove(AppboyKit.PROMOTION_KEY) + Assert.assertTrue(promotionArray is JSONArray) + if (promotionArray is Array<*>) { + Assert.assertEquals(1, promotionArray.size.toLong()) + val promotionBrazeProperties = promotionArray[0] + if (promotionBrazeProperties is BrazeProperties) { + val promotionProperties = promotionBrazeProperties.properties + Assert.assertEquals( + promotionProperties.remove(CommerceEventUtils.Constants.ATT_PROMOTION_ID), + "my_promo_1", + ) + Assert.assertEquals( + promotionProperties.remove(CommerceEventUtils.Constants.ATT_PROMOTION_NAME), + "App-wide 50% off sale", + ) + Assert.assertEquals( + promotionProperties.remove(CommerceEventUtils.Constants.ATT_PROMOTION_POSITION), + "dashboard_bottom", + ) + Assert.assertEquals( + promotionProperties.remove(CommerceEventUtils.Constants.ATT_PROMOTION_CREATIVE), + "sale_banner_1", + ) + Assert.assertEquals(emptyAttributes, promotionProperties) + } + } + + val brazeCustomAttributesDictionary = properties.remove(AppboyKit.CUSTOM_ATTRIBUTES_KEY) + if (brazeCustomAttributesDictionary is BrazeProperties) { + val customAttributesDictionary = brazeCustomAttributesDictionary.properties + Assert.assertEquals(customAttributesDictionary.remove("key1"), "value1") + Assert.assertEquals(customAttributesDictionary.remove("key #2"), "value #3") + Assert.assertEquals(emptyAttributes, customAttributesDictionary) + } + + Assert.assertEquals(properties.remove(CommerceEventUtils.Constants.ATT_TOTAL), 0.0) + + Assert.assertEquals(emptyAttributes, properties) + } + +// @Test +// fun testImpression() { +// val kit = MockAppboyKit() +// kit.configuration = MockKitConfiguration() +// val customAttributes = HashMap() +// customAttributes["key1"] = "value1" +// customAttributes["key #2"] = "value #3" +// val product = Product.Builder("product name", "sku1", 4.5) +// .quantity(5.0) +// .build() +// val impression = Impression("Suggested Products List", product).let { +// CommerceEvent.Builder(it).build() +// } +// val commerceEvent = CommerceEvent.Builder(impression) +// .customAttributes(customAttributes) +// .build() +// +// kit.logEvent(commerceEvent) +// +// val braze = Braze +// val events = braze.events +// Assert.assertEquals(1, events.size.toLong()) +// val event = events.values.iterator().next() +// Assert.assertNotNull(event.properties) +// val properties = event.properties +// +// Assert.assertEquals( +// properties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_TOTAL_AMOUNT), "22.5" +// ) +// Assert.assertEquals( +// properties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_NAME), "product name" +// ) +// Assert.assertEquals( +// properties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_QUANTITY), "5.0" +// ) +// Assert.assertEquals(properties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_ID), "sku1") +// Assert.assertEquals( +// properties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_PRICE), "4.5" +// ) +// Assert.assertEquals( +// properties.remove("Product Impression List"), "Suggested Products List" +// ) +// Assert.assertEquals(properties.remove("key1"), "value1") +// Assert.assertEquals(properties.remove("key #2"), "value #3") +// +// val emptyAttributes = HashMap() +// Assert.assertEquals(emptyAttributes, properties) +// } + + @Test + fun testEnhancedImpression() { + val emptyAttributes = HashMap() + val kit = MockAppboyKit() + kit.configuration = MockKitConfiguration() + val customAttributes = HashMap() + customAttributes["key1"] = "value1" + customAttributes["key #2"] = "value #3" + val product = + Product + .Builder("product name", "sku1", 4.5) + .quantity(5.0) + .customAttributes(customAttributes) + .build() + val impression = + Impression("Suggested Products List", product).let { + CommerceEvent.Builder(it).build() + } + val commerceEvent = + CommerceEvent + .Builder(impression) + .customAttributes(customAttributes) + .build() + kit.logOrderLevelTransaction(commerceEvent) + val braze = Braze + val events = braze.events + Assert.assertEquals(1, events.size.toLong()) + val event = events.values.iterator().next() + Assert.assertNotNull(event.properties) + val properties = event.properties + + val impressionArray = properties.remove(AppboyKit.IMPRESSION_KEY) + Assert.assertTrue(impressionArray is JSONArray) + if (impressionArray is Array<*>) { + Assert.assertEquals(1, impressionArray.size.toLong()) + val impressionBrazeProperties = impressionArray[0] + if (impressionBrazeProperties is BrazeProperties) { + val impressionProperties = impressionBrazeProperties.properties + Assert.assertEquals( + impressionProperties.remove("Product Impression List"), + "Suggested Products List", + ) + val productArray = impressionProperties.remove(AppboyKit.PRODUCT_KEY) + Assert.assertTrue(productArray is Array<*>) + if (productArray is Array<*>) { + Assert.assertEquals(1, productArray.size.toLong()) + val productBrazeProperties = productArray[0] + if (productBrazeProperties is BrazeProperties) { + val productProperties = productBrazeProperties.properties + Assert.assertEquals( + productProperties.remove( + CommerceEventUtils.Constants.ATT_PRODUCT_TOTAL_AMOUNT, + ), + 22.5, + ) + Assert.assertEquals( + productProperties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_NAME), + "product name", + ) + Assert.assertEquals( + productProperties.remove( + CommerceEventUtils.Constants.ATT_PRODUCT_QUANTITY, + ), + 5.0, + ) + Assert.assertEquals( + productProperties.remove(CommerceEventUtils.Constants.ATT_PRODUCT_ID), + "sku1", + ) + Assert.assertEquals( + productProperties.remove( + CommerceEventUtils.Constants.ATT_PRODUCT_PRICE, + ), + 4.5, + ) + val brazeProductCustomAttributesDictionary = + productProperties.remove(AppboyKit.CUSTOM_ATTRIBUTES_KEY) + if (brazeProductCustomAttributesDictionary is BrazeProperties) { + val customProductAttributesDictionary = + brazeProductCustomAttributesDictionary.properties + Assert.assertEquals( + customProductAttributesDictionary.remove("key1"), + "value1", + ) + Assert.assertEquals( + customProductAttributesDictionary.remove("key #2"), + "value #3", + ) + Assert.assertEquals(emptyAttributes, customProductAttributesDictionary) + } + Assert.assertEquals(emptyAttributes, productProperties) + } + Assert.assertEquals(emptyAttributes, impressionProperties) + } + } + } + + val brazeCustomAttributesDictionary = properties.remove(AppboyKit.CUSTOM_ATTRIBUTES_KEY) + if (brazeCustomAttributesDictionary is BrazeProperties) { + val customAttributesDictionary = brazeCustomAttributesDictionary.properties + Assert.assertEquals(customAttributesDictionary.remove("key1"), "value1") + Assert.assertEquals(customAttributesDictionary.remove("key #2"), "value #3") + Assert.assertEquals(emptyAttributes, customAttributesDictionary) + } + + Assert.assertEquals(properties.remove(CommerceEventUtils.Constants.ATT_TOTAL), 0.0) + + Assert.assertEquals(emptyAttributes, properties) + } + +// @Test +// fun setUserAttributeTyped() { +// val kit = MockAppboyKit() +// kit.enableTypeDetection = true +// val currentUser = Braze.currentUser +// kit.setUserAttribute("foo", "true") +// Assert.assertTrue(currentUser.customUserAttributes["foo"] is Boolean) +// Assert.assertEquals(currentUser.customUserAttributes["foo"], true) +// kit.setUserAttribute("foo", "1") +// Assert.assertTrue(currentUser.customUserAttributes["foo"] is Int) +// Assert.assertEquals(currentUser.customUserAttributes["foo"], 1) +// kit.setUserAttribute("foo", "1.1") +// Assert.assertTrue(currentUser.customUserAttributes["foo"] is Double) +// Assert.assertEquals(currentUser.customUserAttributes["foo"], 1.1) +// kit.setUserAttribute("foo", "bar") +// Assert.assertTrue(currentUser.customUserAttributes["foo"] is String) +// Assert.assertEquals(currentUser.customUserAttributes["foo"], "bar") +// } + +// @Test +// fun testEventStringType() { +// val kit = MockAppboyKit() +// kit.configuration = MockKitConfiguration() +// val customAttributes = HashMap() +// customAttributes["foo"] = "false" +// customAttributes["bar"] = "1" +// customAttributes["baz"] = "1.5" +// customAttributes["fuzz?"] = "foobar" +// val customEvent = MPEvent.Builder("testEvent", MParticle.EventType.Location) +// .customAttributes(customAttributes) +// .build() +// kit.enableTypeDetection = true +// kit.logEvent(customEvent) +// val braze = Braze +// val events = braze.events +// Assert.assertEquals(1, events.values.size.toLong()) +// val event = events.values.iterator().next() +// val properties = event.properties +// Assert.assertEquals(properties.remove("foo"), false) +// Assert.assertEquals(properties.remove("bar"), 1) +// Assert.assertEquals(properties.remove("baz"), 1.5) +// Assert.assertEquals(properties.remove("fuzz?"), "foobar") +// Assert.assertEquals(0, properties.size.toLong()) +// } + +// @Test +// fun testLogCommerceEvent() { +// val kit = MockAppboyKit() +// +// val product: Product = Product.Builder("La Enchilada", "13061043670", 12.5) +// .quantity(1.0) +// .build() +// +// val txAttributes = TransactionAttributes() +// .setRevenue(product.getTotalAmount()) +// +// kit.configuration = MockKitConfiguration() +// val customAttributes: MutableMap = HashMap() +// customAttributes["currentLocationLongitude"] = "2.1811267" +// customAttributes["country"] = "ES" +// customAttributes["deliveryLocationLatitude"] = "41.4035798" +// customAttributes["appVersion"] = "5.201.0" +// customAttributes["city"] = "BCN" +// customAttributes["deviceId"] = "1104442582" +// customAttributes["platform"] = "android" +// customAttributes["isAuthorized"] = "true" +// customAttributes["productSelectionOrigin"] = "Catalogue" +// customAttributes["currentLocationLatitude"] = "41.4035798" +// customAttributes["collectionId"] = "1180889389" +// customAttributes["multiplatformVersion"] = "1.0.288" +// customAttributes["deliveryLocationTimestamp"] = "1675344636685" +// customAttributes["productId"] = "13061043670" +// customAttributes["storeAddressId"] = "300482" +// customAttributes["currentLocationAccuracy"] = "19.278" +// customAttributes["productAddedOrigin"] = "Item Detail Add to Order" +// customAttributes["deliveryLocationLongitude"] = "2.1811267" +// customAttributes["currentLocationTimestamp"] = "1675344636685" +// customAttributes["dynamicSessionId"] = "67f8fb8d-8d14-4f0e-bf1a-73fb8e6eed95" +// customAttributes["deliveryLocationAccuracy"] = "19.278" +// customAttributes["categoryId"] = "1" +// customAttributes["isSponsored"] = "false" +// +// val commerceEvent: CommerceEvent = CommerceEvent.Builder(Product.ADD_TO_CART, product) +// .currency("EUR") +// .customAttributes(customAttributes) +// .transactionAttributes(txAttributes) +// .build() +// kit.logEvent(commerceEvent) +// +// val braze = Braze +// val events = braze.events +// Assert.assertEquals(1, events.size.toLong()) +// val event = events.values.iterator().next() +// Assert.assertNotNull(event.properties) +// val properties = event.properties +// +// Assert.assertEquals(properties.remove("Name"), "La Enchilada") +// Assert.assertEquals(properties.remove("Total Product Amount"), "12.5") +// Assert.assertEquals(properties.remove("Id"), "13061043670") +// for (item in customAttributes) { +// Assert.assertTrue(properties.containsKey(item.key)) +// Assert.assertTrue(properties.containsValue(item.value)) +// } +// } + +// @Test +// fun testEventStringTypeNotEnabled() { +// val kit = MockAppboyKit() +// kit.configuration = MockKitConfiguration() +// val customAttributes = HashMap() +// customAttributes["foo"] = "false" +// customAttributes["bar"] = "1" +// customAttributes["baz"] = "1.5" +// customAttributes["fuzz?"] = "foobar" +// val customEvent = MPEvent.Builder("testEvent", MParticle.EventType.Location) +// .customAttributes(customAttributes) +// .build() +// kit.enableTypeDetection = false +// kit.logEvent(customEvent) +// val braze = Braze +// val events = braze.events +// Assert.assertEquals(1, events.values.size.toLong()) +// val event = events.values.iterator().next() +// val properties = event.properties +// Assert.assertEquals(properties.remove("foo"), "false") +// Assert.assertEquals(properties.remove("bar"), "1") +// Assert.assertEquals(properties.remove("baz"), "1.5") +// Assert.assertEquals(properties.remove("fuzz?"), "foobar") +// Assert.assertEquals(0, properties.size.toLong()) +// } + + @Test + fun testCustomAttributes_log_add_attribute_event() { + val kit = MockAppboyKit() + val currentUser = braze.currentUser + + kit.configuration = MockKitConfiguration() + + val jsonObject = JSONObject() + val mapValue = JSONObject() + // this is hash for event attribute i.e combination of eventType + eventName + attribute key + mapValue.put("888169310", "testEvent") + val eaaObject = JSONObject() + eaaObject.put("eaa", mapValue) + jsonObject.put("hs", eaaObject) + + Mockito.`when`(mTypeFilters!!.size()).thenReturn(0) + + var kitConfiguration = MockKitConfiguration.createKitConfiguration(jsonObject) + kit.configuration = kitConfiguration + val customAttributes: MutableMap = HashMap() + customAttributes["destination"] = "Shop" + val event = + MPEvent + .Builder("AndroidTEST", MParticle.EventType.Navigation) + .customAttributes(customAttributes) + .build() + val instance = MParticle.getInstance() + instance?.logEvent(event) + kit.logEvent(event) + Assert.assertEquals(1, braze.events.size.toLong()) + Assert.assertEquals(1, currentUser.getCustomAttribute().size.toLong()) + var outputKey = "" + for (keys in currentUser.getCustomAttribute().keys) { + outputKey = keys + break + } + Assert.assertEquals("testEvent", outputKey) + } + + @Test + fun testCustomAttributes_log_remove_attribute_event() { + val kit = MockAppboyKit() + val currentUser = braze.currentUser + + kit.configuration = MockKitConfiguration() + + val jsonObject = JSONObject() + val mapValue = JSONObject() + // this is hash for event attribute i.e combination of eventType + eventName + attribute key + mapValue.put("888169310", "testEvent") + val eaaObject = JSONObject() + eaaObject.put("eaa", mapValue) + eaaObject.put("ear", mapValue) + jsonObject.put("hs", eaaObject) + + Mockito.`when`(mTypeFilters!!.size()).thenReturn(0) + + var kitConfiguration = MockKitConfiguration.createKitConfiguration(jsonObject) + kit.configuration = kitConfiguration + val customAttributes: MutableMap = HashMap() + customAttributes["destination"] = "Shop" + val event = + MPEvent + .Builder("AndroidTEST", MParticle.EventType.Navigation) + .customAttributes(customAttributes) + .build() + val instance = MParticle.getInstance() + instance?.logEvent(event) + kit.logEvent(event) + Assert.assertEquals(1, braze.events.size.toLong()) + Assert.assertEquals(0, currentUser.getCustomAttribute().size.toLong()) + } + + @Test + fun testCustomAttributes_log_add_customUserAttribute_event() { + val kit = MockAppboyKit() + val currentUser = braze.currentUser + + kit.configuration = MockKitConfiguration() + + val jsonObject = JSONObject() + val mapValue = JSONObject() + // this is hash for event attribute i.e combination of eventType + eventName + attribute key + mapValue.put("888169310", "testEvent") + val eaaObject = JSONObject() + eaaObject.put("eas", mapValue) + jsonObject.put("hs", eaaObject) + + Mockito.`when`(mTypeFilters!!.size()).thenReturn(0) + + var kitConfiguration = MockKitConfiguration.createKitConfiguration(jsonObject) + kit.configuration = kitConfiguration + val customAttributes: MutableMap = HashMap() + customAttributes["destination"] = "Shop" + val event = + MPEvent + .Builder("AndroidTEST", MParticle.EventType.Navigation) + .customAttributes(customAttributes) + .build() + val instance = MParticle.getInstance() + instance?.logEvent(event) + kit.logEvent(event) + Assert.assertEquals(1, braze.events.size.toLong()) + Assert.assertEquals(1, currentUser.getCustomUserAttribute().size.toLong()) + var outputKey = "" + for (keys in currentUser.getCustomUserAttribute().keys) { + outputKey = keys + break + } + Assert.assertEquals("testEvent", outputKey) + } + + @Test + fun testParseToNestedMap_When_JSON_Is_INVALID() { + val kit = MockAppboyKit() + var jsonInput = + "{'GDPR':{'marketing':'{:false,'timestamp':1711038269644:'Test consent'," + + "'location':'17 Cherry Tree Lane','hardware_id':'IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702'}," + + "'performance':'{'consented':true,'timestamp':1711038269644," + + "'document':'parental_consent_agreement_v2','location':'17 Cherry Tree Lan 3'," + + "'hardware_id':'IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702'}'}," + + "'CCPA':'{'consented':true,'timestamp':1711038269644," + + "'document':'ccpa_consent_agreement_v3','location':'17 Cherry Tree Lane'," + + "'hardware_id':'IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702'}'}" + + val method: Method = + AppboyKit::class.java.getDeclaredMethod( + "parseToNestedMap", + String::class.java, + ) + method.isAccessible = true + val result = method.invoke(kit, jsonInput) + Assert.assertEquals(mutableMapOf(), result) + } + + @Test + fun testParseToNestedMap_When_JSON_Is_Empty() { + val kit = MockAppboyKit() + var jsonInput = "" + + val method: Method = + AppboyKit::class.java.getDeclaredMethod( + "parseToNestedMap", + String::class.java, + ) + method.isAccessible = true + val result = method.invoke(kit, jsonInput) + Assert.assertEquals(mutableMapOf(), result) + } + + @Test + fun testSearchKeyInNestedMap_When_Input_Key_Is_Empty_String() { + val kit = MockAppboyKit() + val map = + mapOf( + "FeatureEnabled" to true, + "settings" to + mapOf( + "darkMode" to false, + "notifications" to + mapOf( + "email" to false, + "push" to true, + "lastUpdated" to 1633046400000L, + ), + ), + ) + val method: Method = + AppboyKit::class.java.getDeclaredMethod( + "searchKeyInNestedMap", + Map::class.java, + Any::class.java, + ) + method.isAccessible = true + val result = method.invoke(kit, map, "") + Assert.assertEquals(null, result) + } + + @Test + fun testSearchKeyInNestedMap_When_Input_Is_Empty_Map() { + val kit = MockAppboyKit() + val emptyMap: Map = emptyMap() + val method: Method = + AppboyKit::class.java.getDeclaredMethod( + "searchKeyInNestedMap", + Map::class.java, + Any::class.java, + ) + method.isAccessible = true + val result = method.invoke(kit, emptyMap, "1") + Assert.assertEquals(null, result) + } + + @Test + fun testParseConsentMapping_When_Input_Is_Empty_Json() { + val kit = MockAppboyKit() + val emptyJson = "" + val method: Method = + AppboyKit::class.java.getDeclaredMethod( + "parseConsentMapping", + String::class.java, + ) + method.isAccessible = true + val result = method.invoke(kit, emptyJson) + Assert.assertEquals(emptyMap(), result) + } + + @Test + fun testParseConsentMapping_When_Input_Is_Invalid_Json() { + val kit = MockAppboyKit() + var jsonInput = + "{'GDPR':{'marketing':'{:false,'timestamp':1711038269644:'Test consent'," + + "'location':'17 Cherry Tree Lane','hardware_id':'IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702'}," + + "'performance':'{'consented':true,'timestamp':1711038269644," + + "'document':'parental_consent_agreement_v2','location':'17 Cherry Tree Lan 3'," + + "'hardware_id':'IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702'}'}," + + "'CCPA':'{'consented':true,'timestamp':1711038269644," + + "'document':'ccpa_consent_agreement_v3','location':'17 Cherry Tree Lane'," + + "'hardware_id':'IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702'}'}" + val method: Method = + AppboyKit::class.java.getDeclaredMethod( + "parseConsentMapping", + String::class.java, + ) + method.isAccessible = true + val result = method.invoke(kit, jsonInput) + Assert.assertEquals(emptyMap(), result) + } + + @Test + fun testParseConsentMapping_When_Input_Is_NULL() { + val kit = MockAppboyKit() + val method: Method = + AppboyKit::class.java.getDeclaredMethod( + "parseConsentMapping", + String::class.java, + ) + method.isAccessible = true + val result = method.invoke(kit, null) + Assert.assertEquals(emptyMap(), result) + } + + @Test + fun onConsentStateUpdatedTest() { + val kit = MockAppboyKit() + val currentUser = braze.currentUser + kit.configuration = MockKitConfiguration() + val map = java.util.HashMap() + + map["consentMappingSDK"] = + " [{\\\"jsmap\\\":null,\\\"map\\\":\\\"Performance\\\"," + + "\\\"maptype\\\":\\\"ConsentPurposes\\\",\\\"value\\\":\\\"google_ad_user_data\\\"}," + + "{\\\"jsmap\\\":null,\\\"map\\\":\\\"Marketing\\\"," + + "\\\"maptype\\\":\\\"ConsentPurposes\\\",\\\"value\\\":\\\"google_ad_personalization\\\"}]" + + var kitConfiguration = + MockKitConfiguration.createKitConfiguration(JSONObject().put("as", map.toMutableMap())) + kit.configuration = kitConfiguration + + val marketingConsent = + GDPRConsent + .builder(false) + .document("Test consent") + .location("17 Cherry Tree Lane") + .hardwareId("IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702") + .build() + val state = + ConsentState + .builder() + .addGDPRConsentState("Marketing", marketingConsent) + .build() + filteredMParticleUser = FilteredMParticleUser.getInstance(user, kit) + + kit.onConsentStateUpdated(state, state, filteredMParticleUser) + TestCase.assertEquals( + false, + currentUser.getCustomUserAttribute()["\$google_ad_personalization"], + ) + } + + @Test + fun onConsentStateUpdatedTest_When_Both_The_consents_Are_True() { + val kit = MockAppboyKit() + val currentUser = braze.currentUser + kit.configuration = MockKitConfiguration() + val map = java.util.HashMap() + + map["consentMappingSDK"] = + " [{\\\"jsmap\\\":null,\\\"map\\\":\\\"Performance\\\"," + + "\\\"maptype\\\":\\\"ConsentPurposes\\\",\\\"value\\\":\\\"google_ad_user_data\\\"}," + + "{\\\"jsmap\\\":null,\\\"map\\\":\\\"Marketing\\\"," + + "\\\"maptype\\\":\\\"ConsentPurposes\\\",\\\"value\\\":\\\"google_ad_personalization\\\"}]" + + var kitConfiguration = + MockKitConfiguration.createKitConfiguration(JSONObject().put("as", map.toMutableMap())) + kit.configuration = kitConfiguration + + val marketingConsent = + GDPRConsent + .builder(true) + .document("Test consent") + .location("17 Cherry Tree Lane") + .hardwareId("IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702") + .build() + + val performanceConsent = + GDPRConsent + .builder(true) + .document("parental_consent_agreement_v2") + .location("17 Cherry Tree Lan 3") + .hardwareId("IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702") + .build() + + val state = + ConsentState + .builder() + .addGDPRConsentState("Marketing", marketingConsent) + .addGDPRConsentState("Performance", performanceConsent) + .build() + filteredMParticleUser = FilteredMParticleUser.getInstance(user, kit) + + kit.onConsentStateUpdated(state, state, filteredMParticleUser) + TestCase.assertEquals(true, currentUser.getCustomUserAttribute()["\$google_ad_user_data"]) + TestCase.assertEquals( + true, + currentUser.getCustomUserAttribute()["\$google_ad_personalization"], + ) + } + + @Test + fun onConsentStateUpdatedTest_When_No_DATA_From_Server() { + val kit = MockAppboyKit() + val currentUser = braze.currentUser + kit.configuration = MockKitConfiguration() + val marketingConsent = + GDPRConsent + .builder(true) + .document("Test consent") + .location("17 Cherry Tree Lane") + .hardwareId("IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702") + .build() + + val performanceConsent = + GDPRConsent + .builder(true) + .document("parental_consent_agreement_v2") + .location("17 Cherry Tree Lan 3") + .hardwareId("IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702") + .build() + + val state = + ConsentState + .builder() + .addGDPRConsentState("Marketing", marketingConsent) + .addGDPRConsentState("Performance", performanceConsent) + .build() + filteredMParticleUser = FilteredMParticleUser.getInstance(user, kit) + kit.onConsentStateUpdated(state, state, filteredMParticleUser) + TestCase.assertEquals(0, currentUser.getCustomUserAttribute().size) + } + + @Test + fun testOnConsentStateUpdatedTest_No_consentMappingSDK() { + val kit = MockAppboyKit() + val currentUser = braze.currentUser + kit.configuration = MockKitConfiguration() + val map = java.util.HashMap() + map["includeEnrichedUserAttributes"] = "True" + map["userIdentificationType"] = "MPID" + map["ABKDisableAutomaticLocationCollectionKey"] = "False" + map["defaultAdPersonalizationConsentSDK"] = "Denied" + + kit.configuration = + KitConfiguration.createKitConfiguration(JSONObject().put("as", map.toMutableMap())) + + val marketingConsent = + GDPRConsent + .builder(true) + .document("Test consent") + .location("17 Cherry Tree Lane") + .hardwareId("IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702") + .build() + + val performanceConsent = + GDPRConsent + .builder(true) + .document("parental_consent_agreement_v2") + .location("17 Cherry Tree Lan 3") + .hardwareId("IDFA:a5d934n0-232f-4afc-2e9a-3832d95zc702") + .build() + + val state = + ConsentState + .builder() + .addGDPRConsentState("Marketing", marketingConsent) + .addGDPRConsentState("Performance", performanceConsent) + .build() + filteredMParticleUser = FilteredMParticleUser.getInstance(user, kit) + + kit.onConsentStateUpdated(state, state, filteredMParticleUser) + + TestCase.assertEquals(0, currentUser.getCustomUserAttribute().size) + } + + @Test + fun testPurchase_Forward_product_name() { + var settings = HashMap() + settings[AppboyKit.APPBOY_KEY] = "key" + settings[AppboyKit.REPLACE_SKU_AS_PRODUCT_NAME] = "True" + val kit = MockAppboyKit() + + kit.configuration = + KitConfiguration.createKitConfiguration(JSONObject().put("as", settings)) + kit.onKitCreate(settings, MockContextApplication()) + val product = + Product + .Builder("product name", "sku1", 4.5) + .build() + val commerceEvent = + CommerceEvent + .Builder(Product.CHECKOUT, product) + .currency("Moon Dollars") + .build() + kit.logTransaction(commerceEvent, product) + val braze = Braze + val purchases = braze.purchases + Assert.assertEquals(1, purchases.size.toLong()) + val purchase = purchases[0] + Assert.assertEquals("product name", purchase.sku) + Assert.assertNull( + purchase.purchaseProperties.properties[CommerceEventUtils.Constants.ATT_ACTION_CURRENCY_CODE], + ) + } + + @Test + fun testPurchase_Forward_product_name_When_flag_IS_FALSE() { + var settings = HashMap() + settings[AppboyKit.APPBOY_KEY] = "key" + settings[AppboyKit.REPLACE_SKU_AS_PRODUCT_NAME] = "False" + val kit = MockAppboyKit() + + kit.configuration = + KitConfiguration.createKitConfiguration(JSONObject().put("as", settings)) + kit.onKitCreate(settings, MockContextApplication()) + val product = + Product + .Builder("product name", "sku1", 4.5) + .build() + val commerceEvent = + CommerceEvent + .Builder(Product.CHECKOUT, product) + .currency("Moon Dollars") + .build() + kit.logTransaction(commerceEvent, product) + val braze = Braze + val purchases = braze.purchases + Assert.assertEquals(1, purchases.size.toLong()) + val purchase = purchases[0] + Assert.assertEquals("sku1", purchase.sku) + Assert.assertNull( + purchase.purchaseProperties.properties[CommerceEventUtils.Constants.ATT_ACTION_CURRENCY_CODE], + ) + } + + @Test + fun testPurchase_Forward_product_name_When_flag_IS_Null() { + var settings = HashMap() + settings[AppboyKit.APPBOY_KEY] = "key" + val kit = MockAppboyKit() + + kit.configuration = + KitConfiguration.createKitConfiguration(JSONObject().put("as", settings)) + kit.onKitCreate(settings, MockContextApplication()) + val product = + Product + .Builder("product name", "sku1", 4.5) + .build() + val commerceEvent = + CommerceEvent + .Builder(Product.CHECKOUT, product) + .currency("Moon Dollars") + .build() + kit.logTransaction(commerceEvent, product) + val braze = Braze + val purchases = braze.purchases + Assert.assertEquals(1, purchases.size.toLong()) + val purchase = purchases[0] + Assert.assertEquals("sku1", purchase.sku) + Assert.assertNull( + purchase.purchaseProperties.properties[CommerceEventUtils.Constants.ATT_ACTION_CURRENCY_CODE], + ) + } +} diff --git a/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/BrazePurchase.kt b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/BrazePurchase.kt new file mode 100644 index 000000000..93de4c921 --- /dev/null +++ b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/BrazePurchase.kt @@ -0,0 +1,12 @@ +package com.mparticle.kits + +import com.braze.models.outgoing.BrazeProperties +import java.math.BigDecimal + +data class BrazePurchase( + val sku: String, + val currency: String, + val unitPrice: BigDecimal, + val quantity: Int, + val purchaseProperties: BrazeProperties, +) diff --git a/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/TypeDetectionTests.kt b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/TypeDetectionTests.kt new file mode 100644 index 000000000..c9a3ab91b --- /dev/null +++ b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/TypeDetectionTests.kt @@ -0,0 +1,91 @@ +package com.mparticle.kits + +import com.mparticle.kits.AppboyKit.StringTypeParser +import org.junit.Assert +import org.junit.Test + +class TypeDetectionTests { + @Test + fun testEnableTypeDetection() { + val parser = SomeParser(true) + Assert.assertEquals("foo", parser.parseValue("key", "foo")) + Assert.assertEquals(1, parser.parseValue("key", "1")) + Assert.assertEquals(-99, parser.parseValue("key", "-99")) + Assert.assertEquals(Int.MAX_VALUE, parser.parseValue("key", Int.MAX_VALUE.toString())) + Assert.assertEquals(Int.MIN_VALUE, parser.parseValue("key", Int.MIN_VALUE.toString())) + Assert.assertEquals( + Int.MAX_VALUE + 1L, + parser.parseValue("key", (Int.MAX_VALUE + 1L).toString()), + ) + Assert.assertEquals( + Int.MIN_VALUE - 1L, + parser.parseValue("key", (Int.MIN_VALUE - 1L).toString()), + ) + Assert.assertEquals(Long.MAX_VALUE, parser.parseValue("key", Long.MAX_VALUE.toString())) + Assert.assertEquals(Long.MIN_VALUE, parser.parseValue("key", Long.MIN_VALUE.toString())) + Assert.assertEquals(432.2561, parser.parseValue("key", "432.2561")) + Assert.assertEquals(-1.0001, parser.parseValue("key", "-1.0001")) + Assert.assertEquals(false, parser.parseValue("key", "false")) + Assert.assertEquals(true, parser.parseValue("key", "True")) + Assert.assertTrue(parser.parseValue("key", "1.0") is Double) + Assert.assertTrue(parser.parseValue("key", (Int.MAX_VALUE + 1L).toString()) is Long) + Assert.assertTrue(parser.parseValue("key", Int.MAX_VALUE.toString()) is Int) + Assert.assertTrue(parser.parseValue("key", "0") is Int) + Assert.assertTrue(parser.parseValue("key", "true") is Boolean) + Assert.assertTrue(parser.parseValue("key", "True") is Boolean) + } + + @Test + fun testDisableTypeDetection() { + val parser = SomeParser(false) + Assert.assertEquals("foo", parser.parseValue("key", "foo")) + Assert.assertEquals("1", parser.parseValue("key", "1")) + Assert.assertEquals( + (Int.MAX_VALUE + 1L).toString(), + parser.parseValue("key", (Int.MAX_VALUE + 1L).toString()), + ) + Assert.assertEquals("432.2561", parser.parseValue("key", "432.2561")) + Assert.assertEquals("true", parser.parseValue("key", "true")) + } + + private inner class SomeParser internal constructor( + enableTypeDetection: Boolean?, + ) : StringTypeParser( + enableTypeDetection!!, + ) { + override fun toString( + key: String, + value: String, + ) { + // do nothing + } + + override fun toInt( + key: String, + value: Int, + ) { + // do nothing + } + + override fun toLong( + key: String, + value: Long, + ) { + // do nothing + } + + override fun toDouble( + key: String, + value: Double, + ) { + // do nothing + } + + override fun toBoolean( + key: String, + value: Boolean, + ) { + // do nothing + } + } +} diff --git a/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockAppboyKit.kt b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockAppboyKit.kt new file mode 100644 index 000000000..f96faa2c2 --- /dev/null +++ b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockAppboyKit.kt @@ -0,0 +1,29 @@ +package com.mparticle.kits.mocks + +import android.content.Context +import com.mparticle.internal.ReportingManager +import com.mparticle.kits.AppboyKit +import org.mockito.Mockito + +class MockAppboyKit : AppboyKit() { + val calledAuthority = arrayOfNulls(1) + + override fun setAuthority(authority: String?) { + calledAuthority[0] = authority + } + + override fun queueDataFlush() { + // do nothing + } + + init { + kitManager = + MockKitManagerImpl( + Mockito.mock(Context::class.java), + Mockito.mock( + ReportingManager::class.java, + ), + MockCoreCallbacks(), + ) + } +} diff --git a/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockApplication.kt b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockApplication.kt new file mode 100644 index 000000000..be9dc8b59 --- /dev/null +++ b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockApplication.kt @@ -0,0 +1,39 @@ +package com.mparticle.kits.mocks + +import android.app.Application +import android.content.Context +import android.content.SharedPreferences +import android.content.pm.ApplicationInfo +import android.content.pm.PackageManager +import android.content.res.Resources + +class MockApplication( + var mContext: MockContext, +) : Application() { + var mCallbacks: ActivityLifecycleCallbacks? = null + + override fun registerActivityLifecycleCallbacks(callback: ActivityLifecycleCallbacks) { + mCallbacks = callback + } + + override fun getApplicationContext(): Context = this + + fun setSharedPreferences(prefs: SharedPreferences) { + mContext.setSharedPreferences(prefs) + } + + override fun getSystemService(name: String): Any? = mContext.getSystemService(name) + + override fun getSharedPreferences( + name: String, + mode: Int, + ): SharedPreferences = mContext.getSharedPreferences(name, mode) + + override fun getPackageManager(): PackageManager = mContext.packageManager + + override fun getPackageName(): String = mContext.packageName + + override fun getApplicationInfo(): ApplicationInfo = mContext.applicationInfo + + override fun getResources(): Resources? = mContext.resources +} diff --git a/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockContext.kt b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockContext.kt new file mode 100644 index 000000000..1d620778e --- /dev/null +++ b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockContext.kt @@ -0,0 +1,500 @@ +package com.mparticle.kits.mocks + +import android.content.BroadcastReceiver +import android.content.ComponentName +import android.content.ContentResolver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.content.IntentSender +import android.content.IntentSender.SendIntentException +import android.content.ServiceConnection +import android.content.SharedPreferences +import android.content.pm.ApplicationInfo +import android.content.pm.PackageInfo +import android.content.pm.PackageManager +import android.content.pm.PackageManager.NameNotFoundException +import android.content.res.AssetManager +import android.content.res.Configuration +import android.content.res.Resources +import android.content.res.Resources.Theme +import android.database.DatabaseErrorHandler +import android.database.sqlite.SQLiteDatabase +import android.database.sqlite.SQLiteDatabase.CursorFactory +import android.graphics.Bitmap +import android.graphics.drawable.Drawable +import android.net.Uri +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.os.UserHandle +import android.telephony.TelephonyManager +import android.view.Display +import junit.framework.Assert +import org.mockito.Mockito +import java.io.File +import java.io.FileInputStream +import java.io.FileNotFoundException +import java.io.FileOutputStream +import java.io.IOException +import java.io.InputStream + +class MockContext : Context() { + private var sharedPreferences: SharedPreferences = MockSharedPreferences() + private var resources: Resources = MockResources() + var application: MockApplication? = null + + fun setSharedPreferences(prefs: SharedPreferences) { + sharedPreferences = prefs + } + + override fun getApplicationContext(): Context { + if (application == null) { + application = MockApplication(this) + } + return application as MockApplication + } + + override fun checkCallingOrSelfPermission(permission: String): Int = PackageManager.PERMISSION_GRANTED + + override fun getSharedPreferences( + name: String, + mode: Int, + ): SharedPreferences = sharedPreferences + + override fun getResources(): Resources? = resources + + override fun getSystemService(name: String): Any? = + if (name == TELEPHONY_SERVICE) { + Mockito.mock(TelephonyManager::class.java) + } else { + null + } + + override fun getPackageManager(): PackageManager { + val manager = Mockito.mock(PackageManager::class.java) + val info = Mockito.mock(PackageInfo::class.java) + info.versionName = "42" + info.versionCode = 42 + val appInfo = Mockito.mock(ApplicationInfo::class.java) + try { + Mockito + .`when`(manager.getPackageInfo(Mockito.anyString(), Mockito.anyInt())) + .thenReturn(info) + Mockito + .`when`(manager.getInstallerPackageName(Mockito.anyString())) + .thenReturn("com.mparticle.test.installer") + Mockito + .`when`(manager.getApplicationInfo(Mockito.anyString(), Mockito.anyInt())) + .thenReturn(appInfo) + Mockito.`when`(manager.getApplicationLabel(appInfo)).thenReturn("test label") + } catch (e: Exception) { + Assert.fail(e.toString()) + } + return manager + } + + override fun getPackageName(): String = "com.mparticle.test" + + override fun getApplicationInfo(): ApplicationInfo = ApplicationInfo() + + /** + * Stubbed methods + */ + override fun setTheme(resid: Int) {} + + override fun getTheme(): Theme? = null + + override fun getClassLoader(): ClassLoader? = null + + override fun sendBroadcast(intent: Intent) {} + + override fun sendBroadcast( + intent: Intent, + receiverPermission: String?, + ) {} + + override fun sendOrderedBroadcast( + intent: Intent, + receiverPermission: String?, + ) {} + + override fun sendOrderedBroadcast( + intent: Intent, + receiverPermission: String?, + resultReceiver: BroadcastReceiver?, + scheduler: Handler?, + initialCode: Int, + initialData: String?, + initialExtras: Bundle?, + ) { + } + + override fun sendBroadcastAsUser( + intent: Intent, + user: UserHandle, + ) {} + + override fun sendBroadcastAsUser( + intent: Intent, + user: UserHandle, + receiverPermission: String?, + ) { + } + + override fun sendOrderedBroadcastAsUser( + intent: Intent, + user: UserHandle, + receiverPermission: String?, + resultReceiver: BroadcastReceiver, + scheduler: Handler?, + initialCode: Int, + initialData: String?, + initialExtras: Bundle?, + ) { + } + + override fun sendStickyBroadcast(intent: Intent) {} + + override fun sendStickyOrderedBroadcast( + intent: Intent, + resultReceiver: BroadcastReceiver, + scheduler: Handler?, + initialCode: Int, + initialData: String?, + initialExtras: Bundle?, + ) { + } + + override fun removeStickyBroadcast(intent: Intent) {} + + override fun sendStickyBroadcastAsUser( + intent: Intent, + user: UserHandle, + ) {} + + override fun sendStickyOrderedBroadcastAsUser( + intent: Intent, + user: UserHandle, + resultReceiver: BroadcastReceiver, + scheduler: Handler?, + initialCode: Int, + initialData: String?, + initialExtras: Bundle?, + ) { + } + + override fun removeStickyBroadcastAsUser( + intent: Intent, + user: UserHandle, + ) {} + + override fun registerReceiver( + receiver: BroadcastReceiver?, + filter: IntentFilter, + ): Intent? = null + + override fun registerReceiver( + receiver: BroadcastReceiver?, + filter: IntentFilter, + flags: Int, + ): Intent? = null + + override fun registerReceiver( + receiver: BroadcastReceiver, + filter: IntentFilter, + broadcastPermission: String?, + scheduler: Handler?, + ): Intent? = null + + override fun registerReceiver( + receiver: BroadcastReceiver, + filter: IntentFilter, + broadcastPermission: String?, + scheduler: Handler?, + flags: Int, + ): Intent? = null + + override fun unregisterReceiver(receiver: BroadcastReceiver) {} + + override fun startService(service: Intent): ComponentName? = null + + override fun startForegroundService(service: Intent): ComponentName? = null + + override fun stopService(service: Intent): Boolean = false + + override fun bindService( + service: Intent, + conn: ServiceConnection, + flags: Int, + ): Boolean = false + + override fun unbindService(conn: ServiceConnection) {} + + override fun startInstrumentation( + className: ComponentName, + profileFile: String?, + arguments: Bundle?, + ): Boolean = false + + override fun checkSelfPermission(permission: String): Int = 0 + + override fun enforcePermission( + permission: String, + pid: Int, + uid: Int, + message: String?, + ) {} + + override fun enforceCallingPermission( + permission: String, + message: String?, + ) {} + + override fun enforceCallingOrSelfPermission( + permission: String, + message: String?, + ) {} + + override fun grantUriPermission( + toPackage: String, + uri: Uri, + modeFlags: Int, + ) {} + + override fun revokeUriPermission( + uri: Uri, + modeFlags: Int, + ) {} + + override fun revokeUriPermission( + toPackage: String, + uri: Uri, + modeFlags: Int, + ) {} + + override fun checkUriPermission( + uri: Uri, + pid: Int, + uid: Int, + modeFlags: Int, + ): Int = 0 + + override fun checkCallingUriPermission( + uri: Uri, + modeFlags: Int, + ): Int = 0 + + override fun checkCallingOrSelfUriPermission( + uri: Uri, + modeFlags: Int, + ): Int = 0 + + override fun checkUriPermission( + uri: Uri?, + readPermission: String?, + writePermission: String?, + pid: Int, + uid: Int, + modeFlags: Int, + ): Int = 0 + + override fun enforceUriPermission( + uri: Uri, + pid: Int, + uid: Int, + modeFlags: Int, + message: String, + ) { + } + + override fun enforceCallingUriPermission( + uri: Uri, + modeFlags: Int, + message: String, + ) {} + + override fun enforceCallingOrSelfUriPermission( + uri: Uri, + modeFlags: Int, + message: String, + ) {} + + override fun enforceUriPermission( + uri: Uri?, + readPermission: String?, + writePermission: String?, + pid: Int, + uid: Int, + modeFlags: Int, + message: String?, + ) { + } + + @Throws(NameNotFoundException::class) + override fun createPackageContext( + packageName: String, + flags: Int, + ): Context? = null + + @Throws(NameNotFoundException::class) + override fun createContextForSplit(splitName: String): Context? = null + + override fun createConfigurationContext(overrideConfiguration: Configuration): Context? = null + + override fun createDisplayContext(display: Display): Context? = null + + override fun createDeviceProtectedStorageContext(): Context? = null + + override fun isDeviceProtectedStorage(): Boolean = false + + override fun moveSharedPreferencesFrom( + sourceContext: Context, + name: String, + ): Boolean = false + + override fun deleteSharedPreferences(name: String): Boolean = false + + @Throws(FileNotFoundException::class) + override fun openFileInput(name: String): FileInputStream? = null + + @Throws(FileNotFoundException::class) + override fun openFileOutput( + name: String, + mode: Int, + ): FileOutputStream? = null + + override fun deleteFile(name: String): Boolean = false + + override fun getFileStreamPath(name: String): File? = null + + override fun getDataDir(): File? = null + + override fun getFilesDir(): File? = null + + override fun getNoBackupFilesDir(): File? = null + + override fun getExternalFilesDir(type: String?): File? = null + + override fun getExternalFilesDirs(type: String): Array = arrayOfNulls(0) + + override fun getObbDir(): File? = null + + override fun getObbDirs(): Array = arrayOfNulls(0) + + override fun getCacheDir(): File? = null + + override fun getCodeCacheDir(): File? = null + + override fun getExternalCacheDir(): File? = null + + override fun getExternalCacheDirs(): Array = arrayOfNulls(0) + + override fun getExternalMediaDirs(): Array = arrayOfNulls(0) + + override fun fileList(): Array = arrayOfNulls(0) + + override fun getDir( + name: String, + mode: Int, + ): File? = null + + override fun openOrCreateDatabase( + name: String, + mode: Int, + factory: CursorFactory, + ): SQLiteDatabase? = null + + override fun openOrCreateDatabase( + name: String, + mode: Int, + factory: CursorFactory, + errorHandler: DatabaseErrorHandler?, + ): SQLiteDatabase? = null + + override fun moveDatabaseFrom( + sourceContext: Context, + name: String, + ): Boolean = false + + override fun deleteDatabase(name: String): Boolean = false + + override fun getDatabasePath(name: String): File? = null + + override fun databaseList(): Array = arrayOfNulls(0) + + override fun getWallpaper(): Drawable? = null + + override fun peekWallpaper(): Drawable? = null + + override fun getWallpaperDesiredMinimumWidth(): Int = 0 + + override fun getWallpaperDesiredMinimumHeight(): Int = 0 + + @Throws(IOException::class) + override fun setWallpaper(bitmap: Bitmap) { + } + + @Throws(IOException::class) + override fun setWallpaper(data: InputStream) { + } + + @Throws(IOException::class) + override fun clearWallpaper() { + } + + override fun startActivity(intent: Intent) {} + + override fun startActivity( + intent: Intent, + options: Bundle?, + ) {} + + override fun startActivities(intents: Array) {} + + override fun startActivities( + intents: Array, + options: Bundle, + ) {} + + @Throws(SendIntentException::class) + override fun startIntentSender( + intent: IntentSender, + fillInIntent: Intent?, + flagsMask: Int, + flagsValues: Int, + extraFlags: Int, + ) { + } + + @Throws(SendIntentException::class) + override fun startIntentSender( + intent: IntentSender, + fillInIntent: Intent?, + flagsMask: Int, + flagsValues: Int, + extraFlags: Int, + options: Bundle?, + ) { + } + + override fun getSystemServiceName(serviceClass: Class<*>): String? = null + + override fun checkPermission( + permission: String, + pid: Int, + uid: Int, + ): Int = 0 + + override fun checkCallingPermission(permission: String): Int = 0 + + override fun getContentResolver(): ContentResolver? = null + + override fun getMainLooper(): Looper? = null + + override fun getPackageResourcePath(): String? = null + + override fun getPackageCodePath(): String? = null + + override fun getAssets(): AssetManager? = null +} diff --git a/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockContextApplication.kt b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockContextApplication.kt new file mode 100644 index 000000000..274af78e9 --- /dev/null +++ b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockContextApplication.kt @@ -0,0 +1,19 @@ +package com.mparticle.kits.mocks + +import android.app.Application +import android.app.Application.ActivityLifecycleCallbacks +import android.content.Context +import android.content.SharedPreferences + +class MockContextApplication : Application() { + override fun getApplicationContext(): Context = this + + override fun getSharedPreferences( + name: String, + mode: Int, + ): SharedPreferences = MockSharedPreferences() + + override fun registerActivityLifecycleCallbacks(callback: ActivityLifecycleCallbacks) { + // do nothing + } +} diff --git a/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockCoreCallbacks.kt b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockCoreCallbacks.kt new file mode 100644 index 000000000..fe538f4d5 --- /dev/null +++ b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockCoreCallbacks.kt @@ -0,0 +1,70 @@ +package com.mparticle.kits.mocks + +import android.app.Activity +import android.net.Uri +import com.mparticle.MParticleOptions.DataplanOptions +import com.mparticle.internal.CoreCallbacks +import com.mparticle.internal.CoreCallbacks.KitListener +import org.json.JSONArray +import java.lang.ref.WeakReference + +class MockCoreCallbacks : CoreCallbacks { + override fun isBackgrounded(): Boolean = false + + override fun getUserBucket(): Int = 0 + + override fun isEnabled(): Boolean = false + + override fun setIntegrationAttributes( + kitId: Int, + integrationAttributes: Map, + ) {} + + override fun getIntegrationAttributes(kitId: Int): Map? = null + + override fun getCurrentActivity(): WeakReference? = null + + override fun getLatestKitConfiguration(): JSONArray? = null + + override fun getDataplanOptions(): DataplanOptions? = null + + override fun isPushEnabled(): Boolean = false + + override fun getPushSenderId(): String? = null + + override fun getPushInstanceId(): String? = null + + override fun getLaunchUri(): Uri? = null + + override fun getLaunchAction(): String? = null + + override fun getKitListener(): KitListener = + object : KitListener { + override fun kitFound(kitId: Int) {} + + override fun kitConfigReceived( + kitId: Int, + configuration: String?, + ) {} + + override fun kitExcluded( + kitId: Int, + reason: String?, + ) {} + + override fun kitStarted(kitId: Int) {} + + override fun onKitApiCalled( + kitId: Int, + used: Boolean?, + vararg objects: Any?, + ) {} + + override fun onKitApiCalled( + methodName: String?, + kitId: Int, + used: Boolean?, + vararg objects: Any?, + ) {} + } +} diff --git a/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockKitConfiguration.kt b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockKitConfiguration.kt new file mode 100644 index 000000000..556310a0a --- /dev/null +++ b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockKitConfiguration.kt @@ -0,0 +1,84 @@ +package com.mparticle.kits.mocks + +import android.util.SparseBooleanArray +import com.mparticle.internal.Logger +import com.mparticle.kits.KitConfiguration +import org.json.JSONException +import org.json.JSONObject +import java.util.HashMap +import kotlin.Throws + +open class MockKitConfiguration : KitConfiguration() { + @Throws(JSONException::class) + override fun parseConfiguration(json: JSONObject): KitConfiguration { + mTypeFilters = MockSparseBooleanArray() + mNameFilters = MockSparseBooleanArray() + mAttributeFilters = MockSparseBooleanArray() + mScreenNameFilters = MockSparseBooleanArray() + mScreenAttributeFilters = MockSparseBooleanArray() + mUserIdentityFilters = MockSparseBooleanArray() + mUserAttributeFilters = MockSparseBooleanArray() + mCommerceAttributeFilters = MockSparseBooleanArray() + mCommerceEntityFilters = MockSparseBooleanArray() + return super.parseConfiguration(json) + } + + override fun convertToSparseArray(json: JSONObject): SparseBooleanArray { + val map: SparseBooleanArray = MockSparseBooleanArray() + val iterator = json.keys() + while (iterator.hasNext()) { + try { + val key = iterator.next().toString() + map.put(key.toInt(), json.getInt(key) == 1) + } catch (jse: JSONException) { + Logger.error("Issue while parsing kit configuration: " + jse.message) + } + } + return map + } + + internal inner class MockSparseBooleanArray : SparseBooleanArray() { + override fun get(key: Int): Boolean = get(key, false) + + override fun get( + key: Int, + valueIfKeyNotFound: Boolean, + ): Boolean { + print("SparseArray getting: $key") + return if (map.containsKey(key)) { + true + } else { + valueIfKeyNotFound + } + } + + var map: MutableMap = HashMap() + + override fun put( + key: Int, + value: Boolean, + ) { + map[key] = value + } + + override fun clear() { + map.clear() + } + + override fun size(): Int = map.size + + override fun toString(): String = map.toString() + } + + companion object { + @Throws(JSONException::class) + fun createKitConfiguration(json: JSONObject): KitConfiguration = MockKitConfiguration().parseConfiguration(json) + + @Throws(JSONException::class) + fun createKitConfiguration(): KitConfiguration { + val jsonObject = JSONObject() + jsonObject.put("id", 42) + return MockKitConfiguration().parseConfiguration(jsonObject) + } + } +} diff --git a/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockKitManagerImpl.kt b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockKitManagerImpl.kt new file mode 100644 index 000000000..d4a03754b --- /dev/null +++ b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockKitManagerImpl.kt @@ -0,0 +1,71 @@ +package com.mparticle.kits.mocks + +import android.content.Context +import com.mparticle.MParticleOptions +import com.mparticle.internal.CoreCallbacks +import com.mparticle.internal.CoreCallbacks.KitListener +import com.mparticle.internal.ReportingManager +import com.mparticle.kits.KitConfiguration +import com.mparticle.kits.KitManagerImpl +import org.json.JSONException +import org.json.JSONObject +import org.mockito.Mockito +import kotlin.Throws + +class MockKitManagerImpl( + context: Context?, + reportingManager: ReportingManager?, + coreCallbacks: CoreCallbacks?, +) : KitManagerImpl( + context, + reportingManager, + coreCallbacks, + Mockito.mock( + MParticleOptions::class.java, + ), +) { + constructor() : this( + MockContext(), + Mockito.mock(ReportingManager::class.java), + Mockito.mock( + CoreCallbacks::class.java, + ), + ) { + Mockito.`when`(mCoreCallbacks.getKitListener()).thenReturn( + object : KitListener { + override fun kitFound(kitId: Int) {} + + override fun kitConfigReceived( + kitId: Int, + configuration: String?, + ) {} + + override fun kitExcluded( + kitId: Int, + reason: String?, + ) {} + + override fun kitStarted(kitId: Int) {} + + override fun onKitApiCalled( + kitId: Int, + used: Boolean?, + vararg objects: Any?, + ) {} + + override fun onKitApiCalled( + methodName: String?, + kitId: Int, + used: Boolean?, + vararg objects: Any?, + ) {} + }, + ) + } + + @Throws(JSONException::class) + override fun createKitConfiguration(configuration: JSONObject): KitConfiguration = + MockKitConfiguration.createKitConfiguration(configuration) + + override fun getUserBucket(): Int = 50 +} diff --git a/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockResources.kt b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockResources.kt new file mode 100644 index 000000000..4b2dca6ba --- /dev/null +++ b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockResources.kt @@ -0,0 +1,40 @@ +package com.mparticle.kits.mocks + +import android.content.res.Resources +import android.content.res.Resources.NotFoundException +import kotlin.Throws + +class MockResources : Resources(null, null, null) { + override fun getIdentifier( + name: String, + defType: String, + defPackage: String, + ): Int { + if (name == "mp_key") { + return 1 + } else if (name == "mp_secret") { + return 2 + } + return 0 + } + + @Throws(NotFoundException::class) + override fun getString(id: Int): String { + when (id) { + 1 -> return testAppKey + 2 -> return testAppSecret + } + return "" + } + + @Throws(NotFoundException::class) + override fun getString( + id: Int, + vararg formatArgs: Any, + ): String = super.getString(id, *formatArgs) + + companion object { + var testAppKey = "the app key" + var testAppSecret = "the app secret" + } +} diff --git a/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockSharedPreferences.kt b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockSharedPreferences.kt new file mode 100644 index 000000000..70f560949 --- /dev/null +++ b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockSharedPreferences.kt @@ -0,0 +1,88 @@ +package com.mparticle.kits.mocks + +import android.content.SharedPreferences +import android.content.SharedPreferences.Editor +import android.content.SharedPreferences.OnSharedPreferenceChangeListener +import java.util.TreeSet + +class MockSharedPreferences : + SharedPreferences, + Editor { + override fun getAll(): Map? = null + + override fun getString( + key: String, + defValue: String?, + ): String = "" + + override fun getStringSet( + key: String, + defValues: Set?, + ): Set = TreeSet() + + override fun getInt( + key: String, + defValue: Int, + ): Int = 0 + + override fun getLong( + key: String, + defValue: Long, + ): Long = 0 + + override fun getFloat( + key: String, + defValue: Float, + ): Float = 0f + + override fun getBoolean( + key: String, + defValue: Boolean, + ): Boolean = false + + override fun contains(key: String): Boolean = false + + override fun edit(): Editor = this + + override fun registerOnSharedPreferenceChangeListener(listener: OnSharedPreferenceChangeListener) {} + + override fun unregisterOnSharedPreferenceChangeListener(listener: OnSharedPreferenceChangeListener) {} + + override fun putString( + key: String, + value: String?, + ): Editor = this + + override fun putStringSet( + key: String, + values: Set?, + ): Editor = this + + override fun putInt( + key: String, + value: Int, + ): Editor = this + + override fun putLong( + key: String, + value: Long, + ): Editor = this + + override fun putFloat( + key: String, + value: Float, + ): Editor = this + + override fun putBoolean( + key: String, + value: Boolean, + ): Editor = this + + override fun remove(key: String): Editor = this + + override fun clear(): Editor = this + + override fun commit(): Boolean = false + + override fun apply() {} +} diff --git a/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockUser.kt b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockUser.kt new file mode 100644 index 000000000..35125bb28 --- /dev/null +++ b/kits/braze/braze-39/src/test/kotlin/com/mparticle/kits/mocks/MockUser.kt @@ -0,0 +1,53 @@ +package com.mparticle.kits.mocks + +import com.mparticle.MParticle.IdentityType +import com.mparticle.UserAttributeListenerType +import com.mparticle.audience.AudienceResponse +import com.mparticle.audience.AudienceTask +import com.mparticle.consent.ConsentState +import com.mparticle.identity.MParticleUser + +class MockUser( + var identities: Map, +) : MParticleUser { + override fun getId(): Long = 0 + + override fun getUserAttributes(): Map = mapOf() + + override fun getUserAttributes(p0: UserAttributeListenerType?): MutableMap? = null + + override fun setUserAttributes(map: Map): Boolean = false + + override fun getUserIdentities(): Map = identities + + override fun setUserAttribute( + s: String, + o: Any, + ): Boolean = false + + override fun setUserAttributeList( + s: String, + o: Any, + ): Boolean = false + + override fun incrementUserAttribute( + p0: String, + p1: Number?, + ): Boolean = false + + override fun removeUserAttribute(s: String): Boolean = false + + override fun setUserTag(s: String): Boolean = false + + override fun getConsentState(): ConsentState = consentState + + override fun setConsentState(consentState: ConsentState?) {} + + override fun isLoggedIn(): Boolean = false + + override fun getFirstSeenTime(): Long = 0 + + override fun getLastSeenTime(): Long = 0 + + override fun getUserAudiences(): AudienceTask = throw NotImplementedError("getUserAudiences() is not implemented") +} diff --git a/settings-kits.gradle b/settings-kits.gradle index a12f3c55a..5316a726a 100644 --- a/settings-kits.gradle +++ b/settings-kits.gradle @@ -9,6 +9,7 @@ include ( ':kits:apptimize:apptimize-3', //blueshift hosts kit ':kits:braze:braze-38', + ':kits:braze:braze-39', ':kits:branch:branch-5', ':kits:clevertap:clevertap-7', ':kits:comscore:comscore-6', From be6fb58ab100b56a5745a2e05e036b7965373a6e Mon Sep 17 00:00:00 2001 From: Denis Chilik Date: Fri, 13 Mar 2026 12:07:45 -0400 Subject: [PATCH 2/2] feat: update Braze 39 SDK to 39.0.0 --- kits/braze/braze-39/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kits/braze/braze-39/build.gradle b/kits/braze/braze-39/build.gradle index b00ecfc9d..ffeff9f1d 100644 --- a/kits/braze/braze-39/build.gradle +++ b/kits/braze/braze-39/build.gradle @@ -67,6 +67,6 @@ repositories { dependencies { compileOnly 'com.google.firebase:firebase-messaging:[10.2.1, )' - api 'com.braze:android-sdk-ui:37.0.0' + api 'com.braze:android-sdk-ui:39.0.0' testImplementation files('libs/java-json.jar') }