Skip to content

Commit

Permalink
Merge pull request #309 from AppsFlyerSDK/dev/DELIVERY-58269/privacy_…
Browse files Browse the repository at this point in the history
…preserving_APIs

Dev/delivery 58269/privacy preserving apis
  • Loading branch information
al-af authored Apr 1, 2024
2 parents 2f24543 + a0c38d9 commit 23dc1d5
Show file tree
Hide file tree
Showing 16 changed files with 389 additions and 90 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Versions
## 6.13.2
- Added new APIs such as `anonymizeUser` , `performOnDeepLinking`
- Added to the `startSDK` API, `onSuccess` and `onError` callbacks
- Update to iOS SDK to v6.13.2
## 6.13.0+2
- Update to iOS SDK to v6.13.1
## 6.13.0+1
Expand Down
3 changes: 1 addition & 2 deletions android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#Thu Jul 23 11:36:59 IDT 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.appsflyer.appsflyersdk;

public class AppsFlyerConstants {
final static String PLUGIN_VERSION = "6.13.1";
final static String PLUGIN_VERSION = "6.13.2";
final static String AF_APP_INVITE_ONE_LINK = "appInviteOneLink";
final static String AF_HOST_PREFIX = "hostPrefix";
final static String AF_HOST_NAME = "hostName";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@
import com.appsflyer.share.ShareInviteHelper;
import com.appsflyer.internal.platform_extension.Plugin;
import com.appsflyer.internal.platform_extension.PluginInfo;
import com.appsflyer.attribution.AppsFlyerRequestListener;

import org.json.JSONException;
import org.json.JSONObject;

import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -80,7 +80,7 @@ public class AppsflyerSdkPlugin implements MethodCallHandler, FlutterPlugin, Act
private Boolean isFacebookDeferredApplinksEnabled = false;
private Boolean isSetDisableAdvertisingIdentifiersEnable = false;
private Map<String, Map<String, Object>> mCallbacks = new HashMap<>();

PluginRegistry.NewIntentListener onNewIntentListener = new PluginRegistry.NewIntentListener() {
@Override
public boolean onNewIntent(Intent intent) {
Expand Down Expand Up @@ -200,7 +200,7 @@ private void startListening(Object arguments, Result rawResult) {

@Override
public void onMethodCall(MethodCall call, Result result) {
if(activity == null){
if (activity == null) {
Log.d("AppsFlyer", "Activity isn't attached to the flutter engine");
return;
}
Expand All @@ -212,6 +212,9 @@ public void onMethodCall(MethodCall call, Result result) {
case "startSDK":
startSDK(call, result);
break;
case "startSDKwithHandler":
startSDKwithHandler(call, result);
break;
case "logEvent":
logEvent(call, result);
break;
Expand Down Expand Up @@ -311,6 +314,12 @@ public void onMethodCall(MethodCall call, Result result) {
case "enableFacebookDeferredApplinks":
enableFacebookDeferredApplinks(call, result);
break;
case "anonymizeUser":
anonymizeUser(call, result);
break;
case "performOnDeepLinking":
performOnDeepLinking(call, result);
break;
case "setDisableAdvertisingIdentifiers":
setDisableAdvertisingIdentifiers(call, result);
break;
Expand Down Expand Up @@ -341,9 +350,69 @@ public void onMethodCall(MethodCall call, Result result) {
}
}

private void startSDK(MethodCall call, Result result) {
AppsFlyerLib instance = AppsFlyerLib.getInstance();
private void performOnDeepLinking(MethodCall call, Result result) {
if (activity != null) {
Intent intent = activity.getIntent();
if (intent != null) {
AppsFlyerLib.getInstance().performOnDeepLinking(intent, mApplication);
result.success(null);
} else {
Log.d("AppsFlyer", "performOnDeepLinking: intent is null!");
result.error("NO_INTENT", "The intent is null", null);
}
} else {
Log.d("AppsFlyer", "performOnDeepLinking: activity is null!");
result.error("NO_ACTIVITY", "The current activity is null", null);
}
}

private void anonymizeUser(MethodCall call, Result result) {
boolean shouldAnonymize = (boolean) call.argument("shouldAnonymize");
AppsFlyerLib.getInstance().anonymizeUser(shouldAnonymize);
result.success(null); // indicate that the method invocation is complete
}

private void startSDKwithHandler(MethodCall call, final Result result) {
try {
final AppsFlyerLib instance = AppsFlyerLib.getInstance();
instance.start(activity, null, new AppsFlyerRequestListener() {
@Override
public void onSuccess() {
uiThreadHandler.post(new Runnable() {
@Override
public void run() {
mMethodChannel.invokeMethod("onSuccess", null);
}
});
}

@Override
public void onError(final int errorCode, final String errorMessage) {
uiThreadHandler.post(new Runnable() {
@Override
public void run() {
HashMap<String, Object> errorDetails = new HashMap<>();
errorDetails.put("errorCode", errorCode);
errorDetails.put("errorMessage", errorMessage);
mMethodChannel.invokeMethod("onError", errorDetails);
}
});
}
});
result.success(null);
} catch (Exception e) {
result.error("UNEXPECTED_ERROR", e.getMessage(), null);
}
}

/**
* Initiates the AppsFlyer SDK. The AtomicBoolean isResultSubmitted ensures the result is
* only submitted once, preventing the "Reply already submitted" exception in Flutter.
*/
private void startSDK(MethodCall call, final Result result) {
final AppsFlyerLib instance = AppsFlyerLib.getInstance();
instance.start(activity);
result.success(null);
}

public void setConsentData(MethodCall call, Result result) {
Expand All @@ -366,20 +435,21 @@ public void setConsentData(MethodCall call, Result result) {

result.success(null);
}

private void enableTCFDataCollection(MethodCall call, Result result) {
boolean shouldCollect = (boolean) call.argument("shouldCollect");
AppsFlyerLib.getInstance().enableTCFDataCollection(shouldCollect);
result.success(null);
}

private void addPushNotificationDeepLinkPath(MethodCall call, Result result) {
if(call.arguments != null){
if (call.arguments != null) {
ArrayList<String> depplinkPath = (ArrayList<String>) call.arguments;
String[] depplinkPathArr = depplinkPath.toArray(new String[depplinkPath.size()]);
AppsFlyerLib.getInstance().addPushNotificationDeepLinkPath(depplinkPathArr);
}
result.success(null);
}
}

private void setDisableNetworkData(MethodCall call, Result result) {
boolean disableNetworkData = (boolean) call.arguments;
Expand All @@ -392,10 +462,10 @@ private void getOutOfStore(Result result) {
}

private void setOutOfStore(MethodCall call, Result result) {
String sourceName = (String) call.arguments;
if (sourceName != null) {
AppsFlyerLib.getInstance().setOutOfStore(sourceName);
}
String sourceName = (String) call.arguments;
if (sourceName != null) {
AppsFlyerLib.getInstance().setOutOfStore(sourceName);
}
result.success(null);
}

Expand All @@ -410,14 +480,14 @@ private void setResolveDeepLinkURLs(MethodCall call, Result result) {
private void setPartnerData(MethodCall call, Result result) {
String partnerId = (String) call.argument("partnerId");
HashMap<String, Object> partnerData = (HashMap<String, Object>) call.argument("partnersData");
if(partnerData != null){
if (partnerData != null) {
AppsFlyerLib.getInstance().setPartnerData(partnerId, partnerData);
}
result.success(null);
}

private void setSharingFilterForPartners(MethodCall call, Result result) {
if(call.arguments != null){
if (call.arguments != null) {
ArrayList<String> partnersInput = (ArrayList<String>) call.arguments;
String[] partners = partnersInput.toArray(new String[partnersInput.size()]);
AppsFlyerLib.getInstance().setSharingFilterForPartners(partners);
Expand All @@ -437,7 +507,7 @@ private void setDisableAdvertisingIdentifiers(MethodCall call, Result result) {

private void enableFacebookDeferredApplinks(MethodCall call, Result result) {
isFacebookDeferredApplinksEnabled = (boolean) call.argument("isFacebookDeferredApplinksEnabled");

if (isFacebookDeferredApplinksEnabled) {
AppsFlyerLib.getInstance().enableFacebookDeferredApplinks(true);
} else {
Expand All @@ -456,7 +526,7 @@ private void sendPushNotificationData(MethodCall call, Result result) {
String errorMsg = null;
Bundle bundle;

if(pushPayload == null){
if (pushPayload == null) {
Log.d("AppsFlyer", "Push payload is null");
return;
}
Expand All @@ -481,13 +551,14 @@ private void sendPushNotificationData(MethodCall call, Result result) {
errorMsg = "The activity is null. Push payload has not been sent!";
}

if(errorMsg != null){
if (errorMsg != null) {
Log.d("AppsFlyer", errorMsg);
return;
}

result.success(null);
}

private static Bundle jsonToBundle(JSONObject jsonObject) throws JSONException {
Bundle bundle = new Bundle();
Iterator iter = jsonObject.keys();
Expand All @@ -498,6 +569,7 @@ private static Bundle jsonToBundle(JSONObject jsonObject) throws JSONException {
}
return bundle;
}

private void setOneLinkCustomDomain(MethodCall call, Result result) {
ArrayList<String> brandDomains = (ArrayList<String>) call.arguments;
String[] brandDomainsArray = brandDomains.toArray(new String[brandDomains.size()]);
Expand Down Expand Up @@ -740,11 +812,11 @@ private void setAdditionalData(MethodCall call, Result result) {
private void setUserEmails(MethodCall call, Result result) {
List<String> emails = call.argument("emails");
int cryptTypeInt = call.argument("cryptType");

AppsFlyerProperties.EmailsCryptType cryptType = null;
if (cryptTypeInt == 0){
if (cryptTypeInt == 0) {
cryptType = AppsFlyerProperties.EmailsCryptType.NONE;
} else if (cryptTypeInt == 1){
} else if (cryptTypeInt == 1) {
cryptType = AppsFlyerProperties.EmailsCryptType.SHA256;
} else {
throw new InvalidParameterException("You can use only NONE or SHA256 for EmailsCryptType on android");
Expand Down
86 changes: 85 additions & 1 deletion doc/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
- [onInstallConversionData](#onInstallConversionData)
- [onDeepLinking](#onDeepLinking)
- [logEvent](#logEvent)

- [anonymizeUser](#anonymizeUser)
- [setUserEmails](#setUserEmails)
- [setMinTimeBetweenSessions](#setMinTimeBetweenSessions)
- [stop](#stop)
Expand Down Expand Up @@ -51,6 +51,8 @@
- [setOutOfStore](#setOutOfStore)
- [getOutOfStore](#getOutOfStore)
- [setDisableNetworkData](#setDisableNetworkData)
- [performOnDeepLinking](#performondeeplinking)


---

Expand Down Expand Up @@ -201,7 +203,19 @@ Future<bool?> logEvent(String eventName, Map? eventValues) async {
---

## Other functionalities:
**<a id="anonymizeUser"> `anonymizeUser(shouldAnonymize)`**

It is possible to anonymize specific user identifiers within AppsFlyer analytics.</br>
This complies with both the latest privacy requirements (GDPR, COPPA) and Facebook's data and privacy policies. To anonymize an app user.
| parameter | type | description |
| ---------- |----------|------------------ |
| shouldAnonymize | boolean | True if want Anonymize user Data (default value is false). |

_Example:_
```dart
appsFlyerSdk.anonymizeUser(true);
```
---
**<a id="setUserEmails"> `setUserEmails(List<String> emails, [EmailCryptType cryptType])`**

Set the user emails with the given encryption (`EmailCryptTypeNone, EmailCryptTypeSHA256`). the default encryption is `EmailCryptTypeNone`.
Expand Down Expand Up @@ -739,3 +753,73 @@ _Example:_
}
```
---

**<a id="performOnDeepLinking"> `void performOnDeepLinking()`**

**Android Only!**

Enables manual triggering of deep link resolution. This method allows apps that are delaying the call to `appsflyerSdk.startSDK()` to resolve deep links before the SDK starts.<br>
Note:<br>This API will trigger the `appsflyerSdk.onDeepLink` callback. In the following example, we check if `res.deepLinkStatus` is equal to “FOUND” inside `appsflyerSdk.onDeepLink` callback to extract the deeplink parameters.

```dart
void afStart() async {
// SDK Options
final AppsFlyerOptions options = AppsFlyerOptions(
afDevKey: dotenv.env["DEV_KEY"]!,
appId: dotenv.env["APP_ID"]!,
showDebug: true,
timeToWaitForATTUserAuthorization: 15,
manualStart: true);
_appsflyerSdk = AppsflyerSdk(options);
// Init of AppsFlyer SDK
await _appsflyerSdk.initSdk(
registerConversionDataCallback: true,
registerOnAppOpenAttributionCallback: true,
registerOnDeepLinkingCallback: true);
// Conversion data callback
_appsflyerSdk.onInstallConversionData((res) {
print("onInstallConversionData res: " + res.toString());
setState(() {
_gcd = res;
});
});
// App open attribution callback
_appsflyerSdk.onAppOpenAttribution((res) {
print("onAppOpenAttribution res: " + res.toString());
setState(() {
_deepLinkData = res;
});
});
// Deep linking callback
_appsflyerSdk.onDeepLinking((DeepLinkResult dp) {
switch (dp.status) {
case Status.FOUND:
print(dp.deepLink?.toString());
print("deep link value: ${dp.deepLink?.deepLinkValue}");
break;
case Status.NOT_FOUND:
print("deep link not found");
break;
case Status.ERROR:
print("deep link error: ${dp.error}");
break;
case Status.PARSE_ERROR:
print("deep link status parsing error");
break;
}
print("onDeepLinking res: " + dp.toString());
setState(() {
_deepLinkData = dp.toJson();
});
});
if(Platform.isAndroid){
_appsflyerSdk.performOnDeepLinking();
}
_appsflyerSdk.startSDK();
}
```
Loading

0 comments on commit 23dc1d5

Please sign in to comment.