diff --git a/.github/workflows/build-sample-apps.yml b/.github/workflows/build-sample-apps.yml
index 6cfb64c..5669fe3 100644
--- a/.github/workflows/build-sample-apps.yml
+++ b/.github/workflows/build-sample-apps.yml
@@ -112,13 +112,12 @@ jobs:
run: |
cp ".env.example" ".env"
sd 'SITE_ID=.*' "SITE_ID=${{ secrets[format('CUSTOMERIO_{0}_WORKSPACE_SITE_ID', matrix.sample-app)] }}" ".env"
- sd 'API_KEY=.*' "API_KEY=${{ secrets[format('CUSTOMERIO_{0}_WORKSPACE_API_KEY', matrix.sample-app)] }}" ".env"
+ sd 'CDP_API_KEY=.*' "CDP_API_KEY=${{ secrets[format('CUSTOMERIO_{0}_WORKSPACE_CDP_API_KEY', matrix.sample-app)] }}" ".env"
- name: Setup workspace credentials in iOS environment files
run: |
cp "ios/Env.swift.example" "ios/Env.swift"
- sd 'siteId: String = ".*"' "siteId: String = \"${{ secrets[format('CUSTOMERIO_{0}_WORKSPACE_SITE_ID', matrix.sample-app)] }}\"" "ios/Env.swift"
- sd 'apiKey: String = ".*"' "apiKey: String = \"${{ secrets[format('CUSTOMERIO_{0}_WORKSPACE_API_KEY', matrix.sample-app)] }}\"" "ios/Env.swift"
+ sd 'cdpApiKey: String = ".*"' "cdpApiKey: String = \"${{ secrets[format('CUSTOMERIO_{0}_WORKSPACE_CDP_API_KEY', matrix.sample-app)] }}\"" "ios/Env.swift"
# Make sure to fetch dependencies only after updating the version numbers and workspace credentials
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
deleted file mode 100644
index 2138ae2..0000000
--- a/.github/workflows/build.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-name: Flutter Build
-
-on:
- push:
- branches: [main]
-# Cancel jobs and just run the last one
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-defaults:
- run:
- working-directory: apps/amiapp_flutter
-
-jobs:
- build_ios:
- name: Build iOS
- runs-on: macos-latest
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-java@v3
- with:
- distribution: 'temurin'
- java-version: '17'
- - name: Install CLI tools used in CI script
- run: |
- brew install sd # used in CI script as an easier to use sed CLI. Replaces text in files.
- - name: Setup workspace credentials in iOS environment files
- run: |
- cp "ios/Env.swift.example" "ios/Env.swift"
- sd 'siteId: String = ".*"' "siteId: String = \"${{ secrets.CUSTOMERIO_AMIAPP_FLUTTER_WORKSPACE_SITE_ID }}\"" "ios/Env.swift"
- sd 'siteId: String = ".*"' "siteId: String = \"${{ secrets.CUSTOMERIO_AMIAPP_FLUTTER_WORKSPACE_API_KEY }}\"" "ios/Env.swift"
- - uses: ./.github/actions/setup-flutter
- - run: flutter build ios --release --no-codesign
-
- build_android:
- name: Build Android
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-java@v3
- with:
- distribution: 'temurin'
- java-version: '17'
- - uses: ./.github/actions/setup-flutter
- - run: flutter build apk --release
diff --git a/.releaserc.json b/.releaserc.json
index 9d9a93a..aa684c1 100644
--- a/.releaserc.json
+++ b/.releaserc.json
@@ -42,7 +42,8 @@
"assets": [
"CHANGELOG.md",
"pubspec.yaml",
- "lib/customer_io_plugin_version.dart"
+ "lib/customer_io_plugin_version.dart",
+ "android/src/main/res/values/customer_io_config.xml"
],
"message": "chore: prepare for ${nextRelease.version}\n\n${nextRelease.notes}"
}
diff --git a/android/build.gradle b/android/build.gradle
index 3f52931..ecc0112 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -18,7 +18,6 @@ rootProject.allprojects {
repositories {
google()
mavenCentral()
- maven { url 'https://maven.gist.build' }
}
}
@@ -59,8 +58,8 @@ android {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// Customer.io SDK
- def cioVersion = "3.11.2"
- implementation "io.customer.android:tracking:$cioVersion"
+ def cioVersion = "4.4.1"
+ implementation "io.customer.android:datapipelines:$cioVersion"
implementation "io.customer.android:messaging-push-fcm:$cioVersion"
implementation "io.customer.android:messaging-in-app:$cioVersion"
}
diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
index cc947c5..9b3b143 100644
--- a/android/src/main/AndroidManifest.xml
+++ b/android/src/main/AndroidManifest.xml
@@ -1 +1,15 @@
-
+
+
+
+
+
+
+
+
diff --git a/android/src/main/kotlin/io/customer/customer_io/CustomerIOExtensions.kt b/android/src/main/kotlin/io/customer/customer_io/CustomerIOExtensions.kt
deleted file mode 100644
index 138a65a..0000000
--- a/android/src/main/kotlin/io/customer/customer_io/CustomerIOExtensions.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-package io.customer.customer_io
-
-import io.flutter.plugin.common.MethodCall
-import io.flutter.plugin.common.MethodChannel
-
-/**
- * Returns the value corresponding to the given key after casting to the generic type provided, or
- * null if such key is not present in the map or value cannot be casted to the given type.
- */
-internal inline fun Map.getAsTypeOrNull(key: String): T? {
- if (containsKey(key)) {
- return get(key) as? T
- }
- return null
-}
-
-/**
- * Invokes lambda method that can be used to call matching native method conveniently. The lambda
- * expression receives function parameters as arguments and should return the desired result. Any
- * exception in the lambda will cause the invoked method to fail with error.
- */
-internal fun MethodCall.invokeNative(
- result: MethodChannel.Result,
- performAction: (params: Map) -> R,
-) {
- try {
- @Suppress("UNCHECKED_CAST")
- val params = this.arguments as? Map ?: emptyMap()
- val actionResult = performAction(params)
- if (actionResult is Unit) {
- result.success(true)
- } else {
- result.success(actionResult)
- }
- } catch (ex: Exception) {
- result.error(this.method, ex.localizedMessage, ex)
- }
-}
diff --git a/android/src/main/kotlin/io/customer/customer_io/CustomerIOPlugin.kt b/android/src/main/kotlin/io/customer/customer_io/CustomerIOPlugin.kt
new file mode 100644
index 0000000..773960c
--- /dev/null
+++ b/android/src/main/kotlin/io/customer/customer_io/CustomerIOPlugin.kt
@@ -0,0 +1,274 @@
+package io.customer.customer_io
+
+import android.app.Application
+import android.content.Context
+import androidx.annotation.NonNull
+import io.customer.customer_io.bridge.NativeModuleBridge
+import io.customer.customer_io.bridge.nativeMapArgs
+import io.customer.customer_io.bridge.nativeNoArgs
+import io.customer.customer_io.messaginginapp.CustomerIOInAppMessaging
+import io.customer.customer_io.messagingpush.CustomerIOPushMessaging
+import io.customer.customer_io.utils.getAs
+import io.customer.sdk.CustomerIO
+import io.customer.sdk.CustomerIOBuilder
+import io.customer.sdk.core.di.SDKComponent
+import io.customer.sdk.core.util.CioLogLevel
+import io.customer.sdk.core.util.Logger
+import io.customer.sdk.data.model.Region
+import io.customer.sdk.events.Metric
+import io.customer.sdk.events.TrackMetric
+import io.customer.sdk.events.serializedName
+import io.flutter.embedding.engine.plugins.FlutterPlugin
+import io.flutter.embedding.engine.plugins.activity.ActivityAware
+import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
+import io.flutter.plugin.common.MethodCall
+import io.flutter.plugin.common.MethodChannel
+import io.flutter.plugin.common.MethodChannel.MethodCallHandler
+import io.flutter.plugin.common.MethodChannel.Result
+
+/**
+ * Android implementation of plugin that will let Flutter developers to
+ * interact with a Android platform
+ * */
+class CustomerIOPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
+ /// The MethodChannel that will the communication between Flutter and native Android
+ ///
+ /// This local reference serves to register the plugin with the Flutter Engine and unregister it
+ /// when the Flutter Engine is detached from the Activity
+ private lateinit var flutterCommunicationChannel: MethodChannel
+ private lateinit var context: Context
+
+ private lateinit var modules: List
+
+ private val logger: Logger = SDKComponent.logger
+
+ override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
+ context = flutterPluginBinding.applicationContext
+ flutterCommunicationChannel =
+ MethodChannel(flutterPluginBinding.binaryMessenger, "customer_io")
+ flutterCommunicationChannel.setMethodCallHandler(this)
+
+ // Initialize modules
+ modules = listOf(
+ CustomerIOPushMessaging(flutterPluginBinding),
+ CustomerIOInAppMessaging(flutterPluginBinding)
+ )
+
+ // Attach modules to engine
+ modules.forEach {
+ it.onAttachedToEngine()
+ }
+ }
+
+ override fun onMethodCall(call: MethodCall, result: Result) {
+ when (call.method) {
+ "clearIdentify" -> call.nativeNoArgs(result, ::clearIdentify)
+ "identify" -> call.nativeMapArgs(result, ::identify)
+ "initialize" -> call.nativeMapArgs(result, ::initialize)
+ "registerDeviceToken" -> call.nativeMapArgs(result, ::registerDeviceToken)
+ "screen" -> call.nativeMapArgs(result, ::screen)
+ "setDeviceAttributes" -> call.nativeMapArgs(result, ::setDeviceAttributes)
+ "setProfileAttributes" -> call.nativeMapArgs(result, ::setProfileAttributes)
+ "track" -> call.nativeMapArgs(result, ::track)
+ "trackMetric" -> call.nativeMapArgs(result, ::trackMetric)
+ else -> result.notImplemented()
+ }
+ }
+
+ private fun clearIdentify() {
+ CustomerIO.instance().clearIdentify()
+ }
+
+ private fun identify(params: Map) {
+ val userId = params.getAs(Args.USER_ID)
+ val traits = params.getAs