Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
3de7299
[DELIVERY-125863] Migrate Flutter plugin to AppsFlyer SDK 7 RPC archi…
af-dudka Jul 29, 2026
d2af13c
[DELIVERY-125863] Fix SDK 7 install-referrer docs and dart format.
af-dudka Jul 29, 2026
effc2d8
[DELIVERY-125863] Align plugin release version with SDK 7.0.1.
af-dudka Jul 29, 2026
51b2141
[DELIVERY-125863] Migrate Flutter plugin to AppsFlyer SDK 7 RPC archi…
af-dudka Aug 10, 2026
69886e8
[DELIVERY-125863] Align internal-docs with SDK 7 RPC implementation a…
af-dudka Aug 10, 2026
78dcf05
[DELIVERY-125863] Apply dart format to CI-failing files
af-dudka Aug 10, 2026
c5f84c2
[DELIVERY-125863] Migrate native plugin implementations to Swift and …
af-dudka Aug 10, 2026
8d4df77
[DELIVERY-125863] Fix Android native events lost after engine teardown
af-dudka Aug 11, 2026
4ddcfa7
[DELIVERY-125863] Harden Android RPC dispatch, lifecycle teardown, an…
af-dudka Aug 11, 2026
655d1bc
[DELIVERY-125863] Bound the iOS pending-event buffer
af-dudka Aug 11, 2026
2820349
[DELIVERY-125863] Replace iOS Objective-C shim with main-actor-checke…
af-dudka Aug 12, 2026
bd8f144
[DELIVERY-125863] Guard iOS event-handler and Purchase Connector tear…
af-dudka Aug 12, 2026
b152ef8
[DELIVERY-125863] Remove pendingLaunchOptions and main-thread RPC com…
af-dudka Aug 12, 2026
a7a6c6d
[DELIVERY-125863] Return RPC data map from unwrapValue default instea…
af-dudka Aug 12, 2026
1d46d56
[DELIVERY-125863] Always enqueue af-events delivery on the main queue…
af-dudka Aug 12, 2026
bb3c54d
[DELIVERY-125863] Guard iOS RPC completions and markBridgeReady after…
af-dudka Aug 12, 2026
84292aa
[DELIVERY-125863] Serialize AppsFlyerAttribution queue state on the m…
af-dudka Aug 12, 2026
d6a4ba5
[DELIVERY-125863] Log AppsFlyerAttribution RPC failures and reset que…
af-dudka Aug 12, 2026
a72cf9d
[DELIVERY-125863] Document ephemeral FlutterFramework SPM dependency …
af-dudka Aug 12, 2026
63c3686
[DELIVERY-125863] Fix iOS plugin version bump in release workflows af…
af-dudka Aug 12, 2026
58bc115
[DELIVERY-125863] Throw AppsFlyerException when generateInviteLink re…
af-dudka Aug 12, 2026
cbb55f1
[DELIVERY-125863] Throw AppsFlyerException when getSdkVersion returns…
af-dudka Aug 12, 2026
6d3b19c
[DELIVERY-125863] Throw AppsFlyerException on unexpected RPC result t…
af-dudka Aug 12, 2026
a9954cf
[DELIVERY-125863] Scope the Android RPC handler to the process so eng…
af-dudka Aug 12, 2026
522afb3
[DELIVERY-125863] Fail fast on missing or non-string af-events event …
af-dudka Aug 12, 2026
ab5883b
[DELIVERY-125863] Test every AFMediationNetwork logAdRevenue RPC mapping
af-dudka Aug 12, 2026
502b2bd
[DELIVERY-125863] Test pluginVersion returns the compiled PLUGIN_VERS…
af-dudka Aug 12, 2026
f61a729
[DELIVERY-125863] Forward init parameters to native RPC without Dart-…
af-dudka Aug 12, 2026
6c9a0d2
[DELIVERY-125863] Route symmetric platform-only getters and setters t…
af-dudka Aug 12, 2026
33d49d0
[DELIVERY-125863] Split RPC helpers and enforce non-null native replies
af-dudka Aug 12, 2026
790f3df
[DELIVERY-125863] Forward setSharingFilterForPartners clear requests …
af-dudka Aug 12, 2026
cc3b053
[DELIVERY-125863] Forward setConsentData payloads to native RPC witho…
af-dudka Aug 12, 2026
2037d31
[DELIVERY-125863] Format appsflyer_sdk_test.dart for CI
af-dudka Aug 12, 2026
177cd43
[DELIVERY-125863] Replace event streams with callback-based register*…
af-dudka Aug 13, 2026
1905fd7
[DELIVERY-125863] Bump Gradle wrapper to 8.14 for Flutter minimum
af-dudka Aug 13, 2026
70dbd6b
[DELIVERY-125863] Bump Android Gradle Plugin to 8.11.1 for Flutter mi…
af-dudka Aug 13, 2026
7f6917e
[DELIVERY-125863] Bump example Android Gradle, AGP, and Kotlin for Fl…
af-dudka Aug 13, 2026
bb5c3ef
[DELIVERY-125863] Fix iOS CI: bump example deployment target to 15 an…
af-dudka Aug 13, 2026
d2e60ed
[DELIVERY-125863] Hold replayed af-events until their listener registers
af-dudka Aug 13, 2026
ebbabdc
[DELIVERY-125863] Serialize iOS engine-detach teardown on the main queue
af-dudka Aug 13, 2026
ba62ba4
[DELIVERY-125863] ci: run Android native unit tests in the PR gate
af-dudka Aug 13, 2026
460885a
fix(dart): remove platform gates so the RPC contract decides method s…
af-dudka Aug 13, 2026
50153e5
[DELIVERY-125863] Add explicit RpcEnvelope parser with fail-fast cont…
af-dudka Aug 13, 2026
1667a07
[DELIVERY-125863] Drop awaited RPC results after engine detach
af-dudka Aug 13, 2026
c2773b1
[DELIVERY-125863] Remove unused androidx.appcompat dependency
af-dudka Aug 13, 2026
5983751
[DELIVERY-125863] Remove public markBridgeReady that skipped ownershi…
af-dudka Aug 13, 2026
dc80410
[DELIVERY-125863] Document multi-engine single-listener limitation
af-dudka Aug 13, 2026
d606578
[DELIVERY-125863] Document non-finite eventValues; keep iOS serializa…
af-dudka Aug 13, 2026
22ebb8b
[DELIVERY-125863] Clean up low-severity review findings
af-dudka Aug 13, 2026
7257844
[DELIVERY-125863] Fix dart format and document removed Obj-C headers
af-dudka Aug 13, 2026
4864248
[DELIVERY-125863] Fix exclude-connector typo and remove empty iOS tes…
af-dudka Aug 13, 2026
d3fcdcc
[DELIVERY-125863] Drop refused af-events instead of blocking Android …
af-dudka Aug 17, 2026
820e217
[DELIVERY-125863] Buffer af-events during engine detach instead of si…
af-dudka Aug 17, 2026
082ae09
[DELIVERY-125863] Run Android init RPC off the platform thread via bl…
af-dudka Aug 17, 2026
8b34410
[DELIVERY-125863] Fix stale streams wording in Android bridge KDoc
af-dudka Aug 17, 2026
2d455cd
[DELIVERY-125863] Cover getHostName/getHostPrefix null RPC replies in…
af-dudka Aug 17, 2026
007f4c4
[DELIVERY-125863] Stop treating all af-events sink failures as DROP o…
af-dudka Aug 18, 2026
d305e95
[DELIVERY-125863] Log af-events buffer overflow on Android and iOS
af-dudka Aug 18, 2026
0cae36f
[DELIVERY-125863] Clarify AppsFlyerEventBus threading contract in KDoc
af-dudka Aug 18, 2026
f71455c
[DELIVERY-125863] Return PLUGIN_DETACHED for post-detach executeRpc o…
af-dudka Aug 18, 2026
4bfdb5a
[DELIVERY-125863] Dispose stale Purchase Connector attachment outside…
af-dudka Aug 18, 2026
4972ca2
[DELIVERY-125863] Roll back Dart listener slots when register*Listene…
af-dudka Aug 18, 2026
e3104da
[DELIVERY-125863] Isolate throwing listener callbacks in AppsFlyerLis…
af-dudka Aug 18, 2026
00bbc52
[DELIVERY-125863] Log handleLaunchOptions RPC failures on iOS
af-dudka Aug 18, 2026
33b48ee
[DELIVERY-125863] Rename AppsFlyerRpcExecutor to RpcRequestRunner on …
af-dudka Aug 18, 2026
8fa6233
[DELIVERY-125863] Keep Dart listener slots when unregister*Listener R…
af-dudka Aug 18, 2026
c6b70fe
[DELIVERY-125863] Align Android bridge with RPC 7.0.12 and fix Activi…
af-dudka Aug 19, 2026
5529692
[DELIVERY-125863] dart format
af-dudka Aug 19, 2026
a47e419
[DELIVERY-125863] Require all four bool fields in setConsentData
af-dudka Aug 20, 2026
05c98cb
[DELIVERY-125863] Align plugin with RPC 7.0.12/7.0.13 and finalize SD…
af-dudka Aug 25, 2026
4c6368b
[DELIVERY-125863] Restore working listeners when re-registration RPC …
af-dudka Aug 25, 2026
c17c73c
[DELIVERY-125863] Fix Purchase Connector silent drops on partial Play…
af-dudka Aug 25, 2026
ab1e603
[DELIVERY-125863] Raise Flutter floor to 3.35, fix Purchase Connector…
af-dudka Aug 25, 2026
48b5955
[DELIVERY-125863] Remove internal channel names from public docs, dro…
af-dudka Aug 25, 2026
87d7455
[DELIVERY-125863] Redact event payloads from plugin logs
af-dudka Aug 25, 2026
8d1c6d0
[DELIVERY-125863] Analyze the example app in CI and make infos fatal
af-dudka Aug 25, 2026
72cb95e
[DELIVERY-125863] Remove dead Android build config and the empty pods…
af-dudka Aug 25, 2026
4fc8bea
[DELIVERY-125863] Clear the three Swift compiler warnings in the iOS …
af-dudka Aug 25, 2026
69bf5dd
[DELIVERY-125863] Create dummy example/.env before CI analyze step
af-dudka Aug 25, 2026
9f02b1e
[DELIVERY-125863] Reject background-isolate calls across the SDK and …
af-dudka Aug 25, 2026
93a33eb
[DELIVERY-125863] Silence plugin logs in release unless enableDebug i…
af-dudka Aug 25, 2026
c90e8d0
[DELIVERY-125863] Roll back enableDebug on failure, clarify logging d…
af-dudka Aug 26, 2026
75ee0aa
[DELIVERY-125863] Release stale iOS Purchase Connector registration a…
af-dudka Aug 26, 2026
fec7fb8
[DELIVERY-125863] Recover the af-events subscription on end of stream…
af-dudka Aug 26, 2026
44f53dd
[DELIVERY-125863] Call handleLaunchOptions on the SDK directly, drop …
af-dudka Aug 26, 2026
bc0690f
[DELIVERY-125863] Forward iOS deep-link lifecycle callbacks straight …
af-dudka Aug 26, 2026
7e3aef7
[DELIVERY-125863] Fix inaccurate timeout, isolate, and version claims…
af-dudka Aug 26, 2026
f8f0852
[DELIVERY-125863] Correct stale plugin-logging and dependency claims …
af-dudka Aug 26, 2026
44abcb4
[DELIVERY-125863] Bump the plugin version from 7.0.1 to 7.0.2
af-dudka Aug 26, 2026
8f9c832
[DELIVERY-125863] Badge
af-dudka Aug 26, 2026
c6915a8
[DELIVERY-125863] Guard iOS Purchase Connector payload serialization
af-dudka Aug 26, 2026
bb50324
AppsFlyer Flutter Plugin 7.0.2 Release
af-dudka Aug 27, 2026
6e6a817
[DELIVERY-125863] Fix Android E2E startSDK timeout on slow emulator c…
af-dudka Aug 27, 2026
147479f
[DELIVERY-125863] Stop adb from draining stdin and skipping scenario …
af-dudka Aug 27, 2026
1413532
[DELIVERY-125863] Cover cold deep links and stop iOS phases validatin…
af-dudka Aug 27, 2026
cd1616c
[DELIVERY-125863] Correct iOS isDeferred docs and F-039 UIScene regis…
af-dudka Aug 27, 2026
5610652
[DELIVERY-125863] Point example App/Universal Links at af-flutter-plu…
af-dudka Aug 27, 2026
2b48f87
[DELIVERY-125863] Add Android E2E phase_8 for OneLink https cold App …
af-dudka Aug 27, 2026
1ae7d57
[DELIVERY-125863] Stop iOS delivering deep links twice on the UIScene…
af-dudka Aug 27, 2026
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
2 changes: 1 addition & 1 deletion .claude/skills/alice-pm/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ Automated via GitHub Actions: `.github/workflows/rc-release.yml`, `rc-smoke.yml`

## Domain-Specific Notes

- Cross-platform parity: any new public Dart API must map to matching method names/behavior in both `AppsflyerSdkPlugin.java` (Android) and `AppsflyerSdkPlugin.m` (iOS) — flag any PRD that only specifies one platform.
- Cross-platform parity: any new public Dart API must map to matching method names/behavior in both `AppsflyerSdkPlugin.kt` (Android) and `AppsflyerSdkPlugin.swift` (iOS) — flag any PRD that only specifies one platform.
- This is a published pub.dev package (`appsflyer_sdk`) consumed by third-party apps — breaking changes to the public Dart API require a major version bump and migration notes in `CHANGELOG.md`.
- Purchase Connector is optional/self-contained (`lib/src/purchase_connector/`, `ios/PurchaseConnector/`, Android Kotlin) — changes there should not affect core SDK consumers who don't opt in.
- Release goes through the RC pipeline (see Release Process above) — any feature landing near a release cut should account for RC-SMOKE validation.
4 changes: 2 additions & 2 deletions .claude/skills/dave-flutter-engineer/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: Use when working on AppsFlyer Flutter Plugin code — writing, revi

## Persona

Senior engineer with deep knowledge of AppsFlyer Flutter Plugin. Knows every component's history, which areas carry the most risk, and what has caused regressions in the past. Tech stack: Dart/Flutter plugin (SDK >=2.17.0 <4.0.0, Flutter >=1.10.0) bridging native AppsFlyer SDKs via MethodChannel/EventChannel — Objective-C on iOS (`ios/Classes/`), Java/Kotlin on Android (`android/src/main/java` + `android/src/main/kotlin` for the Purchase Connector). JSON models via `json_annotation`/`json_serializable` + `build_runner`. Testing via `mockito` + `flutter_lints`..
Senior engineer with deep knowledge of AppsFlyer Flutter Plugin. Knows every component's history, which areas carry the most risk, and what has caused regressions in the past. Tech stack: Dart/Flutter plugin (SDK >=2.17.0 <4.0.0, Flutter >=1.10.0) bridging native AppsFlyer SDKs via MethodChannel/EventChannel — Swift on iOS (`ios/appsflyer_sdk/Sources/appsflyer_sdk/`, plus a minimal Objective-C shim target `ios/appsflyer_sdk/Sources/appsflyer_sdk_objc/`), Kotlin on Android (`android/src/main/kotlin` + `android/src/main/include-connector` for the Purchase Connector). JSON models via `json_annotation`/`json_serializable` + `build_runner`. Testing via `mockito` + `flutter_lints`..

## PRD Gate — BLOCKING REQUIREMENT

Expand Down Expand Up @@ -165,7 +165,7 @@ BLOCKING REQUIREMENT: Include a `Skill('dave-flutter-engineer')` tool call in th
## Domain-Specific Notes

- Keep `AppsflyerSdk` as a singleton — do not change the instantiation pattern.
- New SDK method: add Dart method in `lib/src/appsflyer_sdk.dart` (invoke via `_channel.invokeMethod`), implement in `AppsflyerSdkPlugin.java` (Android) and `AppsflyerSdkPlugin.m` (iOS). Keep the method name string identical across all three files.
- New SDK method: add Dart method in `lib/src/appsflyer_sdk.dart` (invoke via `_channel.invokeMethod`), implement in `AppsflyerSdkPlugin.kt` (Android) and `AppsflyerSdkPlugin.swift` (iOS). Keep the method name string identical across all three files.
- Callbacks from native → Dart flow through EventChannels defined in `lib/src/callbacks.dart`.
- Deep linking (UDL) logic is isolated in `lib/src/udl/` — do not mix with core SDK channel calls.
- Purchase Connector is self-contained in `lib/src/purchase_connector/` (Dart models) and `ios/PurchaseConnector/` / `android/.../kotlin/` (native) — keep it that way.
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/erin-flutter-analyst/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,5 @@ After Erin presents any analysis findings, `alice-pm` is invoked automatically.

- Field maps live at the MethodChannel/EventChannel boundary — arguments passed as `Map<String, dynamic>` between Dart and native.
- JSON-serializable Dart models: `lib/src/purchase_connector/` (in-app purchase validation payloads) — regenerate `.g.dart` via `build_runner` after any field change.
- Attribution/conversion data payloads flow through `lib/src/callbacks.dart` — check both the Dart model and the native (Java/ObjC) side that populates the EventChannel data.
- Attribution/conversion data payloads flow through `lib/src/callbacks.dart` — check both the Dart model and the native (Kotlin/Swift) side that populates the EventChannel data.
- When mapping fields, verify parity between what Android and iOS native code send — historically a source of drift.
8 changes: 5 additions & 3 deletions .github/workflows/production-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -405,9 +405,11 @@ jobs:

## 📚 Documentation

- [Installation Guide](https://github.com/${{ github.repository }}/blob/master/doc/Installation.md)
- [Basic Integration](https://github.com/${{ github.repository }}/blob/master/doc/BasicIntegration.md)
- [API Documentation](https://github.com/${{ github.repository }}/blob/master/doc/API.md)
- [Documentation index](https://github.com/${{ github.repository }}/blob/master/doc/README.md)
- [Installation](https://github.com/${{ github.repository }}/blob/master/doc/installation-guide.md)
- [Getting started](https://github.com/${{ github.repository }}/blob/master/doc/getting-started.md)
- [API reference](https://github.com/${{ github.repository }}/blob/master/doc/api-reference.md)
- [Migrating v6 → v7](https://github.com/${{ github.repository }}/blob/master/doc/migration-guide.md)
- [Sample App](https://github.com/${{ github.repository }}/tree/master/example)

## 🔗 Links
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/promote-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ jobs:
VERSION='${{ steps.compute-version.outputs.version }}'
echo "Updating PLUGIN_VERSION constants to: $VERSION"

# Android - AppsFlyerConstants.java
ANDROID_FILE="android/src/main/java/com/appsflyer/appsflyersdk/AppsFlyerConstants.java"
# Android - AppsFlyerConstants.kt
ANDROID_FILE="android/src/main/kotlin/com/appsflyer/appsflyersdk/AppsFlyerConstants.kt"
if [ -f "$ANDROID_FILE" ]; then
sed -i "s/PLUGIN_VERSION = \".*\"/PLUGIN_VERSION = \"$VERSION\"/" "$ANDROID_FILE"
echo "✅ Android:" && grep "PLUGIN_VERSION" "$ANDROID_FILE"
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/rc-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -318,8 +318,8 @@ jobs:
VERSION='${{ needs.validate-release.outputs.version }}'
echo "Updating PLUGIN_VERSION constants to: $VERSION"

# Android - AppsFlyerConstants.java
ANDROID_FILE="android/src/main/java/com/appsflyer/appsflyersdk/AppsFlyerConstants.java"
# Android - AppsFlyerConstants.kt
ANDROID_FILE="android/src/main/kotlin/com/appsflyer/appsflyersdk/AppsFlyerConstants.kt"
if [ -f "$ANDROID_FILE" ]; then
sed -i.bak "s/PLUGIN_VERSION = \".*\"/PLUGIN_VERSION = \"$VERSION\"/" "$ANDROID_FILE"
rm "$ANDROID_FILE.bak"
Expand Down
8 changes: 8 additions & 0 deletions .pubignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@ package.json
package-lock.json
node_modules/
local.properties
build/
coverage/
.githooks/
.cursor/
.claude/
CLAUDE.md
ai-delivery-workflow-templat/
internal-docs/
output.af-quiz-me/

# Example app files that shouldn't be in package
example/.env
Expand Down
120 changes: 120 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,125 @@
# Versions

## 7.0.1

Migration to **AppsFlyer SDK 7**. This is a major release with intentional
breaking changes. See [doc/migration-guide.md](doc/migration-guide.md) for
removed APIs, renames, lifecycle changes, and upgrade instructions.

- Flutter plugin version **7.0.1**
- Minimum Flutter version **3.24.0**
- Minimum Dart version **3.5.0** (and earlier than Dart **4.0.0**)
- Android AppsFlyer SDK **7.0.1**
- iOS AppsFlyer SDK **7.0.1**
- Android Purchase Connector **2.2.0**
- iOS Purchase Connector **7.0.1**
- iOS minimum deployment target **13.0**
- Android minimum API level **21**
- Documentation remains organized under [`doc/`](doc/README.md), with the
complete upgrade catalog in [doc/migration-guide.md](doc/migration-guide.md).

**BREAKING**

- Replaced `AppsflyerSdk(options)` and `AppsFlyerOptions` with the shared
`AppsFlyerSdk.instance` singleton and explicit configuration methods.
- Replaced `initSdk(...)` with `init(devKey:, appId:)`. `appId` is required on
iOS, optional on Android, and is not sent to the Android SDK.
- Replaced `startSDK(...)` with `await start()`. Initialization no longer sends
a session. Subscribe to `onSessionReady`, call
`registerSessionReadyListener()`, and call `start()` once for each readiness
event.
- Replaced callback registration flags and callback slots with typed event
streams and explicit listener registration. Conversion data uses
`onConversionDataSuccess` / `onConversionDataFailure`; Unified Deep Linking
uses `onDeepLinkReceived`.
- Native and plugin failures from operations that await a result are surfaced as
`AppsFlyerException` (`int? code`, `String message`). Non-numeric platform
codes leave `code` as `null`. `MissingPluginException` is not converted.
Failures from fire-and-forget calls are not reported.
- `start`, `logEvent`, `generateInviteLink`, and
`validateAndLogInAppPurchase` expose `awaitResponse` where the native SDK
supports waiting for a completion callback. It defaults to `false` for `start`
and `logEvent`, and to `true` for the two result-producing APIs.
- Removed OAOA callbacks and registration. Use Unified Deep Linking.
- Replaced `performOnDeepLinking()` with
`performDeepLinking(url, {shouldTriggerSession})`.
- Replaced legacy V1 Android/iOS purchase validation and
`validateAndLogInAppPurchaseV2(...)` with
`validateAndLogInAppPurchase(AFPurchaseDetails, ...)`. Use
`AFAndroidPurchaseDetails` with a Play purchase token or
`AFIOSPurchaseDetails` with an App Store transaction ID.
- Replaced the cross-platform `sendPushNotificationData(Map)` shape with
platform-specific Android `sendPushNotificationData(...)` and iOS
`handlePushNotification(pushPayload)` APIs.
- Replaced `setConsentDataV2(...)` and the `AppsFlyerConsent` wrapper with the
flat `setConsentData(...)` API and its four SDK 7 consent fields.
- Renamed platform APIs to match the final SDK 7 surface, including
`enableDebug`, `setDisableSKAdNetwork`,
`setDisableAppleAdsAttribution`, `setDisableIDFVCollection`,
`setUseReceiptValidationSandbox`, and `setUseUninstallSandbox`.
- `setUserFbLoginId` now accepts an `int`; mediation values use
`AFMediationNetwork`; invite-link fields use `referrerCustomerId` and
`userParams`.
- Removed SDK 6 APIs that no longer exist in SDK 7 or are not exposed by the
plugin, including `onAppOpenAttribution`, `setUserEmails`, `EmailCryptType`,
raw IMEI and Android ID setters, V1 purchase validation, `setPushNotification`,
`enableUninstallTracking`, `waitForCustomerUserId`, and
`setCustomerIdAndLogSession`.
- Runtime configuration setters must be re-applied on every cold start before
`start()`.
- Guarded platform-only methods log and return a safe default when called
outside their supported platform.
- `setInstallId()` requires `AppsFlyerAllowCustomInstallId=YES` in iOS
`Info.plist` and must be called before `init()` on iOS. Android requires
`APPSFLYER_ALLOW_CUSTOM_INSTALL_ID=true` in `AndroidManifest.xml` and the call
must follow `init()`.
- Android Purchase Connector `2.2.0` requires Google Play Billing Library `8.x`.
The Flutter plugin does not add Billing Library; the app or its IAP plugin
must provide it. iOS Purchase Connector requires CocoaPods, while Core-only
apps can use Swift Package Manager.
- Remove legacy `SingleInstallBroadcastReceiver` and
`MultipleInstallBroadcastReceiver` manifest entries. The plugin already
includes Google Play Install Referrer `2.2`.

See the [v6 → v7 migration guide](doc/migration-guide.md) for the complete
replacement table.

**Added**

- Added `AppsFlyerSdk.instance`, `init(...)`, `onSessionReady`,
`registerSessionReadyListener()`, `unregisterSessionReadyListener()`,
`isSessionReady()`, and `start()` for the SDK 7 lifecycle.
- Added the cross-platform `enableDebug(bool)` toggle and Android-only
`setLogLevel(AFLogLevel)`.
- Added typed event streams and `AppsFlyerException`.
- Added hashed-PII setters `setUserEmail`, `setUserPhone`,
`setUserFirstName`, and `setUserLastName`, plus integer
`setUserFbLoginId` and `clearUserPii`.
- Added `performDeepLinking`, `setDeepLinkTimeout`,
`appendParametersToDeepLinkingURL`, and iOS-only
`setFacebookDeferredAppLink`.
- Added the `AFPurchaseDetails` interface with dedicated
`AFAndroidPurchaseDetails` and `AFIOSPurchaseDetails` implementations.
- Added Android-only `logSession`, `setPreinstallAttribution`, `setAppId`,
`isStopped`, `isPreInstalledApp`, `getAttributionId`,
`unregisterDeeplinkListener`, and `unregisterConversionListener` APIs.
On Android, `unregisterDeeplinkListener` does not reliably stop subsequent
deep-link events; do not depend on it as an effective unsubscribe.
- Added iOS-only `setDisableAppleAdsAttribution`,
`setDisableIDFVCollection`, `setShouldCollectDeviceName`, and
`setUseUninstallSandbox` APIs.
- Added `logInvite`, `logLocation`, `setInstallId`, and awaitable
`generateInviteLink` support.

**Fixed**

- Purchase Connector: removed stray `[AppsFlyer_PC_Debug]` `print` logging that shipped in release builds; the callback handler now accepts both JSON-string and already-decoded `Map` payloads and logs (instead of throwing) on an unrecognized callback name.
- Purchase Connector (**Android**): subscription and in-app validation-result listeners (`setSubscriptionValidationResultListener` / `setInAppValidationResultListener`) never fired — the Dart callback-name constants used a `#` separator while the native side invokes the channel with `:`, so the handler's `switch` never matched. Aligned the Dart constants to `:`, so these result listeners now deliver.
- Optional Android Purchase Connector state is cleared when the Flutter engine
detaches.
- Corrected iOS ad-mediation identifiers for custom and direct monetization.
- Updated documentation and examples for the final SDK 7 API.

## 6.18.0

- Updated Android SDK from 6.17.6 to 6.18.0
Expand Down
64 changes: 54 additions & 10 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# AppsFlyer Flutter Plugin

## Overview
Flutter plugin providing mobile attribution and analytics for iOS and Android. Bridges native AppsFlyer SDKs (iOS v6.17.9, Android v6.17.6) via Dart MethodChannel/EventChannel. Supports Flutter 2+ with null safety.
Flutter plugin providing mobile attribution and analytics for iOS and Android.
The core bridge uses native AppsFlyer SDK 7.0.1, Android RPC 7.0.1, and iOS
AppsFlyerRPC 7.0.12. It requires Flutter 3.24+ and Dart 3.5+.

## Starting a feature

Expand Down Expand Up @@ -29,12 +31,13 @@ For everything outside of feature delivery, invoke skills directly:

## Architecture
- `lib/src/appsflyer_sdk.dart` — Main SDK class (singleton, MethodChannel/EventChannel bridge)
- `lib/src/callbacks.dart` — Attribution and event callback handlers
- `lib/src/appsflyer_event.dart` — Native RPC event envelope
- `lib/src/udl/deeplink.dart` — Unified Deep Linking (UDL) implementation
- `lib/src/purchase_connector/` — In-app purchase validation models
- `android/src/main/java/com/appsflyer/appsflyersdk/AppsflyerSdkPlugin.java` — Android entry point
- `android/src/main/kotlin/` — Kotlin Purchase Connector for Android
- `ios/Classes/AppsflyerSdkPlugin.m` — iOS entry point (Objective-C)
- `android/src/main/kotlin/com/appsflyer/appsflyersdk/AppsflyerSdkPlugin.kt` — Android entry point
- `android/src/main/include-connector/` — Optional Kotlin Purchase Connector bridge
- `ios/appsflyer_sdk/Sources/appsflyer_sdk/` — iOS RPC entry point (Swift)
- `ios/appsflyer_sdk/Sources/appsflyer_sdk_objc/` — minimal Objective-C shim (`NSException` boundary + RPC bridge pass-through)
- `ios/PurchaseConnector/` — iOS purchase validation module
- `test/` — Dart unit tests (mockito)
- `example/` — Full Flutter example app (iOS + Android)
Expand All @@ -55,11 +58,14 @@ flutter pub run build_runner build # Regenerate JSON serialization code
- **JSON serialization**: Uses `json_annotation` + `json_serializable`. After changing annotated model classes, run `build_runner` to regenerate `.g.dart` files. Commit the generated files.
- **Testing**: `mockito` for mocking. Add tests in `test/` for new public API.
- Dart null safety is required — all new code must be null-safe.
- Keep `AppsflyerSdk` as a singleton; do not change the instantiation pattern.
- Keep `AppsFlyerSdk.instance` as the production singleton.

## Key Patterns
- New SDK method: add Dart method in `appsflyer_sdk.dart` (invoke via `_channel.invokeMethod`), implement in `AppsflyerSdkPlugin.java` (Android) and `AppsflyerSdkPlugin.m` (iOS). Keep method name strings consistent across all three files.
- Callbacks from native → Dart flow through EventChannels defined in `callbacks.dart`.
- New core SDK methods must map to existing native RPC capabilities. Add the
Dart RPC call and only platform adaptation required by the RPC contracts;
keep business behavior in the native SDK/RPC modules.
- Native RPC callbacks flow through the `af-events` EventChannel as
`_AppsFlyerEvent` envelopes parsed on the Dart side.
- Deep linking (UDL) logic is isolated in `lib/src/udl/` — do not mix with core SDK channel calls.
- Purchase Connector is self-contained in `lib/src/purchase_connector/` (Dart models) and `ios/PurchaseConnector/` / `android/.../kotlin/` (native).

Expand All @@ -71,8 +77,46 @@ flutter pub run build_runner build # Regenerate JSON serialization code
## Notes
- SDK version is set in `pubspec.yaml` and native dependency specs (podspec / `build.gradle`).
- Generated files (`*.g.dart`) must be committed — run `build_runner` after model changes.
- `doc/` and `example/` should be kept in sync with API changes.
- iOS native layer is Objective-C; Kotlin is used only for the Android Purchase Connector.
- `doc/` and `example/` must be kept in sync with API changes — see Documentation review.
- The iOS core bridge is Swift, with a minimal Objective-C shim target
(`appsflyer_sdk_objc`) for the `NSException` boundary that Swift cannot express;
Swift and Kotlin implement the optional Purchase Connector bridges.

## Documentation review

Applies to every code change, including pure refactors.

After every code change, identify and review all related documentation. Update
documentation whenever the change affects documented behavior, public APIs,
parameters, configuration, architecture, workflows, examples, compatibility, or
user-visible output. If no documentation update is needed, explicitly state which
documentation was reviewed and why it remains accurate.

Where to look, by what changed:

| Changed | Review |
|---------|--------|
| Public Dart API surface | dartdoc on the member, `doc/api-reference.md`, `README.md`, `CHANGELOG.md` |
| Platform-specific behavior or availability | `doc/api-reference.md`, the affected `internal-docs/features/F-NNN-*.md` |
| Breaking change or removed API | `doc/migration-guide.md`, `CHANGELOG.md` — see also the API Removal Rule |
| Behavior of a catalogued feature | matching `internal-docs/features/F-NNN-*.md` plus `internal-docs/features/INDEX.md` |
| Architecture, channels, or RPC transport | `internal-docs/ARCHITECTURE.md` and the Architecture section above |
| Setup, configuration, or native dependencies | `doc/installation-guide.md`, `doc/getting-started.md` |
| Anything the sample app demonstrates | `example/` and `example/README.md` |

Rules:

- Correct outdated references and examples in the files you review, including stale
method names, signatures, return types, and snippets that no longer compile.
- Never hand-edit generated output. Regenerate it — `*.g.dart` via
`flutter pub run build_runner build`.
- Leave accurate documentation alone. An unnecessary documentation edit is a defect.

Every task summary must state:

- which documentation files were reviewed;
- which documentation files were updated;
- if none were updated, why the existing documentation remains accurate.

## Maintenance bypass

Expand Down
Loading
Loading