diff --git a/Assets/AppsFlyer/AppsFlyer.cs b/Assets/AppsFlyer/AppsFlyer.cs index e290206c..75e701b7 100644 --- a/Assets/AppsFlyer/AppsFlyer.cs +++ b/Assets/AppsFlyer/AppsFlyer.cs @@ -7,7 +7,7 @@ namespace AppsFlyerSDK public class AppsFlyer : MonoBehaviour { - public static readonly string kAppsFlyerPluginVersion = "6.12.22"; + public static readonly string kAppsFlyerPluginVersion = "6.13.0"; public static string CallBackObjectName = null; private static EventHandler onRequestResponse; private static EventHandler onInAppResponse; @@ -222,6 +222,21 @@ public static void setAppInviteOneLinkID(string oneLinkId) } + } + + /// + /// Set the deepLink timeout value that should be used for DDL. + /// + /// deepLink timeout in milliseconds. + public static void setDeepLinkTimeout(long deepLinkTimeout) + { + + if (instance != null) + { + instance.setDeepLinkTimeout(deepLinkTimeout); + } + + } /// @@ -306,6 +321,18 @@ public static void setCurrencyCode(string currencyCode) } } + /// + /// Sets or updates the user consent data related to GDPR and DMA regulations for advertising and data usage purposes within the application. + /// + /// instance of AppsFlyerConsent. + public static void setConsentData(AppsFlyerConsent appsFlyerConsent) + { + if (instance != null) + { + instance.setConsentData(appsFlyerConsent); + } + } + /// /// Manually record the location of the user. /// @@ -339,6 +366,19 @@ public static void anonymizeUser(bool shouldAnonymizeUser) } + /// + /// Calling enableTCFDataCollection(true) will enable collecting and sending any TCF related data. + /// Calling enableTCFDataCollection(false) will disable the collection of TCF related data and from sending it. + /// + /// should start TCF Data collection boolean. + public static void enableTCFDataCollection(bool shouldCollectTcfData) + { + if (instance != null) + { + instance.enableTCFDataCollection(shouldCollectTcfData); + } + } + /// /// Get AppsFlyer's unique device ID which is created for every new install of an app. /// diff --git a/Assets/AppsFlyer/AppsFlyerAndroid.cs b/Assets/AppsFlyer/AppsFlyerAndroid.cs index 7e853a13..9b73f66d 100644 --- a/Assets/AppsFlyer/AppsFlyerAndroid.cs +++ b/Assets/AppsFlyer/AppsFlyerAndroid.cs @@ -197,6 +197,17 @@ public void setAdditionalData(Dictionary customData) #endif } + //// + /// Set the deepLink timeout value that should be used for DDL. + /// + /// deepLink timeout in milliseconds. + public void setDeepLinkTimeout(long deepLinkTimeout) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setDeepLinkTimeout", deepLinkTimeout); +#endif + } + /// /// Set the user emails. /// @@ -353,6 +364,18 @@ public void anonymizeUser(bool isDisabled) #endif } + /// + /// Calling enableTCFDataCollection(true) will enable collecting and sending any TCF related data. + /// Calling enableTCFDataCollection(false) will disable the collection of TCF related data and from sending it. + /// + /// should start TCF Data collection boolean. + public void enableTCFDataCollection(bool shouldCollectTcfData) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("enableTCFDataCollection", shouldCollectTcfData); +#endif + } + /// /// Enable the collection of Facebook Deferred AppLinks. /// Requires Facebook SDK and Facebook app on target/client device. @@ -366,6 +389,18 @@ public void enableFacebookDeferredApplinks(bool isEnabled) #endif } + /// + /// Sets or updates the user consent data related to GDPR and DMA regulations for advertising and data usage purposes within the application. + /// call this method when GDPR user is true + /// + /// hasConsentForDataUsage boolean. + /// hasConsentForAdsPersonalization boolean. + public void setConsentData(AppsFlyerConsent appsFlyerConsent) + { +#if !UNITY_EDITOR + appsFlyerAndroid.CallStatic("setConsentData", appsFlyerConsent.isUserSubjectToGDPR, appsFlyerConsent.hasConsentForDataUsage, appsFlyerConsent.hasConsentForAdsPersonalization); +#endif + } /// /// Restrict reengagement via deep-link to once per each unique deep-link. diff --git a/Assets/AppsFlyer/AppsFlyerConsent.cs b/Assets/AppsFlyer/AppsFlyerConsent.cs new file mode 100644 index 00000000..341e5308 --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyerConsent.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; + +namespace AppsFlyerSDK +{ + /// + // Data class representing a user's consent for data processing in accordance with GDPR and DMA + // (Digital Markets Act) compliance, specifically regarding advertising preferences. + + // This class should be used to notify and record the user's applicability + // under GDPR, their general consent to data usage, and their consent to personalized + // advertisements based on user data. + + // Note that the consent for data usage and ads personalization pair is only applicable when the user is + // subject to GDPR guidelines. Therefore, the following factory methods should be used accordingly: + // - Use [forGDPRUser] when the user is subject to GDPR. + // - Use [forNonGDPRUser] when the user is not subject to GDPR. + + // @property isUserSubjectToGDPR Indicates whether GDPR regulations apply to the user (true if the user is + // a subject of GDPR). It also serves as a flag for compliance with relevant aspects of DMA regulations. + // @property hasConsentForDataUsage Indicates whether the user has consented to the use of their data for advertising + // purposes under both GDPR and DMA guidelines (true if the user has consented, nullable if not subject to GDPR). + // @property hasConsentForAdsPersonalization Indicates whether the user has consented to the use of their data for + // personalized advertising within the boundaries of GDPR and DMA rules (true if the user has consented to + // personalized ads, nullable if not subject to GDPR). + /// + public class AppsFlyerConsent + { + public bool isUserSubjectToGDPR { get; private set; } + public bool hasConsentForDataUsage { get; private set; } + public bool hasConsentForAdsPersonalization { get; private set; } + + private AppsFlyerConsent(bool isGDPR, bool hasForDataUsage, bool hasForAdsPersonalization) + { + isUserSubjectToGDPR = isGDPR; + hasConsentForDataUsage = hasForDataUsage; + hasConsentForAdsPersonalization = hasForAdsPersonalization; + } + + public static AppsFlyerConsent ForGDPRUser(bool hasConsentForDataUsage, bool hasConsentForAdsPersonalization) + { + return new AppsFlyerConsent(true, hasConsentForDataUsage, hasConsentForAdsPersonalization); + } + + public static AppsFlyerConsent ForNonGDPRUser() + { + return new AppsFlyerConsent(false, false, false); + } + } + +} \ No newline at end of file diff --git a/Assets/AppsFlyer/AppsFlyerConsent.cs.meta b/Assets/AppsFlyer/AppsFlyerConsent.cs.meta new file mode 100644 index 00000000..5a881dee --- /dev/null +++ b/Assets/AppsFlyer/AppsFlyerConsent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a97c986fe4ee0461badf7042e08db3f3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/AppsFlyer/AppsFlyeriOS.cs b/Assets/AppsFlyer/AppsFlyeriOS.cs index 8bc91e59..86e2906d 100644 --- a/Assets/AppsFlyer/AppsFlyeriOS.cs +++ b/Assets/AppsFlyer/AppsFlyeriOS.cs @@ -185,6 +185,40 @@ public void setAppInviteOneLinkID(string appInviteOneLinkID) #endif } + /// + /// Set the deepLink timeout value that should be used for DDL. + /// + /// deepLink timeout in milliseconds. + public void setDeepLinkTimeout(long deepLinkTimeout) + { +#if !UNITY_EDITOR + _setDeepLinkTimeout(deepLinkTimeout); +#endif + } + + /// + /// Calling enableTCFDataCollection(true) will enable collecting and sending any TCF related data. + /// Calling enableTCFDataCollection(false) will disable the collection of TCF related data and from sending it. + /// + /// should start TCF Data collection boolean. + public void enableTCFDataCollection(bool shouldCollectTcfData) + { +#if !UNITY_EDITOR + _enableTCFDataCollection(shouldCollectTcfData); +#endif + } + + /// + /// Sets or updates the user consent data related to GDPR and DMA regulations for advertising and data usage purposes within the application. + /// + /// instance of AppsFlyerConsent. + public void setConsentData(AppsFlyerConsent appsFlyerConsent) + { +#if !UNITY_EDITOR + _setConsentData(appsFlyerConsent.isUserSubjectToGDPR, appsFlyerConsent.hasConsentForDataUsage, appsFlyerConsent.hasConsentForAdsPersonalization); +#endif + } + /// /// Anonymize user Data. /// Use this API during the SDK Initialization to explicitly anonymize a user's installs, events and sessions. @@ -675,6 +709,13 @@ public static void getCallback(string gameObjectName, string callbackName, strin #endif private static extern void _setAppInviteOneLinkID(string appInviteOneLinkID); +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setDeepLinkTimeout(long deepLinkTimeout); + #if UNITY_IOS [DllImport("__Internal")] #elif UNITY_STANDALONE_OSX @@ -682,6 +723,20 @@ public static void getCallback(string gameObjectName, string callbackName, strin #endif private static extern void _anonymizeUser(bool shouldAnonymizeUser); +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _enableTCFDataCollection(bool shouldCollectTcfData); + +#if UNITY_IOS + [DllImport("__Internal")] +#elif UNITY_STANDALONE_OSX + [DllImport("AppsFlyerBundle")] +#endif + private static extern void _setConsentData(bool isUserSubjectToGDPR, bool hasConsentForDataUsage, bool hasConsentForAdsPersonalization); + #if UNITY_IOS [DllImport("__Internal")] #elif UNITY_STANDALONE_OSX diff --git a/Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml b/Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml index b9187225..eb31f7a0 100644 --- a/Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml +++ b/Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml @@ -2,16 +2,16 @@ - + - + - + diff --git a/Assets/AppsFlyer/IAppsFlyerNativeBridge.cs b/Assets/AppsFlyer/IAppsFlyerNativeBridge.cs index 43e329d0..fb1a9cff 100644 --- a/Assets/AppsFlyer/IAppsFlyerNativeBridge.cs +++ b/Assets/AppsFlyer/IAppsFlyerNativeBridge.cs @@ -25,6 +25,8 @@ public interface IAppsFlyerNativeBridge void setAdditionalData(Dictionary customData); + void setDeepLinkTimeout(long deepLinkTimeout); + void setResolveDeepLinkURLs(params string[] urls); void setOneLinkCustomDomain(params string[] domains); @@ -37,6 +39,10 @@ public interface IAppsFlyerNativeBridge string getAppsFlyerId(); + void enableTCFDataCollection(bool shouldCollectTcfData); + + void setConsentData(AppsFlyerConsent appsFlyerConsent); + void setMinTimeBetweenSessions(int seconds); void setHost(string hostPrefixName, string hostName); diff --git a/Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.mm b/Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.mm index b13a2e8f..3190be4b 100644 --- a/Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.mm +++ b/Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.mm @@ -18,7 +18,7 @@ static void unityCallBack(NSString* objectName, const char* method, const char* const void _startSDK(bool shouldCallback, const char* objectName) { [[AppsFlyerLib shared] setPluginInfoWith: AFSDKPluginUnity - pluginVersion:@"6.12.22" + pluginVersion:@"6.13.0" additionalParams:nil]; startRequestObjectName = stringFromChar(objectName); AppsFlyeriOSWarpper.didCallStart = YES; @@ -75,10 +75,28 @@ const void _setAppInviteOneLinkID (const char* appInviteOneLinkID) { [[AppsFlyerLib shared] setAppInviteOneLink:stringFromChar(appInviteOneLinkID)]; } + const void _setDeepLinkTimeout (long deepLinkTimeout) { + [AppsFlyerLib shared].deepLinkTimeout = deepLinkTimeout; + } + const void _anonymizeUser (bool anonymizeUser) { [AppsFlyerLib shared].anonymizeUser = anonymizeUser; } + const void _enableTCFDataCollection (bool shouldCollectTcfData) { + [[AppsFlyerLib shared] enableTCFDataCollection:shouldCollectTcfData]; + } + + const void _setConsentData(bool isUserSubjectToGDPR, bool hasConsentForDataUsage, bool hasConsentForAdsPersonalization) { + AppsFlyerConsent *consentData = nil; + if (isUserSubjectToGDPR) { + consentData = [[AppsFlyerConsent alloc] initForGDPRUserWithHasConsentForDataUsage:hasConsentForDataUsage hasConsentForAdsPersonalization:hasConsentForAdsPersonalization]; + } else { + consentData = [[AppsFlyerConsent alloc] initNonGDPRUser]; + } + [[AppsFlyerLib shared] setConsentData:consentData]; + } + const void _setDisableCollectIAd (bool disableCollectASA) { [AppsFlyerLib shared].disableCollectASA = disableCollectASA; } diff --git a/Assets/AppsFlyer/package.json b/Assets/AppsFlyer/package.json index 915962bd..7640a68c 100644 --- a/Assets/AppsFlyer/package.json +++ b/Assets/AppsFlyer/package.json @@ -2,7 +2,7 @@ "name": "appsflyer-unity-plugin", "displayName": "AppsFlyer", "description": "AppsFlyer Unity plugin", - "version": "6.12.22", + "version": "6.13.0", "unity": "2019.4", "license": "MIT" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 0de3011c..3ecb9def 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,11 @@ # Versions -## v6.12.52 -* Update iOS SDK version - 6.12.3 -* Update Android SDK version - 6.12.5 +## v6.13.0 +* Update iOS SDK version - 6.13.0 +* Update Android SDK version - 6.13.0 * Added new iOS and Android API `setDeepLinkTimeout` +* Added new iOS and Android API `enableTCFDataCollection` +* Added new iOS and Android API `setConsentData` ## v6.12.22 * Update EDM4U - 1.2.177 @@ -246,4 +248,3 @@ Changes and fixes: - New plugin with breaking changes. Please see migration doc with details. - diff --git a/README.md b/README.md index c19ee52c..cd2de795 100755 --- a/README.md +++ b/README.md @@ -16,8 +16,8 @@ ### This plugin is built for -- Android AppsFlyer SDK **v6.12.2** -- iOS AppsFlyer SDK **v6.12.2** +- Android AppsFlyer SDK v6.13.0 +- iOS AppsFlyer SDK v6.13.0 --- ### AD_ID permission for Android diff --git a/android-unity-wrapper/gradle.properties b/android-unity-wrapper/gradle.properties index 3c5e7cf3..c8c575e1 100644 --- a/android-unity-wrapper/gradle.properties +++ b/android-unity-wrapper/gradle.properties @@ -20,8 +20,8 @@ android.enableJetifier=true GROUP=com.appsflyer -VERSION_CODE=31 -VERSION_NAME=6.12.22 +VERSION_CODE=36 +VERSION_NAME=6.13.01 POM_ARTIFACT_ID=unity-wrapper POM_PACKAGING=aar diff --git a/android-unity-wrapper/gradle/wrapper/gradle-wrapper.properties b/android-unity-wrapper/gradle/wrapper/gradle-wrapper.properties index 1724911e..69f5dab5 100644 --- a/android-unity-wrapper/gradle/wrapper/gradle-wrapper.properties +++ b/android-unity-wrapper/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,4 @@ -#Wed Apr 01 14:58:41 IDT 2020 +#Thu Jan 25 14:04:48 IST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/android-unity-wrapper/unitywrapper/build.gradle b/android-unity-wrapper/unitywrapper/build.gradle index db5f697d..5038cb6a 100644 --- a/android-unity-wrapper/unitywrapper/build.gradle +++ b/android-unity-wrapper/unitywrapper/build.gradle @@ -1,12 +1,12 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 29 + compileSdkVersion 33 defaultConfig { minSdkVersion 16 - targetSdkVersion 29 + targetSdkVersion 33 versionCode 1 versionName "1.0" @@ -31,7 +31,7 @@ repositories { dependencies { compileOnly fileTree(dir: 'libs', include: ['*.jar']) compileOnly 'androidx.appcompat:appcompat:1.1.0' - compileOnly 'com.appsflyer:af-android-sdk:6.12.2' + compileOnly 'com.appsflyer:af-android-sdk:6.13.0' } diff --git a/android-unity-wrapper/unitywrapper/src/main/java/com/appsflyer/unity/AppsFlyerAndroidWrapper.java b/android-unity-wrapper/unitywrapper/src/main/java/com/appsflyer/unity/AppsFlyerAndroidWrapper.java index ec581cc0..87e6b251 100644 --- a/android-unity-wrapper/unitywrapper/src/main/java/com/appsflyer/unity/AppsFlyerAndroidWrapper.java +++ b/android-unity-wrapper/unitywrapper/src/main/java/com/appsflyer/unity/AppsFlyerAndroidWrapper.java @@ -4,6 +4,7 @@ import androidx.annotation.NonNull; import com.appsflyer.AFLogger; +import com.appsflyer.AppsFlyerConsent; import com.appsflyer.AppsFlyerConversionListener; import com.appsflyer.AppsFlyerInAppPurchaseValidatorListener; import com.appsflyer.AppsFlyerLib; @@ -37,9 +38,11 @@ public class AppsFlyerAndroidWrapper { private static final String ON_DEEPLINKING = "onDeepLinking"; private static final String START_REQUEST_CALLBACK = "requestResponseReceived"; private static final String IN_APP_RESPONSE_CALLBACK = "inAppResponseReceived"; - private static final String PLUGIN_VERSION = "6.12.22"; + private static final String PLUGIN_VERSION = "6.13.0"; + private static final long DDL_TIMEOUT_DEFAULT = 3000; private static AppsFlyerConversionListener conversionListener; private static String devkey = ""; + private static long ddlTimeout = DDL_TIMEOUT_DEFAULT; public static void initSDK(String devKey, String objectName) { if (conversionListener == null && objectName != null){ @@ -117,6 +120,19 @@ public static void setCustomerIdAndTrack(String id) { AppsFlyerLib.getInstance().setCustomerIdAndLogSession(id, UnityPlayer.currentActivity); } + public static void enableTCFDataCollection(boolean shouldCollectTcfData) { + AppsFlyerLib.getInstance().enableTCFDataCollection(shouldCollectTcfData); + } + + public static void setConsentData(boolean isUserSubjectToGDPR, boolean hasConsentForDataUsage, boolean hasConsentForAdsPersonalization) { + AppsFlyerConsent consent; + if (isUserSubjectToGDPR) + consent = AppsFlyerConsent.forGDPRUser(hasConsentForDataUsage, hasConsentForAdsPersonalization); + else + consent = AppsFlyerConsent.forNonGDPRUser(); + AppsFlyerLib.getInstance().setConsentData(consent); + } + public static String getOutOfStore() { return AppsFlyerLib.getInstance().getOutOfStore(UnityPlayer.currentActivity); } @@ -388,14 +404,26 @@ public void onResponseError(String error) { } public static void subscribeForDeepLink(final String objectName){ - AppsFlyerLib.getInstance().subscribeForDeepLink(new DeepLinkListener() { - @Override - public void onDeepLinking(@NonNull DeepLinkResult deepLinkResult) { - if(objectName != null){ - UnityPlayer.UnitySendMessage(objectName, ON_DEEPLINKING, deepLinkResult.toString()); + if (ddlTimeout != DDL_TIMEOUT_DEFAULT) { + AppsFlyerLib.getInstance().subscribeForDeepLink(new DeepLinkListener() { + @Override + public void onDeepLinking(@NonNull DeepLinkResult deepLinkResult) { + if(objectName != null){ + UnityPlayer.UnitySendMessage(objectName, ON_DEEPLINKING, deepLinkResult.toString()); + } } - } - }); + }, ddlTimeout); + } else + { + AppsFlyerLib.getInstance().subscribeForDeepLink(new DeepLinkListener() { + @Override + public void onDeepLinking(@NonNull DeepLinkResult deepLinkResult) { + if(objectName != null){ + UnityPlayer.UnitySendMessage(objectName, ON_DEEPLINKING, deepLinkResult.toString()); + } + } + }); + } } public static void addPushNotificationDeepLinkPath(String ... path){ @@ -418,4 +446,8 @@ public static void setPluginInfo() { PluginInfo pluginInfo = new PluginInfo(Plugin.UNITY, PLUGIN_VERSION); AppsFlyerLib.getInstance().setPluginInfo(pluginInfo); } + + public static void setDeepLinkTimeout(long deepLinkTimeout) { + ddlTimeout = deepLinkTimeout; + } } diff --git a/appsflyer-unity-plugin-6.12.22.unitypackage b/appsflyer-unity-plugin-6.12.22.unitypackage deleted file mode 100644 index 54496590..00000000 Binary files a/appsflyer-unity-plugin-6.12.22.unitypackage and /dev/null differ diff --git a/appsflyer-unity-plugin-6.13.0.unitypackage b/appsflyer-unity-plugin-6.13.0.unitypackage new file mode 100644 index 00000000..60785cd5 Binary files /dev/null and b/appsflyer-unity-plugin-6.13.0.unitypackage differ diff --git a/deploy/build_unity_package.sh b/deploy/build_unity_package.sh index 55d13690..b56b0d0c 100644 --- a/deploy/build_unity_package.sh +++ b/deploy/build_unity_package.sh @@ -4,7 +4,7 @@ echo "Start Build for appsflyer-unity-plugin.unitypackage" DEPLOY_PATH=outputs UNITY_PATH="/Applications/Unity/Unity.app/Contents/MacOS/Unity" -PACKAGE_NAME="appsflyer-unity-plugin-6.12.22.unitypackage" +PACKAGE_NAME="appsflyer-unity-plugin-6.13.0.unitypackage" mkdir -p $DEPLOY_PATH #move external dependency manager @@ -12,7 +12,7 @@ echo "moving the external dependency manager to root" mv external-dependency-manager-1.2.177.unitypackage .. # Build the .unitypackage - /Volumes/T7Shield/Unity/2022.3.10f1/Unity.app/Contents/MacOS/Unity \ +/Applications/Unity/Hub/Editor/2020.3.34f1/Unity.app/Contents/MacOS/Unity \ -gvh_disable \ -batchmode \ -importPackage external-dependency-manager-1.2.177.unitypackage \ @@ -23,7 +23,7 @@ mv external-dependency-manager-1.2.177.unitypackage .. Assets \ $PWD/$DEPLOY_PATH/$PACKAGE_NAME \ -quit \ -&& echo "package exported successfully to outputs/appsflyer-unity-plugin-6.12.22.unitypackage" \ +&& echo "package exported successfully to outputs/appsflyer-unity-plugin-6.13.0.unitypackage" \ || echo "Failed to export package. See create_unity_core.log for more info." diff --git a/deploy/strict_mode_build_package.sh b/deploy/strict_mode_build_package.sh index ac730b18..09081735 100644 --- a/deploy/strict_mode_build_package.sh +++ b/deploy/strict_mode_build_package.sh @@ -5,7 +5,7 @@ echo "Start Build for appsflyer-unity-plugin.unitypackage. Strict Mode." DEPLOY_PATH=outputs UNITY_PATH="/Applications/Unity/Unity.app/Contents/MacOS/Unity" - PACKAGE_NAME="appsflyer-unity-plugin-strict-mode-6.12.22.unitypackage" + PACKAGE_NAME="appsflyer-unity-plugin-strict-mode-6.13.0.unitypackage" mkdir -p $DEPLOY_PATH #move external dependency manager @@ -26,7 +26,7 @@ echo "Commenting out functions. Done." # Build the .unitypackage - /Volumes/T7Shield/Unity/2022.3.10f1/Unity.app/Contents/MacOS/Unity \ + /Applications/Unity/Hub/Editor/2020.3.34f1/Unity.app/Contents/MacOS/Unity \ -gvh_disable \ -batchmode \ -importPackage external-dependency-manager-1.2.177.unitypackage \ @@ -37,7 +37,7 @@ echo "Commenting out functions. Done." Assets \ $PWD/$DEPLOY_PATH/$PACKAGE_NAME \ -quit \ - && echo "package exported successfully to outputs/appsflyer-unity-plugin-strict-mode-6.12.22.unitypackage" \ + && echo "package exported successfully to outputs/appsflyer-unity-plugin-strict-mode-6.13.0.unitypackage" \ || echo "Failed to export package. See create_unity_core.log for more info." diff --git a/docs/API.md b/docs/API.md index bb04fc30..2b848b9e 100755 --- a/docs/API.md +++ b/docs/API.md @@ -22,6 +22,9 @@ The list of available methods for this plugin is described below. - [setResolveDeepLinkURLs](#setresolvedeeplinkurls) - [setOneLinkCustomDomain](#setonelinkcustomdomain) - [setCurrencyCode](#setcurrencycode) + - [setDeepLinkTimeout](#setDeepLinkTimeout) + - [enableTCFDataCollection](#enableTCFDataCollection) + - [setConsentData](#setConsentData) - [recordLocation](#recordlocation) - [anonymizeUser](#anonymizeuser) - [getAppsFlyerId](#getappsflyerid) @@ -366,6 +369,62 @@ AppsFlyer.setCurrencyCode("GBP"); --- +--- + +### setDeepLinkTimeout +**`void setDeepLinkTimeout(long deepLinkTimeout)`** + +Setting the deepLink timeout value that should be used for DDL. +If you want to use it, set it before the DDL setting. + +| parameter | type | description | +| ------------------ |----------|------------------| +| `deepLinkTimeout` | `long` | in milliseconds | + +*Example:* + +```c# +AppsFlyer.setDeepLinkTimeout(2000); +``` + +--- + +### enableTCFDataCollection +**`void enableTCFDataCollection(bool shouldCollectTcfData)`** + +Calling enableTCFDataCollection(true) will enable collecting and sending any TCF related data. +Calling enableTCFDataCollection(false) will disable the collection of TCF related data and from sending it. + +| parameter | type | description | +| ------------------------ |----------|-------------------------------- | +| `shouldCollectTcfData` | `bool` | true to enable data collection | + +*Example:* + +```c# +AppsFlyer.enableTCFDataCollection(true);; +``` + +--- + +### setConsentData +**`void setConsentData(AppsFlyerConsent appsFlyerConsent)`** + +Sets or updates the user consent data related to GDPR and DMA regulations for advertising and data usage purposes within the application. + +| parameter | type | description | +| --------------------------- |---------- |------------------------------------ | +| `appsFlyerConsent` | `AppsFlyerConsent` | Instance of AppsFlyerConsent class | + +*Example:* + +```c# +AppsFlyerConsent consent = AppsFlyerConsent.ForGDPRUser(false, false); +AppsFlyer.setConsentData(consent); +``` + +--- + ### recordLocation **`void recordLocation(double latitude, double longitude)`** @@ -1609,4 +1668,3 @@ For iOS : the callback will return a JSON string from apples verifyReceipt API. ``` --- - diff --git a/docs/BasicIntegration.md b/docs/BasicIntegration.md index a027bf2b..162a6ed5 100644 --- a/docs/BasicIntegration.md +++ b/docs/BasicIntegration.md @@ -107,6 +107,90 @@ If it’s important for you to associate the install event with the CUID, call ` --- + +## Send consent for DMA compliance + +Unity SDK plugin offers two alternative methods for gathering consent data: + +Through a Consent Management Platform (CMP): If the app uses a CMP that complies with the Transparency and Consent Framework (TCF) v2.2 protocol, the Unity SDK can automatically retrieve the consent details. + +OR + +Through a dedicated Unity SDK API: Developers can pass Google's required consent data directly to the Unity SDK using a specific API designed for this purpose. + +### Use CMP to collect consent data + +1. Initialize the SDK. +2. Call enableTCFDataCollection(true) api before startSDK() to instruct the SDK to collect the TCF data from the device. +3. Use the CMP to decide if you need the consent dialog in the current session to acquire the consent data. If you need the consent dialog move to step 4; otherwise move to step 5. +4. Get confirmation from the CMP that the user has made their consent decision and the data is available. +5. Call start(). + + ```c# + AppsFlyer.initSDK(devKey, appID, this); + + AppsFlyer.enableTCFDataCollection(true); + + //YOUR_CMP_FLOW() + // if already has consent ready - you can start + AppsFlyer.startSDK(); + + //else Waiting for CMP completion and data ready and then start + + AppsFlyer.startSDK(); + ``` + +### Manually collect consent data + +1. Initialize the SDK. +2. Determine whether the GDPR applies or not to the user. + +### When GDPR applies to the user +1. Given that GDPR is applicable to the user, determine whether the consent data is already stored for this session. + i. If there is no consent data stored, show the consent dialog to capture the user consent decision. + ii. If there is consent data stored continue to the next step. + +2. To transfer the consent data to the SDK create an AppsFlyerConsent object with the following parameters: + - hasConsentForDataUsage - Indicates whether the user has consented to use their data for advertising purposes. + - hasConsentForAdsPersonalization - Indicates whether the user has consented to use their data for personalized advertising. +3. Call setConsentData()with the AppsFlyerConsent object. +5. Call start(). + + ```c# + + // If the user is subject to GDPR - collect the consent data + // or retrieve it from the storage + ... + // Set the consent data to the SDK: + AppsFlyerConsent consent = AppsFlyerConsent.ForGDPRUser(true, true); + AppsFlyer.setConsentData(consent); + + AppsFlyer.startSDK(); + ``` + +### When GDPR does not apply to the user +1. Create an AppsFlyerConsent object using the ForNonGDPRUser() initializer. This initializer doesn’t accept any parameters. +2. Pass the empty AppsFlyerConsent object to setConsentData(). +2. Call start(). + + ```c# + // If the user is not subject to GDPR: + AppsFlyerConsent consent = AppsFlyerConsent.ForNonGDPRUser(); + AppsFlyer.setConsentData(consent); + + AppsFlyer.startSDK(); + ``` + + ## Verify consent data is sent + To test whether your SDK sends DMA consent data with each event, perform the following steps: + + 1. Enable the SDK debug mode. + 2. Search for consent_data in the log of the outgoing request. + + for more information visit [iOS](https://dev.appsflyer.com/hc/docs/ios-send-consent-for-dma-compliance) + [Android](https://dev.appsflyer.com/hc/docs/android-send-consent-for-dma-compliance) +--- + ## Sending SKAN postback to Appsflyer To register the AppsFlyer endpoint, you need to add the `NSAdvertisingAttributionReportEndpoint` key to your info.plist and set the value to `https://appsflyer-skadnetwork.com/`. More info on how to update the info.plist can be found [here](https://github.com/AppsFlyerSDK/appsflyer-unity-plugin/blob/master/docs/Troubleshooting.md#updating-the-infoplist). @@ -170,4 +254,3 @@ In-App response example: | 50 | "Status code failure" + actual response code from the server | --- - diff --git a/strict-mode-sdk/appsflyer-unity-plugin-strict-mode-6.12.22.unitypackage b/strict-mode-sdk/appsflyer-unity-plugin-strict-mode-6.12.22.unitypackage deleted file mode 100644 index b80a63f9..00000000 Binary files a/strict-mode-sdk/appsflyer-unity-plugin-strict-mode-6.12.22.unitypackage and /dev/null differ diff --git a/strict-mode-sdk/appsflyer-unity-plugin-strict-mode-6.13.0.unitypackage b/strict-mode-sdk/appsflyer-unity-plugin-strict-mode-6.13.0.unitypackage new file mode 100644 index 00000000..c28e858d Binary files /dev/null and b/strict-mode-sdk/appsflyer-unity-plugin-strict-mode-6.13.0.unitypackage differ