From e4735d410efc07c45b353a8e3a8b982d78c0d76b Mon Sep 17 00:00:00 2001 From: dmitry ovchinikov Date: Mon, 25 Jul 2022 15:19:50 +0300 Subject: [PATCH 1/2] 6.8.0 - The API `enableLocationCollection` has been removed. - The API `setDisableNetworkData` has been added. - The AD_ID permission has been added to the plugin. - Updated AppsFlyer Android SDK to v6.8.0 - Updated AppsFlyer iOS SDK to v6.8.0 --- CHANGELOG.md | 6 + README.md | 14 ++- android/build.gradle | 2 +- android/src/main/AndroidManifest.xml | 1 + .../appsflyersdk/AppsflyerSdkPlugin.java | 18 +-- doc/API.md | 16 +++ doc/Guides.md | 2 +- example/ios/Flutter/AppFrameworkInfo.plist | 2 +- example/ios/Flutter/Flutter.podspec | 2 +- example/lib/main_page.dart | 21 ++-- ios/appsflyer_sdk.podspec | 4 +- lib/src/appsflyer_sdk.dart | 110 +++++++++++------- pubspec.yaml | 4 +- 13 files changed, 125 insertions(+), 77 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d38853a..b5dc4c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,10 @@ # Versions +## 6.8.0 +- The API `enableLocationCollection` has been removed. +- The API `setDisableNetworkData` has been added. +- The AD_ID permission has been added to the plugin. +- Updated AppsFlyer Android SDK to v6.8.0 +- Updated AppsFlyer iOS SDK to v6.8.0 ## 6.5.2+2 ## 6.5.2+1 - New APIs: getOutOfStore, setOutOfStore, setResolveDeepLinkURLs, setPartnerData diff --git a/README.md b/README.md index e8650e9..b3977ea 100644 --- a/README.md +++ b/README.md @@ -12,13 +12,15 @@ ### This plugin is built for -- Android AppsFlyer SDK **v6.5.2** -- iOS AppsFlyer SDK **v6.5.2** +- Android AppsFlyer SDK **v6.8.0** +- iOS AppsFlyer SDK **v6.8.0** ## ❗❗ Breaking changes when updating to v6.x.x❗❗ If you have used one of the removed/changed APIs, please check the integration guide for the updated instructions. +- From version `6.8.0`, the `enableLocationCollection` has been removed from the plugin. + - From version `6.4.0`, UDL (Unified deep link) now as a dedicated class with getters for handling the deeplink result. [Check the full UDL guide](https://github.com/AppsFlyerSDK/appsflyer-flutter-plugin/blob/master/doc/Guides.md#-3-unified-deep-linking). `setSharingFilter` & `setSharingFilterForAllPartners` APIs are deprecated. @@ -37,7 +39,7 @@ Instead use the [new API `setSharingFilterForPartners`](https://github.com/AppsF | stopTracking | stop | | validateAndTrackInAppPurchase | validateAndLogInAppPurchase | -- From version `6.1.2+4`, we have renated the following APIs: +- From version `6.1.2+4`, we have renamed the following APIs: |Before v6.1.2+4 | v6.1.2+4 | |-------------------------------|-----------------------------| @@ -46,6 +48,12 @@ Instead use the [new API `setSharingFilterForPartners`](https://github.com/AppsF ### Important notice - Switch `ConversionData` and `OnAppOpenAttribution` to be based on callbacks instead of streams from plugin version `6.0.5+2`. +## AD_ID permission for Android +In v6.8.0 of the AppsFlyer SDK, we added the normal permission `com.google.android.gms.permission.AD_ID` to the SDK's AndroidManifest, +to allow the SDK to collect the Android Advertising ID on apps targeting API 33. +If your app is targeting children, you need to revoke this permission to comply with Google's Data policy. +You can read more about it [here](https://dev.appsflyer.com/hc/docs/install-android-sdk#the-ad_id-permission). + ## 📖 Guides - [Adding the SDK to your project](/doc/Installation.md) - [Initializing the SDK](/doc/BasicIntegration.md) diff --git a/android/build.gradle b/android/build.gradle index 473e683..c0a8e45 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -35,6 +35,6 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.0.0' - implementation 'com.appsflyer:af-android-sdk:6.5.2' + implementation 'com.appsflyer:af-android-sdk:6.8.0' implementation 'com.android.installreferrer:installreferrer:2.1' } \ No newline at end of file diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 63c5302..a83f4f4 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -3,4 +3,5 @@ + diff --git a/android/src/main/java/com/appsflyer/appsflyersdk/AppsflyerSdkPlugin.java b/android/src/main/java/com/appsflyer/appsflyersdk/AppsflyerSdkPlugin.java index ee72286..df2dbac 100644 --- a/android/src/main/java/com/appsflyer/appsflyersdk/AppsflyerSdkPlugin.java +++ b/android/src/main/java/com/appsflyer/appsflyersdk/AppsflyerSdkPlugin.java @@ -226,9 +226,6 @@ public void onMethodCall(MethodCall call, Result result) { case "setAndroidIdData": setAndroidIdData(call, result); break; - case "enableLocationCollection": - enableLocationCollection(call, result); - break; case "setCustomerUserId": setCustomerUserId(call, result); break; @@ -310,12 +307,21 @@ public void onMethodCall(MethodCall call, Result result) { case "setResolveDeepLinkURLs": setResolveDeepLinkURLs(call, result); break; + case "setDisableNetworkData": + setDisableNetworkData(call, result); + break; default: result.notImplemented(); break; } } + private void setDisableNetworkData(MethodCall call, Result result) { + boolean disableNetworkData = (boolean) call.arguments; + AppsFlyerLib.getInstance().setDisableNetworkData(disableNetworkData); + result.success(null); + } + private void getOutOfStore(Result result) { result.success(AppsFlyerLib.getInstance().getOutOfStore(this.mContext)); } @@ -646,12 +652,6 @@ private void setCustomerUserId(MethodCall call, Result result) { result.success(null); } - private void enableLocationCollection(MethodCall call, Result result) { - boolean flag = (boolean) call.argument("flag"); - AppsFlyerLib.getInstance().enableLocationCollection(flag); - result.success(null); - } - private void setAndroidIdData(MethodCall call, Result result) { String androidId = (String) call.argument("androidId"); AppsFlyerLib.getInstance().setAndroidIdData(androidId); diff --git a/doc/API.md b/doc/API.md index 5a02739..e48a4d3 100644 --- a/doc/API.md +++ b/doc/API.md @@ -44,6 +44,7 @@ - [setResolveDeepLinkURLs](#setResolveDeepLinkURLs) - [setOutOfStore](#setOutOfStore) - [getOutOfStore](#getOutOfStore) +- [setDisableNetworkData](#setDisableNetworkData) --- @@ -241,6 +242,8 @@ appsFlyerSdk.setAndroidIdData("androidId"); --- ** `void enableLocationCollection(bool flag)`** +**Removed as of v6.8.0** + _Example:_ ```dart appsFlyerSdk.enableLocationCollection(true); @@ -584,3 +587,16 @@ _Example:_ } ``` --- +** `void setDisableNetworkData(bool disable)`** + +**Android Only!** + +Use to opt-out of collecting the network operator name (carrier) and sim operator name from the device. + +_Example:_ +```dart + if(Platform.isAndroid){ + appsflyerSdk.setDisableNetworkData(true); + } +``` +--- diff --git a/doc/Guides.md b/doc/Guides.md index b1fdb9e..ce5519d 100644 --- a/doc/Guides.md +++ b/doc/Guides.md @@ -39,7 +39,7 @@ AppsflyerSdk appsflyerSdk = AppsflyerSdk(appsFlyerOptions); The next step is to call `initSdk` which have the optional boolean parameters `registerConversionDataCallback` and the deeplink callbacks: `registerOnAppOpenAttributionCallback` `registerOnDeepLinkingCallback` -All callbacks are set to true as default. +All callbacks are set to false as default. After we call `initSdk` we can use all of AppsFlyer SDK features. diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index 9367d48..8d4492f 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 8.0 + 9.0 diff --git a/example/ios/Flutter/Flutter.podspec b/example/ios/Flutter/Flutter.podspec index 2c4421c..663d5b2 100644 --- a/example/ios/Flutter/Flutter.podspec +++ b/example/ios/Flutter/Flutter.podspec @@ -11,7 +11,7 @@ Pod::Spec.new do |s| s.license = { :type => 'MIT' } s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } - s.ios.deployment_target = '8.0' + s.ios.deployment_target = '9.0' # Framework linking is handled by Flutter tooling, not CocoaPods. # Add a placeholder to satisfy `s.dependency 'Flutter'` plugin podspecs. s.vendored_frameworks = 'path/to/nothing' diff --git a/example/lib/main_page.dart b/example/lib/main_page.dart index 7936f4f..4edb24f 100644 --- a/example/lib/main_page.dart +++ b/example/lib/main_page.dart @@ -21,11 +21,10 @@ class MainPageState extends State { void initState() { super.initState(); final AppsFlyerOptions options = AppsFlyerOptions( - afDevKey: DotEnv().env["DEV_KEY"], - appId: DotEnv().env["APP_ID"], - showDebug: true, - timeToWaitForATTUserAuthorization: 15 - ); + afDevKey: DotEnv().env["DEV_KEY"], + appId: DotEnv().env["APP_ID"], + showDebug: true, + timeToWaitForATTUserAuthorization: 15); _appsflyerSdk = AppsflyerSdk(options); _appsflyerSdk.onAppOpenAttribution((res) { print("onAppOpenAttribution res: " + res.toString()); @@ -39,10 +38,10 @@ class MainPageState extends State { _gcd = res; }); }); - _appsflyerSdk.onDeepLinking((DeepLinkResult dp){ + _appsflyerSdk.onDeepLinking((DeepLinkResult dp) { switch (dp.status) { case Status.FOUND: - print(dp.deepLink?.toString()); + print(dp.deepLink?.toString()); print("deep link value: ${dp.deepLink?.deepLinkValue}"); break; case Status.NOT_FOUND: @@ -70,10 +69,9 @@ class MainPageState extends State { children: [ Text('AppsFlyer SDK example app'), FutureBuilder( - future: _appsflyerSdk.getSDKVersion(), builder: (BuildContext context, AsyncSnapshot snapshot) { - return Text(snapshot.hasData ? snapshot.data : ""); - }), + return Text(snapshot.hasData ? snapshot.data : ""); + }), ], ), ), @@ -88,7 +86,7 @@ class MainPageState extends State { } else { if (snapshot.hasData) { return HomeContainer( - onData: _gcd, + onData: _gcd, deepLinkData: _deepLinkData, logEvent: logEvent, ); @@ -102,5 +100,4 @@ class MainPageState extends State { Future logEvent(String eventName, Map eventValues) { return _appsflyerSdk.logEvent(eventName, eventValues); } - } diff --git a/ios/appsflyer_sdk.podspec b/ios/appsflyer_sdk.podspec index 1d57c7f..9b76520 100644 --- a/ios/appsflyer_sdk.podspec +++ b/ios/appsflyer_sdk.podspec @@ -3,7 +3,7 @@ # Pod::Spec.new do |s| s.name = 'appsflyer_sdk' - s.version = '6.4.4' + s.version = '6.8.0' s.summary = 'AppsFlyer Integration for Flutter' s.description = <<-DESC AppsFlyer is the market leader in mobile advertising attribution & analytics, helping marketers to pinpoint their targeting, optimize their ad spend and boost their ROI. @@ -21,6 +21,6 @@ AppsFlyer is the market leader in mobile advertising attribution & analytics, he s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' s.dependency 'Flutter' - s.ios.dependency 'AppsFlyerFramework', '6.5.2' + s.ios.dependency 'AppsFlyerFramework', '6.8.0' end diff --git a/lib/src/appsflyer_sdk.dart b/lib/src/appsflyer_sdk.dart index 5638a45..148179d 100644 --- a/lib/src/appsflyer_sdk.dart +++ b/lib/src/appsflyer_sdk.dart @@ -58,17 +58,22 @@ class AppsflyerSdk { } if (options.disableAdvertisingIdentifier != null) { - validatedOptions[AppsflyerConstants.DISABLE_ADVERTISING_IDENTIFIER] = options.disableAdvertisingIdentifier; + validatedOptions[AppsflyerConstants.DISABLE_ADVERTISING_IDENTIFIER] = + options.disableAdvertisingIdentifier; } else { - validatedOptions[AppsflyerConstants.DISABLE_ADVERTISING_IDENTIFIER] = false; + validatedOptions[AppsflyerConstants.DISABLE_ADVERTISING_IDENTIFIER] = + false; } if (Platform.isIOS) { if (options.timeToWaitForATTUserAuthorization != null) { - dynamic timeToWaitForATTUserAuthorization = options.timeToWaitForATTUserAuthorization; + dynamic timeToWaitForATTUserAuthorization = + options.timeToWaitForATTUserAuthorization; assert(timeToWaitForATTUserAuthorization is double); - validatedOptions[AppsflyerConstants.AF_TIME_TO_WAIT_FOR_ATT_USER_AUTHORIZATION] = timeToWaitForATTUserAuthorization; + validatedOptions[ + AppsflyerConstants.AF_TIME_TO_WAIT_FOR_ATT_USER_AUTHORIZATION] = + timeToWaitForATTUserAuthorization; } dynamic appID = options.appId; assert(appID != null, "appleAppId is required for iOS apps"); @@ -110,16 +115,20 @@ class AppsflyerSdk { afOptions[AppsflyerConstants.DISABLE_ADVERTISING_IDENTIFIER] = options[AppsflyerConstants.DISABLE_ADVERTISING_IDENTIFIER]; } else { - afOptions[AppsflyerConstants.DISABLE_ADVERTISING_IDENTIFIER] = - false; + afOptions[AppsflyerConstants.DISABLE_ADVERTISING_IDENTIFIER] = false; } if (Platform.isIOS) { - if (options[AppsflyerConstants.AF_TIME_TO_WAIT_FOR_ATT_USER_AUTHORIZATION] != null) { - dynamic timeToWaitForATTUserAuthorization = options[AppsflyerConstants.AF_TIME_TO_WAIT_FOR_ATT_USER_AUTHORIZATION]; + if (options[ + AppsflyerConstants.AF_TIME_TO_WAIT_FOR_ATT_USER_AUTHORIZATION] != + null) { + dynamic timeToWaitForATTUserAuthorization = options[ + AppsflyerConstants.AF_TIME_TO_WAIT_FOR_ATT_USER_AUTHORIZATION]; assert(timeToWaitForATTUserAuthorization is double); - afOptions[AppsflyerConstants.AF_TIME_TO_WAIT_FOR_ATT_USER_AUTHORIZATION] = timeToWaitForATTUserAuthorization; + afOptions[ + AppsflyerConstants.AF_TIME_TO_WAIT_FOR_ATT_USER_AUTHORIZATION] = + timeToWaitForATTUserAuthorization; } dynamic appID = options[AppsflyerConstants.AF_APP_Id]; @@ -135,7 +144,6 @@ class AppsflyerSdk { ? options[AppsflyerConstants.AF_IS_DEBUG] : false; - return afOptions; } @@ -145,7 +153,6 @@ class AppsflyerSdk { bool registerOnAppOpenAttributionCallback = false, bool registerOnDeepLinkingCallback = false}) async { return Future.delayed(Duration(seconds: 0)).then((_) { - Map? validatedOptions; if (mapOptions != null) { validatedOptions = _validateMapOptions(mapOptions!); @@ -153,8 +160,11 @@ class AppsflyerSdk { validatedOptions = _validateAFOptions(afOptions!); } - validatedOptions?[AppsflyerConstants.AF_GCD] = registerConversionDataCallback || registerOnAppOpenAttributionCallback; - validatedOptions?[AppsflyerConstants.AF_UDL] = registerOnDeepLinkingCallback; + validatedOptions?[AppsflyerConstants.AF_GCD] = + registerConversionDataCallback || + registerOnAppOpenAttributionCallback; + validatedOptions?[AppsflyerConstants.AF_UDL] = + registerOnDeepLinkingCallback; return _methodChannel.invokeMethod("initSdk", validatedOptions); }); @@ -240,10 +250,6 @@ class AppsflyerSdk { _methodChannel.invokeMethod("stop", {'isStopped': isStopped}); } - void enableLocationCollection(bool flag) { - _methodChannel.invokeMethod("enableLocationCollection", {'flag': flag}); - } - ///Please use updateServerUninstallToken instead @deprecated void enableUninstallTracking(String senderId) { @@ -261,7 +267,8 @@ class AppsflyerSdk { if (cryptType != null) { cryptTypeInt = EmailCryptType.values.indexOf(cryptType); } - _methodChannel.invokeMethod("setUserEmails",{'emails': emails, 'cryptType': cryptTypeInt}); + _methodChannel.invokeMethod( + "setUserEmails", {'emails': emails, 'cryptType': cryptTypeInt}); } ///Get AppsFlyer's unique device ID is created for every new install of an app. @@ -274,22 +281,21 @@ class AppsflyerSdk { _methodChannel.invokeMethod("waitForCustomerUserId", {'wait': wait}); } - Future validateAndLogInAppAndroidPurchase ( + Future validateAndLogInAppAndroidPurchase( String publicKey, String signature, String purchaseData, String price, String currency, Map? additionalParameters) { - - return _methodChannel.invokeMethod("validateAndLogInAppAndroidPurchase", { - 'publicKey': publicKey, - 'signature': signature, - 'purchaseData': purchaseData, - 'price': price, - 'currency': currency, - 'additionalParameters': additionalParameters - }); + return _methodChannel.invokeMethod("validateAndLogInAppAndroidPurchase", { + 'publicKey': publicKey, + 'signature': signature, + 'purchaseData': purchaseData, + 'price': price, + 'currency': currency, + 'additionalParameters': additionalParameters + }); } ///Accessing AppsFlyer purchase validation data @@ -298,19 +304,20 @@ class AppsflyerSdk { String price, String currency, String transactionId, - Map additionalParameters)async{ - return await _methodChannel.invokeMethod("validateAndLogInAppIosPurchase", { - 'productIdentifier': productIdentifier, - 'price': price, - 'currency': currency, - 'transactionId': transactionId, - 'additionalParameters': additionalParameters - }); + Map additionalParameters) async { + return await _methodChannel.invokeMethod("validateAndLogInAppIosPurchase", { + 'productIdentifier': productIdentifier, + 'price': price, + 'currency': currency, + 'transactionId': transactionId, + 'additionalParameters': additionalParameters + }); } /// set sandbox for iOS purchase validation void useReceiptValidationSandbox(bool isSandboxEnabled) { - _methodChannel.invokeMethod("useReceiptValidationSandbox", isSandboxEnabled); + _methodChannel.invokeMethod( + "useReceiptValidationSandbox", isSandboxEnabled); } /// Set additional data to be sent to AppsFlyer. @@ -328,8 +335,10 @@ class AppsflyerSdk { if (parameters != null) { paramsMap = _translateInviteLinkParamsToMap(parameters); } - startListening(success as void Function(dynamic), "generateInviteLinkSuccess"); - startListening(error as void Function(dynamic), "generateInviteLinkFailure"); + startListening( + success as void Function(dynamic), "generateInviteLinkSuccess"); + startListening( + error as void Function(dynamic), "generateInviteLinkFailure"); _methodChannel.invokeMethod("generateInviteLink", paramsMap); } @@ -352,7 +361,8 @@ class AppsflyerSdk { ///The link that is generated for the user invite will use this OneLink ID as the base link ID Future setAppInviteOneLinkID( String oneLinkID, Function callback) async { - startListening(callback as void Function(dynamic), "setAppInviteOneLinkIDCallback"); + startListening( + callback as void Function(dynamic), "setAppInviteOneLinkIDCallback"); await _methodChannel.invokeMethod("setAppInviteOneLinkID", { 'oneLinkID': oneLinkID, }); @@ -384,7 +394,8 @@ class AppsflyerSdk { } void enableFacebookDeferredApplinks(bool isEnabled) { - _methodChannel.invokeMethod("enableFacebookDeferredApplinks", { 'isFacebookDeferredApplinksEnabled': isEnabled }); + _methodChannel.invokeMethod("enableFacebookDeferredApplinks", + {'isFacebookDeferredApplinksEnabled': isEnabled}); } void disableSKAdNetwork(bool isEnabled) { @@ -394,8 +405,10 @@ class AppsflyerSdk { void setDisableAdvertisingIdentifiers(bool isEnabled) { _methodChannel.invokeMethod("setDisableAdvertisingIdentifiers", isEnabled); } + void onInstallConversionData(Function callback) async { - startListening(callback as void Function(dynamic), "onInstallConversionData"); + startListening( + callback as void Function(dynamic), "onInstallConversionData"); } void onAppOpenAttribution(Function callback) async { @@ -411,13 +424,14 @@ class AppsflyerSdk { } void setCurrentDeviceLanguage(String language) async { - _methodChannel.invokeMethod("setCurrentDeviceLanguage", language); + _methodChannel.invokeMethod("setCurrentDeviceLanguage", language); } @Deprecated("use setSharingFilterForPartners instead") void setSharingFilter(List partners) { setSharingFilterForPartners(partners); } + @Deprecated("use setSharingFilterForPartners instead") void setSharingFilterForAllPartners() { setSharingFilterForPartners(["all"]); @@ -438,9 +452,15 @@ class AppsflyerSdk { } void setPartnerData(String partnerId, Map partnerData) async { - _methodChannel.invokeMethod("setPartnerData", {'partnerId': partnerId, 'partnersData': partnerData}); + _methodChannel.invokeMethod("setPartnerData", + {'partnerId': partnerId, 'partnersData': partnerData}); } + void setResolveDeepLinkURLs(List urls) async { - _methodChannel.invokeMethod("setResolveDeepLinkURLs", urls); + _methodChannel.invokeMethod("setResolveDeepLinkURLs", urls); + } + + void setDisableNetworkData(bool disable) { + _methodChannel.invokeMethod("setDisableNetworkData", disable); } } diff --git a/pubspec.yaml b/pubspec.yaml index 79067c5..bc5f057 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: appsflyer_sdk description: A Flutter plugin for AppsFlyer SDK. Supports iOS and Android. -version: 6.5.2+2 +version: 6.8.0 homepage: https://github.com/AppsFlyerSDK/flutter_appsflyer_sdk @@ -16,7 +16,7 @@ dev_dependencies: flutter_test: sdk: flutter test: ^1.16.5 - mockito: 5.0.11 + mockito: 5.2.0 effective_dart: ^1.3.0 From f6ccaf615fb56934dd8e52e2845e327e43575043 Mon Sep 17 00:00:00 2001 From: dmitry ovchinikov Date: Sun, 7 Aug 2022 09:32:03 +0300 Subject: [PATCH 2/2] - The API `enableLocationCollection` has been removed. - The API `setDisableNetworkData` has been added. - The AD_ID permission has been added to the plugin. - Updated AppsFlyer Android SDK to v6.8.0 - Updated AppsFlyer iOS SDK to v6.8.0 --- android/src/main/AndroidManifest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index a83f4f4..8f3433b 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -2,6 +2,5 @@ package="com.appsflyer.appsflyersdk"> -