Skip to content

Commit 6f726c8

Browse files
Merge pull request #164 from adobe/staging
Updating main from staging
2 parents 8adb270 + 657b8a9 commit 6f726c8

17 files changed

Lines changed: 254 additions & 99 deletions

File tree

.github/workflows/dart.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ jobs:
3737

3838
job2:
3939
name: Build iOS example app
40-
runs-on: macos-13
40+
runs-on: macos-15
4141

4242
steps:
4343
- uses: actions/checkout@v1
4444

4545
- uses: maxim-lobanov/setup-xcode@v1
4646
with:
47-
xcode-version: "15.0.1"
47+
xcode-version: "16.4.0"
4848

4949
- uses: actions/setup-java@v1
5050
with:
@@ -189,4 +189,4 @@ jobs:
189189
- name: Unit test
190190
working-directory: ./plugins/flutter_aepuserprofile
191191
run: flutter test
192-
192+

example/lib/core.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import 'package:flutter/material.dart';
1313
import 'dart:developer';
1414
import 'package:flutter/services.dart';
1515
import 'package:flutter_aepcore/flutter_aepcore.dart';
16-
import 'package:flutter_aepcore/flutter_aepcore_data.dart';
1716
import 'package:flutter_aepcore/flutter_aeplifecycle.dart';
1817
import 'package:flutter_aepcore/flutter_aepsignal.dart';
1918
import 'util.dart';

example/lib/identity.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ governing permissions and limitations under the License.
1212
import 'dart:developer';
1313
import 'package:flutter/material.dart';
1414
import 'package:flutter/services.dart';
15-
import 'package:flutter_aepcore/flutter_aepcore_data.dart';
1615
import 'package:flutter_aepcore/flutter_aepidentity.dart';
1716
import 'util.dart';
1817

example/lib/messaging.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ governing permissions and limitations under the License.
1111

1212
import 'dart:developer';
1313
import 'package:flutter/material.dart';
14-
import 'package:flutter/services.dart';
1514
import 'package:flutter_aepcore/flutter_aepcore.dart';
16-
import 'package:flutter_aepcore/flutter_aepcore_data.dart';
1715
import 'package:flutter_aepmessaging/flutter_aepmessaging.dart';
1816
import 'util.dart';
1917

plugins/flutter_aepcore/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## 5.1.0
2+
* Added `MobileCore.setPushIdentifier` API to the Flutter wrapper.
3+
14
## 5.0.1
25

36
* Add `MobileCore.setApplication` call in Android FlutterPlugin's `onAttachedToEngine` to accurately register lifecycle callbacks for launcher activity.

plugins/flutter_aepcore/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,26 @@ static Future<void> trackState
327327
MobileCore.trackState("myState", data: {"key1": "value1"});
328328
```
329329

330+
### setPushIdentifier
331+
Register a push notification token with the Adobe SDK. Pass `null` to clear a previously registered token.
332+
333+
On **Android**, pass the push token string provided by your push notification service.
334+
On **iOS**, pass the APNs device token as a lowercase hex string. The native bridge converts it to the raw bytes expected by the AEP SDK internally.
335+
336+
**Syntax**
337+
```dart
338+
static Future<void> setPushIdentifier(String? token)
339+
```
340+
341+
**Example**
342+
```dart
343+
// Register a push token
344+
MobileCore.setPushIdentifier(token);
345+
346+
// Clear the push token
347+
MobileCore.setPushIdentifier(null);
348+
```
349+
330350
### Identity
331351

332352
For more information on the Core Identity APIs, visit the documentation [here](https://developer.adobe.com/client-sdks/documentation/mobile-core/identity/).

plugins/flutter_aepcore/android/src/main/java/com/adobe/marketing/mobile/flutter/flutter_aepcore/FlutterAEPCorePlugin.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ public void onMethodCall(MethodCall call, @NonNull Result result) {
9090
} else if ("setAdvertisingIdentifier".equals(call.method)) {
9191
handleSetAdvertisingIdentifier(call.arguments);
9292
result.success(null);
93+
} else if ("setPushIdentifier".equals(call.method)) {
94+
handleSetPushIdentifier(call.arguments);
95+
result.success(null);
9396
} else if ("dispatchEvent".equals(call.method)) {
9497
handleDispatchEvent(result, call.arguments);
9598
} else if ("dispatchEventWithResponseCallback".equals(call.method)) {
@@ -191,6 +194,16 @@ private void handleSetAdvertisingIdentifier(final Object arguments) {
191194
}
192195
}
193196

197+
private void handleSetPushIdentifier(final Object arguments) {
198+
if (arguments == null) {
199+
MobileCore.setPushIdentifier(null);
200+
}
201+
202+
if (arguments instanceof String) {
203+
MobileCore.setPushIdentifier((String) arguments);
204+
}
205+
}
206+
194207
private void handleDispatchEvent(final Result result, final Object arguments) {
195208
if (!(arguments instanceof Map)) {
196209
Log.e(TAG, "Dispatch event failed because arguments were invalid");

plugins/flutter_aepcore/ios/Classes/FlutterAEPCorePlugin.m

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ - (void)handleMethodCall:(FlutterMethodCall *)call
4444
NSString *aid = call.arguments;
4545
[AEPMobileCore setAdvertisingIdentifier:aid];
4646
result(nil);
47+
} else if ([@"setPushIdentifier" isEqualToString:call.method]) {
48+
[self handleSetPushIdentifier:call];
49+
result(nil);
4750
} else if ([@"dispatchEvent" isEqualToString:call.method]) {
4851
[self handleDispatchEvent:call result:result];
4952
} else if ([@"dispatchEventWithResponseCallback"
@@ -198,6 +201,35 @@ - (void)handleResetIdentities:(FlutterMethodCall *)call {
198201
[AEPMobileCore resetIdentities];
199202
}
200203

204+
- (void)handleSetPushIdentifier:(FlutterMethodCall *)call {
205+
if (call.arguments == nil || call.arguments == [NSNull null]) {
206+
[AEPMobileCore setPushIdentifier:nil];
207+
return;
208+
}
209+
210+
// The Dart layer sends the APNs token as a lowercase hex string (e.g. "a1b2c3d4...").
211+
// Convert it back to the original NSData bytes that AEP SDK expects.
212+
NSString *hexString = call.arguments;
213+
NSUInteger length = hexString.length;
214+
if (length % 2 != 0) {
215+
NSLog(@"[FlutterAEPCore] setPushIdentifier - Invalid APNs token: hex string has odd length (%lu), skipping.", (unsigned long)length);
216+
return;
217+
}
218+
NSMutableData *tokenData = [NSMutableData dataWithCapacity:length / 2];
219+
for (NSUInteger i = 0; i < length; i += 2) {
220+
NSString *byteString = [hexString substringWithRange:NSMakeRange(i, 2)];
221+
NSScanner *scanner = [NSScanner scannerWithString:byteString];
222+
unsigned int byte = 0;
223+
if (![scanner scanHexInt:&byte] || !scanner.isAtEnd) {
224+
NSLog(@"[FlutterAEPCore] setPushIdentifier - Invalid APNs token: non-hex character found at index %lu, skipping.", (unsigned long)i);
225+
return;
226+
}
227+
uint8_t byteValue = (uint8_t)byte;
228+
[tokenData appendBytes:&byteValue length:1];
229+
}
230+
[AEPMobileCore setPushIdentifier:tokenData];
231+
}
232+
201233
- (FlutterError *)flutterErrorFromNSError:(NSError *)error {
202234
return [FlutterError
203235
errorWithCode:[NSString stringWithFormat:@"%ld", (long)error.code]

plugins/flutter_aepcore/ios/flutter_aepcore.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = 'flutter_aepcore'
3-
s.version = '5.0.0'
3+
s.version = '5.1.0'
44
s.summary = 'Adobe Experience Platform support for Flutter apps.'
55
s.homepage = 'https://developer.adobe.com/client-sdks'
66
s.license = { :file => '../LICENSE' }

plugins/flutter_aepcore/lib/flutter_aepcore.dart

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ class MobileCore {
2626
/// Initializes the AEP Mobile SDK with the provided initialization options.
2727
/// @param initOptions The [InitOptions] to configure the SDK.
2828
static Future<void> initialize({required InitOptions initOptions}) {
29-
return _channel.invokeMethod<void>('initialize', {'initOptions': initOptions.toMap()});
29+
return _channel
30+
.invokeMethod<void>('initialize', {'initOptions': initOptions.toMap()});
3031
}
3132

3233
/// Initializes the AEP Mobile SDK with the provided App ID.
@@ -69,6 +70,18 @@ class MobileCore {
6970
static Future<void> setAdvertisingIdentifier(String aid) =>
7071
_channel.invokeMethod<void>('setAdvertisingIdentifier', aid);
7172

73+
/// Submits a generic event containing the provided push token with event type `generic.identity`.
74+
///
75+
/// On **Android**, pass the push token string as provided by your push notification service.
76+
/// On **iOS**, pass the APNs device token as a lowercase hex string. The native bridge
77+
/// converts it to the raw bytes expected by the AEP SDK internally.
78+
///
79+
/// Pass `null` to clear a previously registered token.
80+
///
81+
/// @param token The push notification token string. Pass `null` to clear the identifier.
82+
static Future<void> setPushIdentifier(String? token) =>
83+
_channel.invokeMethod<void>('setPushIdentifier', token);
84+
7285
/// 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.
7386
static Future<void> dispatchEvent(Event event) =>
7487
_channel.invokeMethod<void>('dispatchEvent', event.data);

0 commit comments

Comments
 (0)