diff --git a/CHANGELOG.md b/CHANGELOG.md index 18e089c2..6ec06f8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 6.13.0 + Release date: *2024-02-19* + +- Add DMA support +- Fix incompatible config for RN >= 0.69.x +- Update Plugin to v6.13.0 + ## 6.12.2 Release date: *2023-08-29* diff --git a/Docs/RN_API.md b/Docs/RN_API.md index 6277bc57..11905b42 100644 --- a/Docs/RN_API.md +++ b/Docs/RN_API.md @@ -35,6 +35,8 @@ The list of available methods for this plugin is described below. - [addPushNotificationDeepLinkPath](#addpushnotificationdeeplinkpath) - [appendParametersToDeepLinkingURL](#appendparameterstodeeplinkingurl) - [disableAdvertisingIdentifier](#disableAdvertisingIdentifier) + - [enableTCFDataCollection](#enableTCFDataCollection) + - [setConsentData](#setConsentData) - [Android Only APIs](#android-only-apis) - [setCollectAndroidID](#setcollectandroidid) - [setCollectIMEI](#setcollectimei) @@ -750,6 +752,51 @@ Disables collection of various Advertising IDs by the SDK.
appsFlyer.disableAdvertisingIdentifier(true); ``` +--- +### enableTCFDataCollection +`enableTCFDataCollection(enabled): void` + +instruct the SDK to collect the TCF data from the device. + + +| parameter | type | description | +| ---------- |----------|------------------ | +| enabled | boolean | enable/disable TCF data collection | + +*Example:* + +```javascript +appsFlyer.enableTCFDataCollection(true); +``` + +--- +### setConsentData +`setConsentData(consentObject): void` + +When GDPR applies to the user and your app does not use a CMP compatible with TCF v2.2, use this API to provide the consent data directly to the SDK.
+The AppsFlyerConsent object has 2 methods: + +1. `AppsFlyerConsent.forNonGDPRUser`: Indicates that GDPR doesn’t apply to the user and generates nonGDPR consent object. This method doesn’t accept any parameters. +2. `AppsFlyerConsent.forGDPRUser`: create an AppsFlyerConsent object with 2 parameters: + + +| parameter | type | description | +| ---------- |----------|------------------ | +| hasConsentForDataUsage | boolean | Indicates whether the user has consented to use their data for advertising purposes | +| hasConsentForAdsPersonalization | boolean | Indicates whether the user has consented to use their data for personalized advertising | + +*Example:* + +```javascript +import appsFlyer, {AppsFlyerConsent} from 'react-native-appsflyer'; + +let nonGDPRUser = AppsFlyerConsent.forNonGDPRUser(); +// OR +let GDPRUser = AppsFlyerConsent.forGDPRUser(true, false); + +appsFlyer.setConsentData(nonGDPRUser /**or**/ GDPRUser); +``` + ## Android Only APIs ### setCollectAndroidID diff --git a/Docs/RN_CMP.md b/Docs/RN_CMP.md new file mode 100644 index 00000000..9930bcac --- /dev/null +++ b/Docs/RN_CMP.md @@ -0,0 +1,139 @@ +--- +title: Send consent for DMA compliance +category: 5f9705393c689a065c409b23 +parentDoc: 645213236f53a00d4daa9230 +order: 12 +hidden: false +--- + +## Send consent for DMA compliance +The SDK 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 SDK can automatically retrieve the consent details. + +OR + +Through a dedicated SDK API: Developers can pass Google's required consent data directly to the SDK using a specific API designed for this purpose. + +### Use CMP to collect consent data +A CMP compatible with TCF v2.2 collects DMA consent data and stores it in NSUserDefaults (iOS) and SharedPreferences (Android). To enable the SDK to access this data and include it with every event, follow these steps: + +1. Call `appsFlyer.enableTCFDataCollection(true)` +2. Initialize the SDK in [manual start mode](/Docs/RN_API.md#initsdk) +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 in NSUserDefaults/SharedPreferences +5. Call `appsFlyer.startSdk()` +```javascript + useEffect(() => { + const option = { + isDebug: true, + devKey: 'UxXxXxXxXd', + onInstallConversionDataListener: true, + onDeepLinkListener: true, + timeToWaitForATTUserAuthorization: 10, + manualStart: true, // <-- Manual start + }; + // TCF data collection + appsFlyer.enableTCFDataCollection(true); + + //init appsflyer + appsFlyer.initSdk( + option, + res => { + console.log(res); + }, + err => { + console.log(err); + }, + ); + + ... + + // CMP Pseudocode + if (cmpManager.hasConsent()) { + appsFlyer.startSdk(); + } else { + cmpManager.presentConsentDialog(res => { + appsFlyer.startSdk(); + }); + } + },[]) +``` +## Manually collect consent data +If your app does not use a CMP compatible with TCF v2.2, use the SDK API detailed below to provide the consent data directly to the SDK. + +### When GDPR applies to the user +If GDPR applies to the user, perform the following: + +1. Given that GDPR is applicable to the user, determine whether the consent data is already stored for this session. + 1. If there is no consent data stored, show the consent dialog to capture the user consent decision. + 2. If there is consent data stored continue to the next step. +2. To transfer the consent data to the SDK create an AppsFlyerConsent object using `forGDPRUser` method that accepts the following parameters:
+ `hasConsentForDataUsage: boolean` - Indicates whether the user has consented to use their data for advertising purposes.
+ `hasConsentForAdsPersonalization: boolean` - Indicates whether the user has consented to use their data for personalized advertising. +3. Call `appsFlyer.setConsentData(consentData)` with the AppsFlyerConsent object. +4. Call `appsFlyer.initSdk()`. +```javascript +import appsFlyer, {AppsFlyerConsent} from 'react-native-appsflyer'; + +useEffect(() => { + const option = { + isDebug: true, + devKey: 'UxXxXxXxXd', + onInstallConversionDataListener: true, + onDeepLinkListener: true, + timeToWaitForATTUserAuthorization: 10, + }; + + // user consent data + let consentData = AppsFlyerConsent.forGDPRUser(true, false); + + appsFlyer.setConsentData(consentData); + + //start appsflyer + appsFlyer.initSdk( + option, + res => { + console.log(res); + }, + err => { + console.log(err); + }, + ); + },[]) +``` +### When GDPR does not apply to the user + +If GDPR doesn’t apply to the user perform the following: +1. Create an AppsFlyerConsent object using `forNonGDPRUser` method that doesn't accepts any parameters +2. Call `appsFlyer.setConsentData(consentData)` with the AppsFlyerConsent object. +3. Call `appsFlyer.initSdk()`. +```javascript +import appsFlyer, {AppsFlyerConsent} from 'react-native-appsflyer'; + +useEffect(() => { + const option = { + isDebug: true, + devKey: 'UxXxXxXxXd', + onInstallConversionDataListener: true, + onDeepLinkListener: true, + timeToWaitForATTUserAuthorization: 10, + }; + + // GDPR does not apply to the user + let consentData = AppsFlyerConsent.forNonGDPRUser(); + + appsFlyer.setConsentData(consentData); + + //start appsflyer + appsFlyer.initSdk( + option, + res => { + console.log(res); + }, + err => { + console.log(err); + }, + ); + },[]) +``` \ No newline at end of file diff --git a/Docs/RN_UserInvite.md b/Docs/RN_UserInvite.md index 50c725b8..dbb7750e 100644 --- a/Docs/RN_UserInvite.md +++ b/Docs/RN_UserInvite.md @@ -36,7 +36,7 @@ The link that is generated for the user invite will use this OneLink ID as the b ```javascript -// set the tamplate ID before you generate a link. Without it UserInvite won't work. +// set the template ID before you generate a link. Without it UserInvite won't work. appsFlyer.setAppInviteOneLinkID('scVs', null); // set the user invite params diff --git a/README.md b/README.md index 56ad9f49..423f3e79 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,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** ## ❗❗ Breaking changes when updating to v6.x.x❗❗ @@ -51,6 +51,7 @@ If you have used 1 of the removed APIs, please check the integration guide for t - [Test integration](/Docs/RN_Testing.md) - [In-app events](/Docs/RN_InAppEvents.md) - [Uninstall measurement](/Docs/RN_UninstallMeasurement.md) +- [Send consent for DMA compliance](/Docs/RN_CMP.md) ## 🔗 Deep Linking - [Integration](/Docs/RN_DeepLinkIntegrate.md) - [***Expo*** Integration](/Docs/RN_ExpoDeepLinkIntegration.md) diff --git a/android/build.gradle b/android/build.gradle index 2372c120..fd85b614 100755 --- a/android/build.gradle +++ b/android/build.gradle @@ -54,5 +54,5 @@ repositories { dependencies { implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}" implementation "com.android.installreferrer:installreferrer:${safeExtGet('installReferrerVersion', '2.1')}" - api "com.appsflyer:af-android-sdk:${safeExtGet('appsflyerVersion', '6.12.2')}" + api "com.appsflyer:af-android-sdk:${safeExtGet('appsflyerVersion', '6.13.0')}" } diff --git a/android/src/main/java/com/appsflyer/reactnative/RNAppsFlyerConstants.java b/android/src/main/java/com/appsflyer/reactnative/RNAppsFlyerConstants.java index eff5d9f1..2802506b 100755 --- a/android/src/main/java/com/appsflyer/reactnative/RNAppsFlyerConstants.java +++ b/android/src/main/java/com/appsflyer/reactnative/RNAppsFlyerConstants.java @@ -6,7 +6,7 @@ public class RNAppsFlyerConstants { - final static String PLUGIN_VERSION = "6.12.2"; + final static String PLUGIN_VERSION = "6.13.0"; final static String NO_DEVKEY_FOUND = "No 'devKey' found or its empty"; final static String UNKNOWN_ERROR = "AF Unknown Error"; final static String SUCCESS = "Success"; diff --git a/android/src/main/java/com/appsflyer/reactnative/RNAppsFlyerModule.java b/android/src/main/java/com/appsflyer/reactnative/RNAppsFlyerModule.java index c607a1a5..90989a67 100755 --- a/android/src/main/java/com/appsflyer/reactnative/RNAppsFlyerModule.java +++ b/android/src/main/java/com/appsflyer/reactnative/RNAppsFlyerModule.java @@ -815,7 +815,27 @@ public void performOnDeepLinking() { Log.d("AppsFlyer", "performOnDeepLinking: activity is null!"); } } - + + @ReactMethod + public void enableTCFDataCollection(Boolean enabled) { + AppsFlyerLib.getInstance().enableTCFDataCollection(enabled); + } + + @ReactMethod + public void setConsentData(ReadableMap consentData) { + JSONObject JSONConsentData = RNUtil.readableMapToJson(consentData); + boolean isUserSubjectToGDPR = JSONConsentData.optBoolean("isUserSubjectToGDPR"); + boolean hasConsentForDataUsage = JSONConsentData.optBoolean("hasConsentForDataUsage"); + boolean hasConsentForAdsPersonalization = JSONConsentData.optBoolean("hasConsentForAdsPersonalization"); + AppsFlyerConsent consentObject; + if (isUserSubjectToGDPR) { + consentObject = AppsFlyerConsent.forGDPRUser(hasConsentForDataUsage, hasConsentForAdsPersonalization); + } else { + consentObject = AppsFlyerConsent.forNonGDPRUser(); + } + AppsFlyerLib.getInstance().setConsentData(consentObject); + } + @ReactMethod public void addListener(String eventName) { // Keep: Required for RN built in Event Emitter Calls. diff --git a/demos/appsflyer-react-native-app/android/build.gradle b/demos/appsflyer-react-native-app/android/build.gradle index 7591242f..e5f20a04 100644 --- a/demos/appsflyer-react-native-app/android/build.gradle +++ b/demos/appsflyer-react-native-app/android/build.gradle @@ -4,8 +4,8 @@ buildscript { ext { buildToolsVersion = "30.0.2" minSdkVersion = 21 - compileSdkVersion = 31 - targetSdkVersion = 31 + compileSdkVersion = 32 + targetSdkVersion = 32 ndkVersion = "20.1.5948944" } repositories { diff --git a/demos/appsflyer-react-native-app/package.json b/demos/appsflyer-react-native-app/package.json index c79dfa0b..ce3eac5d 100644 --- a/demos/appsflyer-react-native-app/package.json +++ b/demos/appsflyer-react-native-app/package.json @@ -18,8 +18,8 @@ "react-native-elements": "^3.4.2", "react-native-gesture-handler": "^1.10.3", "react-native-safe-area-context": "^3.3.2", - "react-native-screens": "^3.7.0", - "react-native-vector-icons": "^8.1.0" + "react-native-screens": "3.7.2", + "react-native-vector-icons": "8.1.0" }, "devDependencies": { "@babel/core": "^7.12.9", diff --git a/index.d.ts b/index.d.ts index bddce131..e1ae4930 100644 --- a/index.d.ts +++ b/index.d.ts @@ -114,6 +114,13 @@ declare module "react-native-appsflyer" { brandDomain?: string; } + export const AppsFlyerConsent: { + forGDPRUser: (hasConsentForDataUsage: boolean, hasConsentForAdsPersonalization: boolean) => void; + forNonGDPRUser: () => void; + } + + export type AppsFlyerConsentType = typeof AppsFlyerConsent; + const appsFlyer: { onInstallConversionData(callback: (data: ConversionData) => any): () => void; onInstallConversionFailure(callback: (data: ConversionData) => any): () => void; @@ -151,6 +158,8 @@ declare module "react-native-appsflyer" { setPartnerData(partnerId: string, partnerData: object): void appendParametersToDeepLinkingURL(contains: string, parameters: object): void startSdk(): void + enableTCFDataCollection(enabled: boolean): void + setConsentData(consentData: AppsFlyerConsentType): void /** * For iOS Only diff --git a/index.js b/index.js index 93e2e0d2..07a297c8 100755 --- a/index.js +++ b/index.js @@ -625,10 +625,48 @@ appsFlyer.performOnDeepLinking = () => { return RNAppsFlyer.performOnDeepLinking(); }; +/** + * instruct the SDK to collect the TCF data from the device. + * @param enabled: if the sdk should collect the TCF data. true/false + */ +appsFlyer.enableTCFDataCollection= (enabled) => { + return RNAppsFlyer.enableTCFDataCollection(enabled); +} + +/** + * If your app does not use a CMP compatible with TCF v2.2, use the SDK API detailed below to provide the consent data directly to the SDK. + * @param consentData: AppsFlyerConsent object. + */ +appsFlyer.setConsentData = (consentData) => { + return RNAppsFlyer.setConsentData(consentData); +} + function AFParseJSONException(_message, _data) { this.message = _message; this.data = _data; this.name = 'AFParseJSONException'; } -export default appsFlyer; +// Consent object +export const AppsFlyerConsent = (function () { + // Private constructor + function AppsFlyerConsent(isUserSubjectToGDPR, hasConsentForDataUsage, hasConsentForAdsPersonalization) { + this.isUserSubjectToGDPR = isUserSubjectToGDPR; + this.hasConsentForDataUsage = hasConsentForDataUsage; + this.hasConsentForAdsPersonalization = hasConsentForAdsPersonalization; + } + + return { + // Factory method for GDPR user + forGDPRUser: function(hasConsentForDataUsage, hasConsentForAdsPersonalization) { + return new AppsFlyerConsent(true, hasConsentForDataUsage, hasConsentForAdsPersonalization); + }, + + // Factory method for non GDPR user + forNonGDPRUser: function() { + return new AppsFlyerConsent(false, null, null); + } + }; +})(); + +export default appsFlyer; \ No newline at end of file diff --git a/ios/AppsFlyerConsent.h b/ios/AppsFlyerConsent.h new file mode 100644 index 00000000..564912a9 --- /dev/null +++ b/ios/AppsFlyerConsent.h @@ -0,0 +1,26 @@ +// +// AppsFlyerConsent.h +// AppsFlyerLib +// +// Created by Veronica Belyakov on 14/01/2024. +// +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface AppsFlyerConsent : NSObject + +@property (nonatomic, readonly, assign) BOOL isUserSubjectToGDPR; +@property (nonatomic, readonly, assign) BOOL hasConsentForDataUsage; +@property (nonatomic, readonly, assign) BOOL hasConsentForAdsPersonalization; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +- (instancetype)initForGDPRUserWithHasConsentForDataUsage:(BOOL)hasConsentForDataUsage + hasConsentForAdsPersonalization:(BOOL)hasConsentForAdsPersonalization NS_DESIGNATED_INITIALIZER; +- (instancetype)initNonGDPRUser NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/AppsFlyerLib.h b/ios/AppsFlyerLib.h index 0b900a92..34ee5f01 100644 --- a/ios/AppsFlyerLib.h +++ b/ios/AppsFlyerLib.h @@ -2,7 +2,7 @@ // AppsFlyerLib.h // AppsFlyerLib // -// AppsFlyer iOS SDK 6.10.1 (109) +// AppsFlyer iOS SDK 6.13.0 (148) // Copyright (c) 2012-2023 AppsFlyer Ltd. All rights reserved. // @@ -12,6 +12,7 @@ #import #import #import +#import NS_ASSUME_NONNULL_BEGIN @@ -140,7 +141,7 @@ typedef enum { EmailCryptTypeSHA256 = 3 } EmailCryptType; -typedef NS_CLOSED_ENUM (NSInteger ,AFSDKPlugin) { +typedef NS_CLOSED_ENUM(NSInteger, AFSDKPlugin) { AFSDKPluginIOSNative, AFSDKPluginUnity, AFSDKPluginFlutter, @@ -159,7 +160,6 @@ typedef NS_CLOSED_ENUM (NSInteger ,AFSDKPlugin) { AFSDKPluginAdobeSwiftAEP } NS_SWIFT_NAME(Plugin); -@class AFSDKPluginInfo; NS_SWIFT_NAME(DeepLinkDelegate) @protocol AppsFlyerDeepLinkDelegate @@ -351,7 +351,7 @@ NS_SWIFT_NAME(waitForATTUserAuthorization(timeoutInterval:)); [[AppsFlyerLib shared] setResolveDeepLinkURLs:@[@"domain.com", @"subdomain.domain.com"]]; */ -@property(nonatomic, nullable) NSArray *resolveDeepLinkURLs; +@property(nonatomic, nullable, copy) NSArray *resolveDeepLinkURLs; /** For advertisers who use vanity OneLinks. @@ -362,12 +362,12 @@ NS_SWIFT_NAME(waitForATTUserAuthorization(timeoutInterval:)); [[AppsFlyerLib shared] oneLinkCustomDomains:@[@"domain.com", @"subdomain.domain.com"]]; */ -@property(nonatomic, nullable) NSArray *oneLinkCustomDomains; +@property(nonatomic, nullable, copy) NSArray *oneLinkCustomDomains; /* * Set phone number for each `start` event. `phoneNumber` will be sent as SHA256 string */ -@property(nonatomic, nullable) NSString *phoneNumber; +@property(nonatomic, nullable, copy) NSString *phoneNumber; - (NSString *)phoneNumber UNAVAILABLE_ATTRIBUTE; @@ -390,13 +390,16 @@ NS_SWIFT_NAME(waitForATTUserAuthorization(timeoutInterval:)); AppsFlyerLib.shared().currentDeviceLanguage("EN") */ -@property(nonatomic, nullable) NSString *currentDeviceLanguage; +@property(nonatomic, nullable, copy) NSString *currentDeviceLanguage; /** Internal API. Please don't use. */ -- (void)setPluginInfoWith:(AFSDKPlugin)plugin pluginVersion:(NSString *)version additionalParams:(NSDictionary * _Nullable)additionalParams +- (void)setPluginInfoWith:(AFSDKPlugin)plugin + pluginVersion:(NSString *)version + additionalParams:(NSDictionary * _Nullable)additionalParams NS_SWIFT_NAME(setPluginInfo(plugin:version:additionalParams:)); + /** Enable the collection of Facebook Deferred AppLinks Requires Facebook SDK and Facebook app on target/client device. @@ -578,6 +581,11 @@ NS_SWIFT_NAME(logEvent(name:values:completionHandler:)); */ - (void)remoteDebuggingCallWithData:(NSString *)data; +/** + This is for internal use. + */ +- (void)remoteDebuggingCallV2WithData:(NSString *)dataAsString; + /** Used to force the trigger `onAppOpenAttribution` delegate. Notice, re-engagement, session and launch won't be counted. @@ -634,13 +642,13 @@ NS_SWIFT_NAME(logEvent(name:values:completionHandler:)); /** API to set manually Facebook deferred app link */ -@property(nonatomic, nullable) NSURL *facebookDeferredAppLink; +@property(nonatomic, nullable, copy) NSURL *facebookDeferredAppLink; /** Block an events from being shared with ad networks and other 3rd party integrations Must only include letters/digits or underscore, maximum length: 45 */ -@property(nonatomic, nullable) NSArray *sharingFilter DEPRECATED_MSG_ATTRIBUTE("starting SDK version 6.4.0, please use `setSharingFilterForPartners:`"); +@property(nonatomic, nullable, copy) NSArray *sharingFilter DEPRECATED_MSG_ATTRIBUTE("starting SDK version 6.4.0, please use `setSharingFilterForPartners:`"); @property(nonatomic) NSUInteger deepLinkTimeout; @@ -661,6 +669,27 @@ NS_SWIFT_NAME(logEvent(name:values:completionHandler:)); */ - (void)setSharingFilterForPartners:(NSArray * _Nullable)sharingFilter; + +/** + Sets or updates the user consent data related to GDPR and DMA regulations for advertising and data usage + purposes within the application. This method must be invoked with the user's current consent status each + time the app starts or whenever there is a change in the user's consent preferences. + + Note that this method does not persist the consent data across app sessions; it only applies for the + duration of the current app session. If you wish to stop providing the consent data, you should + cease calling this method. + + @param consent an instance of AppsFlyerConsent that encapsulates the user's consent information. + */ +- (void)setConsentData:(AppsFlyerConsent *)consent; + +/** + Enable the SDK to collect and send TCF data + + @param shouldCollectConsentData indicates if the TCF data collection is enabled. + */ +- (void)enableTCFDataCollection:(BOOL)shouldCollectConsentData; + /** Validate if URL contains certain string and append quiery parameters to deeplink URL. In case if URL does not contain user-defined string, diff --git a/ios/AppsFlyerLinkGenerator.h b/ios/AppsFlyerLinkGenerator.h index b917074e..d3ec8f4e 100644 --- a/ios/AppsFlyerLinkGenerator.h +++ b/ios/AppsFlyerLinkGenerator.h @@ -22,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN /// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]` + (instancetype)new NS_UNAVAILABLE; -@property(nonatomic, nullable) NSString *brandDomain; +@property(nonatomic, nullable, copy) NSString *brandDomain; /// The channel through which the invite was sent (e.g. Facebook/Gmail/etc.). Usage: Recommended - (void)setChannel :(nonnull NSString *)channel; diff --git a/ios/RNAppsFlyer.h b/ios/RNAppsFlyer.h index 506499ce..03487ab8 100755 --- a/ios/RNAppsFlyer.h +++ b/ios/RNAppsFlyer.h @@ -22,7 +22,7 @@ @end -static NSString *const kAppsFlyerPluginVersion = @"6.12.2"; +static NSString *const kAppsFlyerPluginVersion = @"6.13.0"; static NSString *const NO_DEVKEY_FOUND = @"No 'devKey' found or its empty"; static NSString *const NO_APPID_FOUND = @"No 'appId' found or its empty"; static NSString *const NO_EVENT_NAME_FOUND = @"No 'eventName' found or its empty"; diff --git a/ios/RNAppsFlyer.m b/ios/RNAppsFlyer.m index 284c31e9..43e48f78 100755 --- a/ios/RNAppsFlyer.m +++ b/ios/RNAppsFlyer.m @@ -564,4 +564,26 @@ - (BOOL)isExpoApp { RCT_EXPORT_METHOD(appendParametersToDeepLinkingURL:(NSString *)contains partnerData:(NSDictionary *)parameters) { [[AppsFlyerLib shared] appendParametersToDeepLinkingURLWithString:contains parameters:parameters]; } + +RCT_EXPORT_METHOD(enableTCFDataCollection:(BOOL *)enabled) { + [[AppsFlyerLib shared] enableTCFDataCollection:enabled]; +} + +RCT_EXPORT_METHOD(setConsentData:(NSDictionary *)consentDictionary) { + if (![consentDictionary isKindOfClass:[NSNull null]]) { + BOOL isUserSubjectToGDPR = [consentDictionary[@"isUserSubjectToGDPR"] boolValue]; + + AppsFlyerConsent *consentData; + if (isUserSubjectToGDPR){ + BOOL hasConsentForDataUsage = [consentDictionary[@"hasConsentForDataUsage"] boolValue]; + BOOL hasConsentForAdsPersonalization = [consentDictionary[@"hasConsentForAdsPersonalization"] boolValue]; + consentData = [[AppsFlyerConsent alloc] initForGDPRUserWithHasConsentForDataUsage:hasConsentForDataUsage hasConsentForAdsPersonalization:hasConsentForAdsPersonalization]; + } else { + consentData = [[AppsFlyerConsent alloc] initNonGDPRUser]; + } + + [[AppsFlyerLib shared] setConsentData:consentData]; + } +} + @end diff --git a/package.json b/package.json index 7813f911..674815a4 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-appsflyer", - "version": "6.12.2", + "version": "6.13.0", "description": "React Native Appsflyer plugin", "main": "index.js", "types": "index.d.ts", diff --git a/react-native-appsflyer.podspec b/react-native-appsflyer.podspec index 7674b34e..5daca372 100644 --- a/react-native-appsflyer.podspec +++ b/react-native-appsflyer.podspec @@ -18,13 +18,13 @@ Pod::Spec.new do |s| # AppsFlyerFramework if defined?($RNAppsFlyerStrictMode) && ($RNAppsFlyerStrictMode == true) Pod::UI.puts "#{s.name}: Using AppsFlyerFramework/Strict mode" - s.dependency 'AppsFlyerFramework/Strict', '6.12.2' + s.dependency 'AppsFlyerFramework/Strict', '6.13.0' s.xcconfig = {'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) AFSDK_NO_IDFA=1' } else if !defined?($RNAppsFlyerStrictMode) Pod::UI.puts "#{s.name}: Using default AppsFlyerFramework. You may require App Tracking Transparency. Not allowed for Kids apps." Pod::UI.puts "#{s.name}: You may set variable `$RNAppsFlyerStrictMode=true` in Podfile to use strict mode for kids apps." end - s.dependency 'AppsFlyerFramework', '6.12.2' + s.dependency 'AppsFlyerFramework', '6.13.0' end end diff --git a/react-native.config.js b/react-native.config.js index dfbe81b4..9fe432f3 100644 --- a/react-native.config.js +++ b/react-native.config.js @@ -3,11 +3,10 @@ const path = require('path'); module.exports = { dependency: { platforms: { - ios: { podspecPath: path.join(__dirname, 'react-native-appsflyer.podspec') }, android: { packageImportPath: 'import com.appsflyer.reactnative.RNAppsFlyerPackage;', packageInstance: 'new RNAppsFlyerPackage()', }, }, }, -}; \ No newline at end of file +};