Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,5 @@ example/android/GeneratedPluginRegistrant.java
**/ios/flutter_export_environment.sh

# podspec.lock for plugins
plugins/**/pubspec.lock
plugins/**/pubspec.lockplugins/flutter_aepcore/android/.project
plugins/flutter_aepcore/android/.settings/
1 change: 0 additions & 1 deletion example/lib/core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import 'package:flutter/material.dart';
import 'dart:developer';
import 'package:flutter/services.dart';
import 'package:flutter_aepcore/flutter_aepcore.dart';
import 'package:flutter_aepcore/flutter_aepcore_data.dart';
import 'package:flutter_aepcore/flutter_aeplifecycle.dart';
import 'package:flutter_aepcore/flutter_aepsignal.dart';
import 'util.dart';
Expand Down
1 change: 0 additions & 1 deletion example/lib/identity.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ governing permissions and limitations under the License.
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_aepcore/flutter_aepcore_data.dart';
import 'package:flutter_aepcore/flutter_aepidentity.dart';
import 'util.dart';

Expand Down
2 changes: 0 additions & 2 deletions example/lib/messaging.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ governing permissions and limitations under the License.

import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_aepcore/flutter_aepcore.dart';
import 'package:flutter_aepcore/flutter_aepcore_data.dart';
import 'package:flutter_aepmessaging/flutter_aepmessaging.dart';
import 'util.dart';

Expand Down
24 changes: 12 additions & 12 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ packages:
dependency: transitive
description:
name: characters
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
url: "https://pub.dev"
source: hosted
version: "1.4.0"
version: "1.4.1"
clock:
dependency: transitive
description:
Expand Down Expand Up @@ -75,7 +75,7 @@ packages:
path: "../plugins/flutter_aepcore"
relative: true
source: path
version: "5.0.0"
version: "5.0.1"
flutter_aepedge:
dependency: "direct main"
description:
Expand Down Expand Up @@ -151,26 +151,26 @@ packages:
dependency: transitive
description:
name: matcher
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
url: "https://pub.dev"
source: hosted
version: "0.12.17"
version: "0.12.19"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
url: "https://pub.dev"
source: hosted
version: "0.11.1"
version: "0.13.0"
meta:
dependency: transitive
description:
name: meta
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
url: "https://pub.dev"
source: hosted
version: "1.16.0"
version: "1.17.0"
path:
dependency: transitive
description:
Expand Down Expand Up @@ -228,10 +228,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
url: "https://pub.dev"
source: hosted
version: "0.7.6"
version: "0.7.10"
vector_math:
dependency: transitive
description:
Expand All @@ -249,5 +249,5 @@ packages:
source: hosted
version: "14.2.5"
sdks:
dart: ">=3.8.0-0 <4.0.0"
dart: ">=3.9.0-0 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"
5 changes: 5 additions & 0 deletions plugins/flutter_aepcore/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 5.0.2
Comment thread
brunogabriel marked this conversation as resolved.
Outdated

* Add `MobileCore.setPushIdentifier` API to register a push notification token string (FCM) with the Adobe SDK on Android and iOS.
* Add `MobileCore.setPushIdentifierWithData` API to register a raw APNs push token (`Uint8List`) on iOS, passing the bytes directly to the native SDK without encoding conversion.

## 5.0.1

* Add `MobileCore.setApplication` call in Android FlutterPlugin's `onAttachedToEngine` to accurately register lifecycle callbacks for launcher activity.
Expand Down
48 changes: 48 additions & 0 deletions plugins/flutter_aepcore/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,54 @@ static Future<void> trackState
MobileCore.trackState("myState", data: {"key1": "value1"});
```

### setPushIdentifier
Register a FCM push token string with the Adobe SDK. Pass `null` to clear a previously registered token.

Use this method on **Android** with the FCM token string from `FirebaseMessaging.instance.getToken()`.
On **iOS**, prefer [setPushIdentifierWithData](#setpushidentifierwithdata) to pass the raw APNs token bytes.

**Syntax**
```dart
static Future<void> setPushIdentifier(String? token)
```

**Example**
```dart
// Android: register FCM token
final token = await FirebaseMessaging.instance.getToken();
MobileCore.setPushIdentifier(token);

// Clear the push token
MobileCore.setPushIdentifier(null);
```

### setPushIdentifierWithData
Register a raw APNs push token (`Uint8List`) with the Adobe SDK. The bytes are passed directly to the native iOS SDK without any encoding conversion.

Use this method on **iOS** with the raw APNs device token obtained from
`FirebaseMessaging.instance.getAPNSToken()` or from the native
`didRegisterForRemoteNotificationsWithDeviceToken` delegate.

On **Android** this method is a no-op — use [setPushIdentifier](#setpushidentifier) instead.

**Syntax**
```dart
static Future<void> setPushIdentifierWithData(Uint8List? tokenData)
```

**Example**
```dart
import 'dart:io';

if (Platform.isIOS) {
final apnsToken = await FirebaseMessaging.instance.getAPNSToken();
MobileCore.setPushIdentifierWithData(apnsToken);
} else {
final fcmToken = await FirebaseMessaging.instance.getToken();
MobileCore.setPushIdentifier(fcmToken);
}
```

### Identity

For more information on the Core Identity APIs, visit the documentation [here](https://developer.adobe.com/client-sdks/documentation/mobile-core/identity/).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ public void onMethodCall(MethodCall call, @NonNull Result result) {
} else if ("setAdvertisingIdentifier".equals(call.method)) {
handleSetAdvertisingIdentifier(call.arguments);
result.success(null);
} else if ("setPushIdentifier".equals(call.method)) {
handleSetPushIdentifier(call.arguments);
result.success(null);
} else if ("setPushIdentifierWithData".equals(call.method)) {
com.adobe.marketing.mobile.services.Log.debug(TAG, AEPCORE_TAG, "setPushIdentifierWithData() is not supported on Android. Use setPushIdentifier() with the FCM token string.");
result.success(null);
} else if ("dispatchEvent".equals(call.method)) {
handleDispatchEvent(result, call.arguments);
} else if ("dispatchEventWithResponseCallback".equals(call.method)) {
Expand Down Expand Up @@ -191,6 +197,16 @@ private void handleSetAdvertisingIdentifier(final Object arguments) {
}
}

private void handleSetPushIdentifier(final Object arguments) {
if (arguments == null) {
MobileCore.setPushIdentifier(null);
}

if (arguments instanceof String) {
MobileCore.setPushIdentifier((String) arguments);
}
}

private void handleDispatchEvent(final Result result, final Object arguments) {
if (!(arguments instanceof Map)) {
Log.e(TAG, "Dispatch event failed because arguments were invalid");
Expand Down
28 changes: 28 additions & 0 deletions plugins/flutter_aepcore/ios/Classes/FlutterAEPCorePlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ - (void)handleMethodCall:(FlutterMethodCall *)call
NSString *aid = call.arguments;
[AEPMobileCore setAdvertisingIdentifier:aid];
result(nil);
} else if ([@"setPushIdentifier" isEqualToString:call.method]) {
[self handleSetPushIdentifier:call];
result(nil);
} else if ([@"setPushIdentifierWithData" isEqualToString:call.method]) {
[self handleSetPushIdentifierWithData:call];
result(nil);
} else if ([@"dispatchEvent" isEqualToString:call.method]) {
[self handleDispatchEvent:call result:result];
} else if ([@"dispatchEventWithResponseCallback"
Expand Down Expand Up @@ -198,6 +204,28 @@ - (void)handleResetIdentities:(FlutterMethodCall *)call {
[AEPMobileCore resetIdentities];
}

- (void)handleSetPushIdentifier:(FlutterMethodCall *)call {
if (call.arguments == nil || call.arguments == [NSNull null]) {
[AEPMobileCore setPushIdentifier:nil];
return;
}

NSString *tokenString = call.arguments;
NSData *token = [tokenString dataUsingEncoding:NSUTF8StringEncoding];
[AEPMobileCore setPushIdentifier:token];
}

- (void)handleSetPushIdentifierWithData:(FlutterMethodCall *)call {
if (call.arguments == nil || call.arguments == [NSNull null]) {
[AEPMobileCore setPushIdentifier:nil];
return;
}

// Flutter sends Uint8List as FlutterStandardTypedData; extract NSData directly.
FlutterStandardTypedData *typedData = call.arguments;
[AEPMobileCore setPushIdentifier:typedData.data];
}

- (FlutterError *)flutterErrorFromNSError:(NSError *)error {
return [FlutterError
errorWithCode:[NSString stringWithFormat:@"%ld", (long)error.code]
Expand Down
36 changes: 35 additions & 1 deletion plugins/flutter_aepcore/lib/flutter_aepcore.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ governing permissions and limitations under the License.
*/

import 'dart:async';
import 'dart:typed_data';

import 'package:flutter/services.dart';
import 'package:flutter_aepcore/flutter_aepcore_data.dart';
Expand All @@ -26,7 +27,8 @@ class MobileCore {
/// Initializes the AEP Mobile SDK with the provided initialization options.
/// @param initOptions The [InitOptions] to configure the SDK.
static Future<void> initialize({required InitOptions initOptions}) {
return _channel.invokeMethod<void>('initialize', {'initOptions': initOptions.toMap()});
return _channel
.invokeMethod<void>('initialize', {'initOptions': initOptions.toMap()});
}

/// Initializes the AEP Mobile SDK with the provided App ID.
Expand Down Expand Up @@ -69,6 +71,38 @@ class MobileCore {
static Future<void> setAdvertisingIdentifier(String aid) =>
_channel.invokeMethod<void>('setAdvertisingIdentifier', aid);

/// Submits a generic event containing the provided push token with event type `generic.identity`.
///
/// Pass `null` to clear the push identifier.
///
/// On **Android**, pass the FCM registration token string obtained from `FirebaseMessaging.getInstance().getToken()`.
///
/// On **iOS**, pass the APNs device token as a **lowercase hex string** (e.g. `"a1b2c3d4..."`).
/// The hex string must be obtained from the raw `Data` token received in
/// `application(_:didRegisterForRemoteNotificationsWithDeviceToken:)` and converted before
/// passing to Flutter (e.g. `deviceToken.map { String(format: "%02x", $0) }.joined()`).
///
/// @param token The push notification token. Pass `null` to clear the identifier.
static Future<void> setPushIdentifier(String? token) =>
_channel.invokeMethod<void>('setPushIdentifier', token);

/// Submits a generic event containing the provided push token (as raw bytes) with event type `generic.identity`.
///
/// Use this method on **iOS** to pass the raw APNs device token (`Data`) obtained from
/// `application(_:didRegisterForRemoteNotificationsWithDeviceToken:)` or from
/// `FirebaseMessaging.instance.getAPNSToken()`.
///
/// The bytes are passed directly to `[AEPMobileCore setPushIdentifier:]` as `NSData` without
/// any encoding conversion, which is the correct behaviour for raw APNs tokens.
///
/// On **Android** this method is a no-op — use [setPushIdentifier] with the FCM token string instead.
///
/// Pass `null` to clear a previously registered token.
///
/// @param tokenData The raw push notification token bytes. Pass `null` to clear the identifier.
static Future<void> setPushIdentifierWithData(Uint8List? tokenData) =>
_channel.invokeMethod<void>('setPushIdentifierWithData', tokenData);

/// Called by the extension public API to dispatch an event for other extensions or the internal SDK to consume. Any events dispatched by this call will not be processed until after `start` has been called.
static Future<void> dispatchEvent(Event event) =>
_channel.invokeMethod<void>('dispatchEvent', event.data);
Expand Down
Loading