diff --git a/CHANGELOG.md b/CHANGELOG.md index 3603108f..49169af3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,24 @@ +### Version 4.21.0 (10th April 2020) +#### Added +- Added support for Huawei App Gallery install referrer. +- Added `disableThirdPartySharing` method to `Adjust` interface to allow disabling of data sharing with third parties outside of Adjust ecosystem. +- Added external device ID support. +- Added support for signature library as a plugin. +- Added more aggressive sending retry logic for install session package. +- Added additional parameters to `ad_revenue` package payload. + +#### Changed +- Updated communication flow with `iAd.framework`. + +#### Fixed +- Fixed lack of `trackAdRevenue` method definition in iOS extension. + +#### Native SDKs +- [iOS@v4.21.1][ios_sdk_v4.21.1] +- [Android@v4.21.1][android_sdk_v4.21.1] + +--- + ### Version 4.18.0 (26th November 2019) #### Added - Added 64-bit support to ANE for Android platform. @@ -419,6 +440,7 @@ [ios_sdk_v4.14.1]: https://github.com/adjust/ios_sdk/tree/v4.14.1 [ios_sdk_v4.17.1]: https://github.com/adjust/ios_sdk/tree/v4.17.1 [ios_sdk_v4.18.3]: https://github.com/adjust/ios_sdk/tree/v4.18.3 +[ios_sdk_v4.21.1]: https://github.com/adjust/ios_sdk/tree/v4.21.1 [android_sdk_v2.1.3]: https://github.com/adjust/android_sdk/tree/v2.1.3 [android_sdk_v2.1.4]: https://github.com/adjust/android_sdk/tree/v2.1.4 @@ -439,3 +461,4 @@ [android_sdk_v4.14.0]: https://github.com/adjust/android_sdk/tree/v4.14.0 [android_sdk_v4.17.0]: https://github.com/adjust/android_sdk/tree/v4.17.0 [android_sdk_v4.18.4]: https://github.com/adjust/android_sdk/tree/v4.18.4 +[android_sdk_v4.21.1]: https://github.com/adjust/android_sdk/tree/v4.21.1 diff --git a/README.md b/README.md index 0c39229d..66e18968 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ This is the Adobe AIR SDK of Adjust™. You can read more about Adjust™ at [Ad * [Install referrer](#install-referrer) * [Google Play Referrer API](#gpr-api) * [Google Play Store intent](#gps-intent) + * [Huawei Referrer API](#huawei-referrer-api) * [Proguard settings](#sdk-proguard) * [Additional features](#additional-features) * [Event tracking](#event-tracking) @@ -34,6 +35,7 @@ This is the Adobe AIR SDK of Adjust™. You can read more about Adjust™ at [Ad * [Offline mode](#offline-mode) * [Event buffering](#event-buffering) * [GDPR right to be forgotten](#gdpr-forget-me) + * [Disable third-party sharing](#disable-third-party-sharing) * [SDK signature](#sdk-signature) * [Background tracking](#background-tracking) * [Device IDs](#device-ids) @@ -230,6 +232,10 @@ The Google Play Store `INSTALL_REFERRER` intent should be captured with a broadc Also, in case you are using your custom broadcast receiver, please make a call to the Adjust broadcast receiver as described in [here][custom-broadcast-receiver]. +#### Huawei Referrer API + +As of v4.21.0, the Adjust SDK supports install tracking on Huawei devices with Huawei App Gallery version 10.4 and higher. No additional integration steps are needed to start using the Huawei Referrer API. + ### Proguard settings If you are using Proguard, add these lines to your Proguard file: @@ -677,6 +683,19 @@ Adjust.gdprForgetMe(); Upon receiving this information, Adjust will erase the user's data and the Adjust SDK will stop tracking the user. No requests from this device will be sent to Adjust in the future. +### Disable third-party sharing for specific users + +You can now notify Adjust when a user has exercised their right to stop sharing their data with partners for marketing purposes, but has allowed it to be shared for statistics purposes. + +Call the following method to instruct the Adjust SDK to communicate the user's choice to disable data sharing to the Adjust backend: + + +```actionscript +Adjust.disableThirdPartySharing(); +``` + +Upon receiving this information, Adjust will block the sharing of that specific user's data to partners and the Adjust SDK will continue to work as usual. + ### SDK signature An account manager must activate the Adjust SDK signature. Contact Adjust support (support@adjust.com) if you are interested in using this feature. diff --git a/VERSION b/VERSION index b30c4dcb..7c6be317 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.18.0 +4.21.0 diff --git a/default/src/com/adjust/sdk/Adjust.as b/default/src/com/adjust/sdk/Adjust.as index bcf249a2..41ff7707 100644 --- a/default/src/com/adjust/sdk/Adjust.as +++ b/default/src/com/adjust/sdk/Adjust.as @@ -100,6 +100,10 @@ package com.adjust.sdk { trace("Adjust: trackAdRevenue called"); } + public static function disableThirdPartySharing():void { + trace("Adjust: disableThirdPartySharing called"); + } + public static function setTestOptions(testOptions:AdjustTestOptions):void { trace("Adjust: setTestOptions called"); } diff --git a/default/src/com/adjust/sdk/AdjustConfig.as b/default/src/com/adjust/sdk/AdjustConfig.as index ee9e7670..59e6089b 100644 --- a/default/src/com/adjust/sdk/AdjustConfig.as +++ b/default/src/com/adjust/sdk/AdjustConfig.as @@ -1,6 +1,5 @@ package com.adjust.sdk { public class AdjustConfig { - // For iOS & Android private var delayStart:Number; private var appToken:String; @@ -8,6 +7,7 @@ package com.adjust.sdk { private var userAgent:String; private var environment:String; private var defaultTracker:String; + private var externalDeviceId:String; private var sendInBackground:Boolean; private var shouldLaunchDeeplink:Boolean; @@ -27,13 +27,26 @@ package com.adjust.sdk { private var info3:String; private var info4:String; - // For Android only + // Android only private var processName:String; private var readMobileEquipmentIdentity:Boolean; + // iOS only + private var allowiAdInfoReading:Boolean; + private var allowIdfaReading:Boolean; + public function AdjustConfig(appToken:String, environment:String) { this.appToken = appToken; this.environment = environment; + + // set Boolean members to their default values + this.sendInBackground = false; + this.shouldLaunchDeeplink = true; + this.eventBufferingEnabled = false; + this.isDeviceKnown = false; + this.readMobileEquipmentIdentity = false; + this.allowiAdInfoReading = true; + this.allowIdfaReading = true; } public function setLogLevel(logLevel:String):void { @@ -60,6 +73,10 @@ package com.adjust.sdk { this.defaultTracker = defaultTracker; } + public function setExternalDeviceId(externalDeviceId:String):void { + this.externalDeviceId = externalDeviceId; + } + public function setProcessName(processName:String):void { this.processName = processName; } @@ -122,6 +139,14 @@ package com.adjust.sdk { this.readMobileEquipmentIdentity = readMobileEquipmentIdentity; } + public function setAllowiAdInfoReading(allowiAdInfoReading:Boolean):void { + this.allowiAdInfoReading = allowiAdInfoReading; + } + + public function setAllowIdfaReading(allowIdfaReading:Boolean):void { + this.allowIdfaReading = allowIdfaReading; + } + // Getters public function getAppToken():String { return this.appToken; @@ -155,6 +180,10 @@ package com.adjust.sdk { return this.defaultTracker; } + public function getExternalDeviceId():String { + return this.externalDeviceId; + } + public function getProcessName():String { return this.processName; } @@ -214,5 +243,13 @@ package com.adjust.sdk { public function getReadMobileEquipmentIdentity():Boolean { return this.readMobileEquipmentIdentity; } + + public function getAllowiAdInfoReading():Boolean { + return this.allowiAdInfoReading; + } + + public function getAllowIdfaReading():Boolean { + return this.allowIdfaReading; + } } } diff --git a/default/src/com/adjust/sdk/AdjustTestOptions.as b/default/src/com/adjust/sdk/AdjustTestOptions.as index eede78c3..0f25c28c 100644 --- a/default/src/com/adjust/sdk/AdjustTestOptions.as +++ b/default/src/com/adjust/sdk/AdjustTestOptions.as @@ -5,6 +5,7 @@ package com.adjust.sdk { public var noBackoffWait:Boolean = false; public var tryInstallReferrer:Boolean = false; public var useTestConnectionOptions:Boolean = false; + public var iAdFrameworkEnabled:Boolean = false; public var baseUrl:String = null; public var gdprUrl:String = null; diff --git a/doc/migrate.md b/doc/migrate.md index 4b81faa8..0466ef5f 100644 --- a/doc/migrate.md +++ b/doc/migrate.md @@ -1,4 +1,4 @@ -## Migrate your adjust SDK for Adobe AIR to 4.18.0 from 3.4.3 +## Migrate your Adjust SDK for Adobe AIR to 4.21.0 from 3.4.3 ### SDK initialization diff --git a/example/Main-app.xml b/example/Main-app.xml index f17d2805..40e3bfdc 100644 --- a/example/Main-app.xml +++ b/example/Main-app.xml @@ -1,7 +1,7 @@ com.adjust.examples - 4.18.0 + 4.21.0 Adjust AIR SDK Demo diff --git a/example/lib/Adjust-4.18.0.ane b/example/lib/Adjust-4.18.0.ane deleted file mode 100644 index 697ce11a..00000000 Binary files a/example/lib/Adjust-4.18.0.ane and /dev/null differ diff --git a/example/lib/Adjust-4.21.0.ane b/example/lib/Adjust-4.21.0.ane new file mode 100644 index 00000000..be3b7a4a Binary files /dev/null and b/example/lib/Adjust-4.21.0.ane differ diff --git a/ext/android/sdk b/ext/android/sdk index 4566f8af..b10a8724 160000 --- a/ext/android/sdk +++ b/ext/android/sdk @@ -1 +1 @@ -Subproject commit 4566f8af9ca3d51d594cdf38c0e96ee63dbc81b6 +Subproject commit b10a872446bf151cce569f34ff80a291c3dd9fdd diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/ActivityHandler.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/ActivityHandler.java index 53577c5a..a18dd67a 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/ActivityHandler.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/ActivityHandler.java @@ -70,6 +70,7 @@ public class ActivityHandler implements IActivityHandler { private ISdkClickHandler sdkClickHandler; private SessionParameters sessionParameters; private InstallReferrer installReferrer; + private InstallReferrerHuawei installReferrerHuawei; @Override public void teardown() { @@ -458,11 +459,15 @@ public void run() { } @Override - public void sendInstallReferrer(final String installReferrer, final long referrerClickTimestampSeconds, final long installBeginTimestampSeconds) { + public void sendInstallReferrer(final String installReferrer, + final long referrerClickTimestampSeconds, + final long installBeginTimestampSeconds, + final String referrerApi) { executor.submit(new Runnable() { @Override public void run() { - sendInstallReferrerI(installReferrer, referrerClickTimestampSeconds, installBeginTimestampSeconds); + sendInstallReferrerI(installReferrer, referrerClickTimestampSeconds, + installBeginTimestampSeconds, referrerApi); } }); } @@ -608,6 +613,16 @@ public void run() { }); } + @Override + public void disableThirdPartySharing() { + executor.submit(new Runnable() { + @Override + public void run() { + disableThirdPartySharingI(); + } + }); + } + @Override public void trackAdRevenue(final String source, final JSONObject adRevenueJson) { executor.submit(new Runnable() { @@ -765,6 +780,8 @@ public void run(ActivityHandler activityHandler) { SharedPreferencesManager sharedPreferencesManager = new SharedPreferencesManager(getContext()); if (sharedPreferencesManager.getGdprForgetMe()) { gdprForgetMe(); + } else if (sharedPreferencesManager.getDisableThirdPartySharing()) { + disableThirdPartySharing(); } } @@ -821,9 +838,17 @@ public void run() { installReferrer = new InstallReferrer(adjustConfig.context, new InstallReferrerReadListener() { @Override public void onInstallReferrerRead(String installReferrer, long referrerClickTimestampSeconds, long installBeginTimestampSeconds) { - sendInstallReferrer(installReferrer, referrerClickTimestampSeconds, installBeginTimestampSeconds); + sendInstallReferrer(installReferrer, referrerClickTimestampSeconds, installBeginTimestampSeconds, Constants.REFERRER_API_GOOGLE); + } + }); + + installReferrerHuawei = new InstallReferrerHuawei(adjustConfig.context, new InstallReferrerReadListener() { + @Override + public void onInstallReferrerRead(String installReferrer, long referrerClickTimestampSeconds, long installBeginTimestampSeconds) { + sendInstallReferrer(installReferrer, referrerClickTimestampSeconds, installBeginTimestampSeconds, Constants.REFERRER_API_HUAWEI); } }); + preLaunchActionsI(adjustConfig.preLaunchActionsArray); sendReftagReferrerI(); } @@ -862,6 +887,7 @@ private void preLaunchActionsI(List preLaunchActionsArray) private void startI() { // check if it's the first sdk start if (internalState.hasFirstSdkStartNotOcurred()) { + AdjustSigner.onResume(adjustConfig.logger); startFirstSessionI(); return; } @@ -871,6 +897,8 @@ private void startI() { return; } + AdjustSigner.onResume(adjustConfig.logger); + updateHandlersStatusAndSendI(); processSessionI(); @@ -895,12 +923,17 @@ private void startFirstSessionI() { // track the first session package only if it's enabled if (internalState.isEnabled()) { - if (!sharedPreferencesManager.getGdprForgetMe()) { + if (sharedPreferencesManager.getGdprForgetMe()) { + gdprForgetMeI(); + } else { + // check if disable third party sharing request came, then send it first + if (sharedPreferencesManager.getDisableThirdPartySharing()) { + disableThirdPartySharingI(); + } + activityState.sessionCount = 1; // this is the first session transferSessionPackageI(now); checkAfterNewStartI(sharedPreferencesManager); - } else { - gdprForgetMeI(); } } @@ -911,6 +944,7 @@ private void startFirstSessionI() { writeActivityStateI(); sharedPreferencesManager.removePushToken(); sharedPreferencesManager.removeGdprForgetMe(); + sharedPreferencesManager.removeDisableThirdPartySharing(); // check for cached deep links processCachedDeeplinkI(); @@ -953,6 +987,7 @@ private void processSessionI() { // Try to check if there's new referrer information. installReferrer.startConnection(); + installReferrerHuawei.readReferrer(); return; } @@ -1297,7 +1332,7 @@ private void setEnabledI(boolean enabled) { } if (enabled) { - if (activityState.isGdprForgotten) { + if (activityState != null && activityState.isGdprForgotten) { logger.error("Re-enabling SDK not possible for forgotten user"); return; } @@ -1322,6 +1357,8 @@ private void setEnabledI(boolean enabled) { if (sharedPreferencesManager.getGdprForgetMe()) { gdprForgetMeI(); + } else if (sharedPreferencesManager.getDisableThirdPartySharing()) { + disableThirdPartySharingI(); } // check if install was tracked @@ -1362,6 +1399,7 @@ private void checkAfterNewStartI(SharedPreferencesManager sharedPreferencesManag // try to read and send the install referrer installReferrer.startConnection(); + installReferrerHuawei.readReferrer(); } private void setOfflineModeI(boolean offline) { @@ -1445,7 +1483,8 @@ private void sendReftagReferrerI() { sdkClickHandler.sendReftagReferrers(); } - private void sendInstallReferrerI(String installReferrer, long referrerClickTimestampSeconds, long installBeginTimestampSeconds) { + private void sendInstallReferrerI(String installReferrer, long referrerClickTimestampSeconds, + long installBeginTimestampSeconds, String referrerApi) { if (!isEnabledI()) { return; } @@ -1454,11 +1493,20 @@ private void sendInstallReferrerI(String installReferrer, long referrerClickTime return; } - if (referrerClickTimestampSeconds == activityState.clickTime - && installBeginTimestampSeconds == activityState.installBegin - && installReferrer.equals(activityState.installReferrer)) { - // Same click already sent before, nothing to be done. - return; + if (referrerApi.equals(Constants.REFERRER_API_GOOGLE)) { + if (referrerClickTimestampSeconds == activityState.clickTime + && installBeginTimestampSeconds == activityState.installBegin + && installReferrer.equals(activityState.installReferrer)) { + // Same click already sent before for google referrer, nothing to be done. + return; + } + } else if (referrerApi.equals(Constants.REFERRER_API_HUAWEI)) { + if (referrerClickTimestampSeconds == activityState.clickTimeHuawei + && installBeginTimestampSeconds == activityState.installBeginHuawei + && installReferrer.equals(activityState.installReferrerHuawei)) { + // Same click already sent before huawei referrer, nothing to be done. + return; + } } // Create sdk click @@ -1466,6 +1514,7 @@ private void sendInstallReferrerI(String installReferrer, long referrerClickTime installReferrer, referrerClickTimestampSeconds, installBeginTimestampSeconds, + referrerApi, activityState, adjustConfig, deviceInfo, @@ -1879,6 +1928,36 @@ private void gdprForgetMeI() { } } + private void disableThirdPartySharingI() { + // cache the disable third party sharing request, so that the request order maintains + // even this call returns before making server request + SharedPreferencesManager sharedPreferencesManager = new SharedPreferencesManager(getContext()); + sharedPreferencesManager.setDisableThirdPartySharing(); + + if (!checkActivityStateI(activityState)) { return; } + if (!isEnabledI()) { return; } + if (activityState.isGdprForgotten) { return; } + if (activityState.isThirdPartySharingDisabled) { return; } + + activityState.isThirdPartySharingDisabled = true; + writeActivityStateI(); + + long now = System.currentTimeMillis(); + PackageBuilder packageBuilder = new PackageBuilder(adjustConfig, deviceInfo, activityState, sessionParameters, now); + + ActivityPackage activityPackage = packageBuilder.buildDisableThirdPartySharingPackage(); + packageHandler.addPackage(activityPackage); + + // Removed the cached disable third party sharing flag. + sharedPreferencesManager.removeDisableThirdPartySharing(); + + if (adjustConfig.eventBufferingEnabled) { + logger.info("Buffered event %s", activityPackage.getSuffix()); + } else { + packageHandler.sendFirstPackage(); + } + } + private void trackAdRevenueI(String source, JSONObject adRevenueJson) { if (!checkActivityStateI(activityState)) { return; } if (!isEnabledI()) { return; } @@ -2087,9 +2166,17 @@ private void checkForInstallReferrerInfo(final SdkClickResponseData responseData return; } - activityState.clickTime = responseData.clickTime; - activityState.installBegin = responseData.installBegin; - activityState.installReferrer = responseData.installReferrer; + boolean isInstallReferrerHuawei = responseData.referrerApi != null && responseData.referrerApi.equalsIgnoreCase(Constants.REFERRER_API_HUAWEI); + + if (!isInstallReferrerHuawei) { + activityState.clickTime = responseData.clickTime; + activityState.installBegin = responseData.installBegin; + activityState.installReferrer = responseData.installReferrer; + } else { + activityState.clickTimeHuawei = responseData.clickTime; + activityState.installBeginHuawei = responseData.installBegin; + activityState.installReferrerHuawei = responseData.installReferrer; + } writeActivityStateI(); } diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/ActivityKind.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/ActivityKind.java index 8687307a..471e7118 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/ActivityKind.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/ActivityKind.java @@ -1,7 +1,7 @@ package com.adjust.sdk; public enum ActivityKind { - UNKNOWN, SESSION, EVENT, CLICK, ATTRIBUTION, REVENUE, REATTRIBUTION, INFO, GDPR, AD_REVENUE; + UNKNOWN, SESSION, EVENT, CLICK, ATTRIBUTION, REVENUE, REATTRIBUTION, INFO, GDPR, AD_REVENUE, DISABLE_THIRD_PARTY_SHARING; public static ActivityKind fromString(String string) { if ("session".equals(string)) { @@ -16,6 +16,8 @@ public static ActivityKind fromString(String string) { return INFO; } else if ("gdpr".equals(string)) { return GDPR; + } else if ("disable_third_party_sharing".equals(string)) { + return DISABLE_THIRD_PARTY_SHARING; } else if ("ad_revenue".equals(string)) { return AD_REVENUE; } else { @@ -38,6 +40,8 @@ public String toString() { return "info"; case GDPR: return "gdpr"; + case DISABLE_THIRD_PARTY_SHARING: + return "disable_third_party_sharing"; case AD_REVENUE: return "ad_revenue"; default: diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/ActivityState.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/ActivityState.java index b816df04..fc9a10b8 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/ActivityState.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/ActivityState.java @@ -17,7 +17,6 @@ import java.io.Serializable; import java.util.Calendar; import java.util.LinkedList; -import java.util.Locale; public class ActivityState implements Serializable, Cloneable { private static final long serialVersionUID = 9039439291143138148L; @@ -27,6 +26,7 @@ public class ActivityState implements Serializable, Cloneable { new ObjectStreamField("uuid", String.class), new ObjectStreamField("enabled", boolean.class), new ObjectStreamField("isGdprForgotten", boolean.class), + new ObjectStreamField("isThirdPartySharingDisabled", boolean.class), new ObjectStreamField("askingAttribution", boolean.class), new ObjectStreamField("eventCount", int.class), new ObjectStreamField("sessionCount", int.class), @@ -48,6 +48,7 @@ public class ActivityState implements Serializable, Cloneable { protected String uuid; protected boolean enabled; protected boolean isGdprForgotten; + protected boolean isThirdPartySharingDisabled; protected boolean askingAttribution; // global counters @@ -73,12 +74,17 @@ public class ActivityState implements Serializable, Cloneable { protected long installBegin; protected String installReferrer; + protected long clickTimeHuawei; + protected long installBeginHuawei; + protected String installReferrerHuawei; + protected ActivityState() { logger = AdjustFactory.getLogger(); // create UUID for new devices uuid = Util.createUuid(); enabled = true; isGdprForgotten = false; + isThirdPartySharingDisabled = false; askingAttribution = false; eventCount = 0; // no events yet sessionCount = 0; // the first session just started @@ -94,6 +100,9 @@ protected ActivityState() { clickTime = 0; installBegin = 0; installReferrer = null; + clickTimeHuawei = 0; + installBeginHuawei = 0; + installReferrerHuawei = null; } protected void resetSessionAttributes(long now) { @@ -140,6 +149,7 @@ public boolean equals(Object other) { if (!Util.equalString(uuid, otherActivityState.uuid)) return false; if (!Util.equalBoolean(enabled, otherActivityState.enabled)) return false; if (!Util.equalBoolean(isGdprForgotten, otherActivityState.isGdprForgotten)) return false; + if (!Util.equalBoolean(isThirdPartySharingDisabled, otherActivityState.isThirdPartySharingDisabled)) return false; if (!Util.equalBoolean(askingAttribution, otherActivityState.askingAttribution)) return false; if (!Util.equalInt(eventCount, otherActivityState.eventCount)) return false; if (!Util.equalInt(sessionCount, otherActivityState.sessionCount)) return false; @@ -154,6 +164,9 @@ public boolean equals(Object other) { if (!Util.equalLong(clickTime, otherActivityState.clickTime)) return false; if (!Util.equalLong(installBegin, otherActivityState.installBegin)) return false; if (!Util.equalString(installReferrer, otherActivityState.installReferrer)) return false; + if (!Util.equalLong(clickTimeHuawei, otherActivityState.clickTimeHuawei)) return false; + if (!Util.equalLong(installBeginHuawei, otherActivityState.installBeginHuawei)) return false; + if (!Util.equalString(installReferrerHuawei, otherActivityState.installReferrerHuawei)) return false; return true; } @@ -163,6 +176,7 @@ public int hashCode() { hashCode = 37 * hashCode + Util.hashString(uuid); hashCode = 37 * hashCode + Util.hashBoolean(enabled); hashCode = 37 * hashCode + Util.hashBoolean(isGdprForgotten); + hashCode = 37 * hashCode + Util.hashBoolean(isThirdPartySharingDisabled); hashCode = 37 * hashCode + Util.hashBoolean(askingAttribution); hashCode = 37 * hashCode + eventCount; hashCode = 37 * hashCode + sessionCount; @@ -177,6 +191,9 @@ public int hashCode() { hashCode = 37 * hashCode + Util.hashLong(clickTime); hashCode = 37 * hashCode + Util.hashLong(installBegin); hashCode = 37 * hashCode + Util.hashString(installReferrer); + hashCode = 37 * hashCode + Util.hashLong(clickTimeHuawei); + hashCode = 37 * hashCode + Util.hashLong(installBeginHuawei); + hashCode = 37 * hashCode + Util.hashString(installReferrerHuawei); return hashCode; } @@ -195,6 +212,7 @@ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFo uuid = Util.readStringField(fields, "uuid", null); enabled = Util.readBooleanField(fields, "enabled", true); isGdprForgotten = Util.readBooleanField(fields, "isGdprForgotten", false); + isThirdPartySharingDisabled = Util.readBooleanField(fields, "isThirdPartySharingDisabled", false); askingAttribution = Util.readBooleanField(fields, "askingAttribution", false); updatePackages = Util.readBooleanField(fields, "updatePackages", false); @@ -206,6 +224,10 @@ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFo installBegin = Util.readLongField(fields, "installBegin", -1l); installReferrer = Util.readStringField(fields, "installReferrer", null); + clickTimeHuawei = Util.readLongField(fields, "clickTimeHuawei", -1l); + installBeginHuawei = Util.readLongField(fields, "installBeginHuawei", -1l); + installReferrerHuawei = Util.readStringField(fields, "installReferrerHuawei", null); + // create UUID for migrating devices if (uuid == null) { uuid = Util.createUuid(); diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/Adjust.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/Adjust.java index 1a909f4b..a29dff4b 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/Adjust.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/Adjust.java @@ -32,7 +32,7 @@ private Adjust() { */ public static synchronized AdjustInstance getDefaultInstance() { @SuppressWarnings("unused") - String VERSION = "!SDK-VERSION-STRING!:com.adjust.sdk:adjust-android:4.18.4"; + String VERSION = "!SDK-VERSION-STRING!:com.adjust.sdk:adjust-android:4.21.1"; if (defaultInstance == null) { defaultInstance = new AdjustInstance(); @@ -239,6 +239,16 @@ public static void gdprForgetMe(final Context context) { adjustInstance.gdprForgetMe(context); } + /** + * Called to disable the third party sharing. + * + * @param context Application context + */ + public static void disableThirdPartySharing(final Context context) { + AdjustInstance adjustInstance = Adjust.getDefaultInstance(); + adjustInstance.disableThirdPartySharing(context); + } + /** * Track ad revenue from a source provider * diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustConfig.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustConfig.java index 306bb14a..2bf510ae 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustConfig.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustConfig.java @@ -35,6 +35,7 @@ public class AdjustConfig { boolean startOffline; String secretId; String appSecret; + String externalDeviceId; public static final String ENVIRONMENT_SANDBOX = "sandbox"; public static final String ENVIRONMENT_PRODUCTION = "production"; @@ -166,6 +167,10 @@ public void setReadMobileEquipmentIdentity(boolean readMobileEquipmentIdentity) logger.warn("This method has been deprecated and shouldn't be used anymore"); } + public void setExternalDeviceId(String externalDeviceId) { + this.externalDeviceId = externalDeviceId; + } + public boolean isValid() { if (!checkAppToken(appToken)) return false; if (!checkEnvironment(environment)) return false; diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustContext.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustContext.java index 99757172..f1392b21 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustContext.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustContext.java @@ -39,6 +39,7 @@ public class AdjustContext extends FREContext { public static String GetSdkVersion = "getSdkVersion"; public static String GdprForgetMe = "gdprForgetMe"; public static String TrackAdRevenue = "trackAdRevenue"; + public static String DisableThirdPartySharing = "disableThirdPartySharing"; // iOS methods. public static String GetIdfa = "getIdfa"; // Test methods. @@ -72,6 +73,7 @@ public Map getFunctions() { functions.put(AdjustContext.GetSdkVersion, new AdjustFunction(AdjustContext.GetSdkVersion)); functions.put(AdjustContext.GdprForgetMe, new AdjustFunction(AdjustContext.GdprForgetMe)); functions.put(AdjustContext.TrackAdRevenue, new AdjustFunction(AdjustContext.TrackAdRevenue)); + functions.put(AdjustContext.DisableThirdPartySharing, new AdjustFunction(AdjustContext.DisableThirdPartySharing)); // iOS methods. functions.put(AdjustContext.GetIdfa, new AdjustFunction(AdjustContext.GetIdfa)); // Test methods. diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustFactory.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustFactory.java index 6dbd75ec..fdfeeb3d 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustFactory.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustFactory.java @@ -32,6 +32,7 @@ public class AdjustFactory { private static long subsessionInterval = -1; private static BackoffStrategy sdkClickBackoffStrategy = null; private static BackoffStrategy packageHandlerBackoffStrategy = null; + private static BackoffStrategy installSessionBackoffStrategy = null; private static long maxDelayStart = -1; private static String baseUrl = Constants.BASE_URL; private static String gdprUrl = Constants.GDPR_URL; @@ -116,6 +117,13 @@ public static BackoffStrategy getPackageHandlerBackoffStrategy() { return packageHandlerBackoffStrategy; } + public static BackoffStrategy getInstallSessionBackoffStrategy() { + if (installSessionBackoffStrategy == null) { + return BackoffStrategy.SHORT_WAIT; + } + return installSessionBackoffStrategy; + } + public static IActivityHandler getActivityHandler(AdjustConfig config) { if (activityHandler == null) { return ActivityHandler.getInstance(config); @@ -305,6 +313,14 @@ public static void setTryInstallReferrer(boolean tryInstallReferrer) { AdjustFactory.tryInstallReferrer = tryInstallReferrer; } + public static void enableSigning() { + AdjustSigner.enableSigning(getLogger()); + } + + public static void disableSigning() { + AdjustSigner.disableSigning(getLogger()); + } + private static String byte2HexFormatted(byte[] arr) { StringBuilder str = new StringBuilder(arr.length * 2); diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustFunction.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustFunction.java index da4bf79b..c12589ed 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustFunction.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustFunction.java @@ -104,6 +104,9 @@ public FREObject call(FREContext freContext, FREObject[] freObjects) { if (functionName == AdjustContext.GdprForgetMe) { return GdprForgetMe(freContext, freObjects); } + if (functionName == AdjustContext.DisableThirdPartySharing) { + return DisableThirdPartySharing(freContext, freObjects); + } if (functionName == AdjustContext.GetIdfa) { return GetIdfa(freContext, freObjects); } @@ -322,6 +325,14 @@ private FREObject OnCreate(FREContext freContext, FREObject[] freObjects) { adjustConfig.setReadMobileEquipmentIdentity(readMobileEquipmentIdentity); } + // External device ID. + if (freObjects[24] != null) { + String externalDeviceId = freObjects[24].getAsString(); + if (externalDeviceId != null) { + adjustConfig.setExternalDeviceId(externalDeviceId); + } + } + Adjust.onCreate(adjustConfig); } catch (Exception e) { Log.e(AdjustExtension.LogTag, e.getMessage()); @@ -648,6 +659,16 @@ private FREObject GdprForgetMe(FREContext freContext, FREObject[] freObjects) { return null; } + private FREObject DisableThirdPartySharing(FREContext freContext, FREObject[] freObjects) { + try { + Adjust.disableThirdPartySharing(freContext.getActivity()); + } catch (Exception e) { + Log.e(AdjustExtension.LogTag, e.getMessage()); + } + + return null; + } + private FREObject GetIdfa(FREContext freContext, FREObject[] freObjects) { return null; } private FREObject SetTestOptions(FREContext freContext, FREObject[] freObjects) { diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustInstance.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustInstance.java index 9baf5b65..9234c7b2 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustInstance.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustInstance.java @@ -389,6 +389,20 @@ public void gdprForgetMe(final Context context) { } } + /** + * Called to disable the third party sharing. + * + * @param context Application context + */ + public void disableThirdPartySharing(final Context context) { + if (!checkActivityHandler("disable third party sharing")) { + saveDisableThirdPartySharing(context); + return; + } + + activityHandler.disableThirdPartySharing(); + } + /** * Track ad revenue from a source provider * @@ -532,6 +546,22 @@ public void run() { Util.runInBackground(command); } + /** + * Save disable third party sharing choice to shared preferences. + * + * @param context Application context + */ + private void saveDisableThirdPartySharing(final Context context) { + Runnable command = new Runnable() { + @Override + public void run() { + SharedPreferencesManager sharedPreferencesManager = new SharedPreferencesManager(context); + sharedPreferencesManager.setDisableThirdPartySharing(); + } + }; + Util.runInBackground(command); + } + /** * Flag stored referrers as still not sent. * @@ -598,5 +628,11 @@ public void setTestOptions(AdjustTestOptions testOptions) { AdjustFactory.setPackageHandlerBackoffStrategy(BackoffStrategy.NO_WAIT); AdjustFactory.setSdkClickBackoffStrategy(BackoffStrategy.NO_WAIT); } + if (testOptions.enableSigning != null && testOptions.enableSigning) { + AdjustFactory.enableSigning(); + } + if (testOptions.disableSigning != null && testOptions.disableSigning) { + AdjustFactory.disableSigning(); + } } } diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustSigner.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustSigner.java new file mode 100644 index 00000000..c60b1143 --- /dev/null +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustSigner.java @@ -0,0 +1,84 @@ +package com.adjust.sdk; + +import android.content.Context; + +import java.util.Map; + +public class AdjustSigner { + + // https://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html + private static volatile Object signerInstance = null; + + private AdjustSigner() { + } + + public static void enableSigning(ILogger logger) { + getSignerInstance(); + + if (signerInstance == null) { + return; + } + + try { + Reflection.invokeInstanceMethod(signerInstance, "enableSigning", null); + } catch (Exception e) { + logger.warn("Invoking Signer enableSigning() received an error [%s]", e.getMessage()); + } + } + + public static void disableSigning(ILogger logger) { + getSignerInstance(); + + if (signerInstance == null) { + return; + } + + try { + Reflection.invokeInstanceMethod(signerInstance, "disableSigning", null); + } catch (Exception e) { + logger.warn("Invoking Signer disableSigning() received an error [%s]", e.getMessage()); + } + } + + public static void onResume(ILogger logger){ + getSignerInstance(); + + if (signerInstance == null) { + return; + } + + try { + Reflection.invokeInstanceMethod(signerInstance, "onResume", null); + } catch (Exception e) { + logger.warn("Invoking Signer onResume() received an error [%s]", e.getMessage()); + } + } + + public static void sign(Map parameters, String activityKind, String clientSdk, + Context context, ILogger logger) { + getSignerInstance(); + + if (signerInstance == null) { + return; + } + + try { + Reflection.invokeInstanceMethod(signerInstance, "sign", + new Class[]{Context.class, Map.class, String.class, String.class}, + context, parameters, activityKind, clientSdk); + + } catch (Exception e) { + logger.warn("Invoking Signer sign() for %s received an error [%s]", activityKind, e.getMessage()); + } + } + + private static void getSignerInstance() { + if (signerInstance == null) { + synchronized (AdjustSigner.class) { + if (signerInstance == null) { + signerInstance = Reflection.createDefaultInstance("com.adjust.sdk.sig.Signer"); + } + } + } + } +} diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustTestOptions.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustTestOptions.java index e916306c..d099ef73 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustTestOptions.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/AdjustTestOptions.java @@ -20,4 +20,6 @@ public class AdjustTestOptions { public Boolean teardown; public Boolean tryInstallReferrer = false; public Boolean noBackoffWait; + public Boolean enableSigning; + public Boolean disableSigning; } diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/Constants.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/Constants.java index 3c0b5c3e..ed859198 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/Constants.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/Constants.java @@ -30,10 +30,12 @@ public interface Constants { String GDPR_URL = "https://gdpr.adjust.com"; String SCHEME = "https"; String AUTHORITY = "app.adjust.com"; - String CLIENT_SDK = "android4.18.4"; + String CLIENT_SDK = "android4.21.1"; String LOGTAG = "Adjust"; String REFTAG = "reftag"; String INSTALL_REFERRER = "install_referrer"; + String REFERRER_API_GOOGLE = "google"; + String REFERRER_API_HUAWEI = "huawei"; String DEEPLINK = "deeplink"; String PUSH = "push"; String THREAD_PREFIX = "Adjust-"; diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/GooglePlayServicesClient.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/GooglePlayServicesClient.java index 3f2989e1..7c72050f 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/GooglePlayServicesClient.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/GooglePlayServicesClient.java @@ -13,6 +13,7 @@ import java.io.IOException; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; public class GooglePlayServicesClient { public static final class GooglePlayServicesInfo { @@ -80,7 +81,7 @@ public IBinder getBinder() throws InterruptedException { throw new IllegalStateException(); } this.retrieved = true; - return (IBinder)this.queue.take(); + return (IBinder)this.queue.poll(Constants.ONE_SECOND, TimeUnit.MILLISECONDS); } } diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/IActivityHandler.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/IActivityHandler.java index e366ecb9..b2ef5dac 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/IActivityHandler.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/IActivityHandler.java @@ -37,7 +37,7 @@ public interface IActivityHandler { void sendReftagReferrer(); - void sendInstallReferrer(String installReferrer, long referrerClickTimestampSeconds, long installBeginTimestampSeconds); + void sendInstallReferrer(String installReferrer, long referrerClickTimestampSeconds, long installBeginTimestampSeconds, String referrerApi); void setOfflineMode(boolean enabled); @@ -63,6 +63,8 @@ public interface IActivityHandler { void gdprForgetMe(); + void disableThirdPartySharing(); + void trackAdRevenue(String source, JSONObject adRevenueJson); void gotOptOutResponse(); diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/InstallReferrer.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/InstallReferrer.java index 882b0c4d..e17cf9f7 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/InstallReferrer.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/InstallReferrer.java @@ -60,9 +60,12 @@ public class InstallReferrer implements InvocationHandler { private int retries; /** - * Boolean indicating whether service responded with install referrer information. + * Boolean indicating whether service should be tried to read. + * Either because it has not yet tried, + * or it did and it was successful + * or it did, was not successful, but it should not retry */ - private final AtomicBoolean hasInstallReferrerBeenRead; + private final AtomicBoolean shouldTryToRead; /** * Adjust logger instance. @@ -101,7 +104,7 @@ public InstallReferrer(final Context context, final InstallReferrerReadListener this.logger = AdjustFactory.getLogger(); this.playInstallReferrer = createInstallReferrer(context, referrerCallback, logger); this.context = context; - this.hasInstallReferrerBeenRead = new AtomicBoolean(false); + this.shouldTryToRead = new AtomicBoolean(true); this.retries = 0; this.retryTimer = new TimerOnce(new Runnable() { @Override @@ -136,8 +139,8 @@ public void startConnection() { } closeReferrerClient(); - if (hasInstallReferrerBeenRead.get()) { - logger.debug("Install referrer has already been read"); + if (!shouldTryToRead.get()) { + logger.debug("Should not try to read Install referrer"); return; } @@ -327,8 +330,6 @@ private void onInstallReferrerSetupFinishedInt(final int responseCode) { // Stuff successfully read, try to send it. referrerCallback.onInstallReferrerRead(installReferrer, clickTime, installBegin); - - hasInstallReferrerBeenRead.set(true); } catch (Exception e) { logger.warn("Couldn't get install referrer from client (%s). Retrying...", e.getMessage()); retryAtEnd = true; @@ -370,6 +371,7 @@ private void onInstallReferrerSetupFinishedInt(final int responseCode) { if (retryAtEnd) { retry(); } else { + shouldTryToRead.set(false); closeReferrerClient(); } } @@ -464,8 +466,8 @@ private long getInstallBeginTimestampSeconds(final Object referrerDetails) { * Retry connection to install referrer service. */ private void retry() { - if (hasInstallReferrerBeenRead.get()) { - logger.debug("Install referrer has already been read"); + if (!shouldTryToRead.get()) { + logger.debug("Should not try to read Install referrer"); closeReferrerClient(); return; } diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/InstallReferrerHuawei.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/InstallReferrerHuawei.java new file mode 100644 index 00000000..8cb9cf85 --- /dev/null +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/InstallReferrerHuawei.java @@ -0,0 +1,95 @@ +package com.adjust.sdk; + +import android.content.ContentResolver; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +public class InstallReferrerHuawei { + + /** + * Huawei install referrer provider content uri. + */ + private static final String REFERRER_PROVIDER_URI = "content://com.huawei.appmarket.commondata/item/5"; + + /** + * Adjust logger instance. + */ + private ILogger logger; + + /** + * Application context. + */ + private Context context; + + /** + * Weak reference to ActivityHandler instance. + */ + private final InstallReferrerReadListener referrerCallback; + + /** + * Boolean indicating whether service should be tried to read. + * Either because it has not yet tried, + * or it did and it was successful + * or it did, was not successful, but it should not retry + */ + private final AtomicBoolean shouldTryToRead; + + /** + * Default constructor. + * + * @param context Application context + * @param referrerCallback Callback for referrer information + */ + public InstallReferrerHuawei(final Context context, final InstallReferrerReadListener referrerCallback) { + this.logger = AdjustFactory.getLogger(); + this.context = context; + this.referrerCallback = referrerCallback; + this.shouldTryToRead = new AtomicBoolean(true); + } + + public void readReferrer() { + if (!shouldTryToRead.get()) { + logger.debug("Should not try to read Install referrer Huawei"); + return; + } + + Cursor cursor = null; + Uri uri = Uri.parse(REFERRER_PROVIDER_URI); + ContentResolver contentResolver = context.getContentResolver(); + + String packageName[] = new String[] { context.getPackageName() }; + try { + cursor = contentResolver.query(uri, null, null, packageName, null); + + if (cursor != null && cursor.moveToFirst()) { + + String installReferrer = cursor.getString(0); + String clickTime = cursor.getString(1); + String installTime = cursor.getString(2); + + logger.debug("InstallReferrerHuawei reads referrer[%s] clickTime[%s] installTime[%s]", installReferrer, clickTime, installTime ); + + long referrerClickTimestampSeconds = Long.parseLong(clickTime); + long installBeginTimestampSeconds = Long.parseLong(installTime); + + referrerCallback.onInstallReferrerRead(installReferrer, referrerClickTimestampSeconds, installBeginTimestampSeconds); + + } else { + logger.debug("InstallReferrerHuawei fail to read referrer for package [%s] and content uri [%s]", context.getPackageName(), uri.toString()); + } + } catch (Exception e) { + logger.debug("InstallReferrerHuawei error [%s]", e.getMessage()); + } finally { + if (cursor != null) { + cursor.close(); + } + } + + shouldTryToRead.set(false); + } + +} diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/PackageBuilder.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/PackageBuilder.java index 4ef1b5a1..885064a9 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/PackageBuilder.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/PackageBuilder.java @@ -32,6 +32,7 @@ public class PackageBuilder { String deeplink; String referrer; String rawReferrer; + String referrerApi; AdjustAttribution attribution; Map extraParameters; @@ -77,6 +78,10 @@ ActivityPackage buildSessionPackage(boolean isInDelay) { ActivityPackage sessionPackage = getDefaultActivityPackage(ActivityKind.SESSION); sessionPackage.setPath("/session"); sessionPackage.setSuffix(""); + + AdjustSigner.sign(parameters, ActivityKind.SESSION.toString(), + sessionPackage.getClientSdk(), adjustConfig.context, adjustConfig.logger); + sessionPackage.setParameters(parameters); return sessionPackage; } @@ -86,6 +91,10 @@ ActivityPackage buildEventPackage(AdjustEvent event, boolean isInDelay) { ActivityPackage eventPackage = getDefaultActivityPackage(ActivityKind.EVENT); eventPackage.setPath("/event"); eventPackage.setSuffix(getEventSuffix(event)); + + AdjustSigner.sign(parameters, ActivityKind.EVENT.toString(), + eventPackage.getClientSdk(), adjustConfig.context, adjustConfig.logger); + eventPackage.setParameters(parameters); if (isInDelay) { @@ -98,11 +107,15 @@ ActivityPackage buildEventPackage(AdjustEvent event, boolean isInDelay) { ActivityPackage buildInfoPackage(String source) { Map parameters = getInfoParameters(source); - ActivityPackage clickPackage = getDefaultActivityPackage(ActivityKind.INFO); - clickPackage.setPath("/sdk_info"); - clickPackage.setSuffix(""); - clickPackage.setParameters(parameters); - return clickPackage; + ActivityPackage infoPackage = getDefaultActivityPackage(ActivityKind.INFO); + infoPackage.setPath("/sdk_info"); + infoPackage.setSuffix(""); + + AdjustSigner.sign(parameters, ActivityKind.INFO.toString(), + infoPackage.getClientSdk(), adjustConfig.context, adjustConfig.logger); + + infoPackage.setParameters(parameters); + return infoPackage; } ActivityPackage buildClickPackage(String source) { @@ -113,6 +126,10 @@ ActivityPackage buildClickPackage(String source) { clickPackage.setClickTimeInMilliseconds(clickTimeInMilliseconds); clickPackage.setClickTimeInSeconds(clickTimeInSeconds); clickPackage.setInstallBeginTimeInSeconds(installBeginTimeInSeconds); + + AdjustSigner.sign(parameters, ActivityKind.CLICK.toString(), + clickPackage.getClientSdk(), adjustConfig.context, adjustConfig.logger); + clickPackage.setParameters(parameters); return clickPackage; } @@ -122,6 +139,10 @@ ActivityPackage buildAttributionPackage(String initiatedByDescription) { ActivityPackage attributionPackage = getDefaultActivityPackage(ActivityKind.ATTRIBUTION); attributionPackage.setPath("attribution"); // does not contain '/' because of Uri.Builder.appendPath attributionPackage.setSuffix(""); + + AdjustSigner.sign(parameters, ActivityKind.ATTRIBUTION.toString(), + attributionPackage.getClientSdk(), adjustConfig.context, adjustConfig.logger); + attributionPackage.setParameters(parameters); return attributionPackage; } @@ -131,15 +152,36 @@ ActivityPackage buildGdprPackage() { ActivityPackage gdprPackage = getDefaultActivityPackage(ActivityKind.GDPR); gdprPackage.setPath("/gdpr_forget_device"); gdprPackage.setSuffix(""); + + AdjustSigner.sign(parameters, ActivityKind.GDPR.toString(), + gdprPackage.getClientSdk(), adjustConfig.context, adjustConfig.logger); + gdprPackage.setParameters(parameters); return gdprPackage; } + ActivityPackage buildDisableThirdPartySharingPackage() { + Map parameters = getDisableThirdPartySharingParameters(); + ActivityPackage activityPackage = getDefaultActivityPackage(ActivityKind.DISABLE_THIRD_PARTY_SHARING); + activityPackage.setPath("/disable_third_party_sharing"); + activityPackage.setSuffix(""); + + AdjustSigner.sign(parameters, ActivityKind.DISABLE_THIRD_PARTY_SHARING.toString(), + activityPackage.getClientSdk(), adjustConfig.context, adjustConfig.logger); + + activityPackage.setParameters(parameters); + return activityPackage; + } + ActivityPackage buildAdRevenuePackage(String source, JSONObject adRevenueJson) { Map parameters = getAdRevenueParameters(source, adRevenueJson); ActivityPackage adRevenuePackage = getDefaultActivityPackage(ActivityKind.AD_REVENUE); adRevenuePackage.setPath("/ad_revenue"); adRevenuePackage.setSuffix(""); + + AdjustSigner.sign(parameters, ActivityKind.AD_REVENUE.toString(), + adRevenuePackage.getClientSdk(), adjustConfig.context, adjustConfig.logger); + adRevenuePackage.setParameters(parameters); return adRevenuePackage; @@ -201,6 +243,7 @@ private Map getSessionParameters(boolean isInDelay) { PackageBuilder.addString(parameters, "display_width", deviceInfo.displayWidth); PackageBuilder.addString(parameters, "environment", adjustConfig.environment); PackageBuilder.addBoolean(parameters, "event_buffering_enabled", adjustConfig.eventBufferingEnabled); + PackageBuilder.addString(parameters, "external_device_id", adjustConfig.externalDeviceId); PackageBuilder.addString(parameters, "fb_id", deviceInfo.fbAttributionId); PackageBuilder.addString(parameters, "fire_adid", Util.getFireAdvertisingId(contentResolver)); PackageBuilder.addBoolean(parameters, "fire_tracking_enabled", Util.getFireTrackingEnabled(contentResolver)); @@ -290,6 +333,7 @@ public Map getEventParameters(AdjustEvent event, boolean isInDel PackageBuilder.addLong(parameters, "event_count", activityStateCopy.eventCount); PackageBuilder.addBoolean(parameters, "event_buffering_enabled", adjustConfig.eventBufferingEnabled); PackageBuilder.addString(parameters, "event_token", event.eventToken); + PackageBuilder.addString(parameters, "external_device_id", adjustConfig.externalDeviceId); PackageBuilder.addString(parameters, "fb_id", deviceInfo.fbAttributionId); PackageBuilder.addString(parameters, "fire_adid", Util.getFireAdvertisingId(contentResolver)); PackageBuilder.addBoolean(parameters, "fire_tracking_enabled", Util.getFireTrackingEnabled(contentResolver)); @@ -357,6 +401,7 @@ private Map getInfoParameters(String source) { PackageBuilder.addBoolean(parameters, "device_known", adjustConfig.deviceKnown); PackageBuilder.addString(parameters, "environment", adjustConfig.environment); PackageBuilder.addBoolean(parameters, "event_buffering_enabled", adjustConfig.eventBufferingEnabled); + PackageBuilder.addString(parameters, "external_device_id", adjustConfig.externalDeviceId); PackageBuilder.addString(parameters, "fire_adid", Util.getFireAdvertisingId(contentResolver)); PackageBuilder.addBoolean(parameters, "fire_tracking_enabled", Util.getFireTrackingEnabled(contentResolver)); PackageBuilder.addBoolean(parameters, "needs_response_details", true); @@ -429,6 +474,7 @@ private Map getClickParameters(String source) { PackageBuilder.addString(parameters, "display_width", deviceInfo.displayWidth); PackageBuilder.addString(parameters, "environment", adjustConfig.environment); PackageBuilder.addBoolean(parameters, "event_buffering_enabled", adjustConfig.eventBufferingEnabled); + PackageBuilder.addString(parameters, "external_device_id", adjustConfig.externalDeviceId); PackageBuilder.addString(parameters, "fb_id", deviceInfo.fbAttributionId); PackageBuilder.addString(parameters, "fire_adid", Util.getFireAdvertisingId(contentResolver)); PackageBuilder.addBoolean(parameters, "fire_tracking_enabled", Util.getFireTrackingEnabled(contentResolver)); @@ -450,6 +496,7 @@ private Map getClickParameters(String source) { PackageBuilder.addString(parameters, "push_token", activityStateCopy.pushToken); PackageBuilder.addString(parameters, "raw_referrer", rawReferrer); PackageBuilder.addString(parameters, "referrer", referrer); + PackageBuilder.addString(parameters, "referrer_api", referrerApi); PackageBuilder.addString(parameters, "reftag", reftag); PackageBuilder.addString(parameters, "screen_density", deviceInfo.screenDensity); PackageBuilder.addString(parameters, "screen_format", deviceInfo.screenFormat); @@ -509,6 +556,7 @@ private Map getAttributionParameters(String initiatedBy) { PackageBuilder.addString(parameters, "device_type", deviceInfo.deviceType); PackageBuilder.addString(parameters, "environment", adjustConfig.environment); PackageBuilder.addBoolean(parameters, "event_buffering_enabled", adjustConfig.eventBufferingEnabled); + PackageBuilder.addString(parameters, "external_device_id", adjustConfig.externalDeviceId); PackageBuilder.addString(parameters, "fire_adid", Util.getFireAdvertisingId(contentResolver)); PackageBuilder.addBoolean(parameters, "fire_tracking_enabled", Util.getFireTrackingEnabled(contentResolver)); PackageBuilder.addString(parameters, "initiated_by", initiatedBy); @@ -566,6 +614,64 @@ private Map getGdprParameters() { PackageBuilder.addString(parameters, "device_type", deviceInfo.deviceType); PackageBuilder.addString(parameters, "environment", adjustConfig.environment); PackageBuilder.addBoolean(parameters, "event_buffering_enabled", adjustConfig.eventBufferingEnabled); + PackageBuilder.addString(parameters, "external_device_id", adjustConfig.externalDeviceId); + PackageBuilder.addString(parameters, "fire_adid", Util.getFireAdvertisingId(contentResolver)); + PackageBuilder.addBoolean(parameters, "fire_tracking_enabled", Util.getFireTrackingEnabled(contentResolver)); + PackageBuilder.addBoolean(parameters, "needs_response_details", true); + PackageBuilder.addString(parameters, "os_name", deviceInfo.osName); + PackageBuilder.addString(parameters, "os_version", deviceInfo.osVersion); + PackageBuilder.addString(parameters, "package_name", deviceInfo.packageName); + PackageBuilder.addString(parameters, "push_token", activityStateCopy.pushToken); + PackageBuilder.addString(parameters, "secret_id", adjustConfig.secretId); + + checkDeviceIds(parameters); + return parameters; + } + + private Map getDisableThirdPartySharingParameters() { + ContentResolver contentResolver = adjustConfig.context.getContentResolver(); + Map parameters = new HashMap(); + Map imeiParameters = Reflection.getImeiParameters(adjustConfig.context, logger); + + // Check if plugin is used and if yes, add read parameters. + if (imeiParameters != null) { + parameters.putAll(imeiParameters); + } + + // Check if oaid plugin is used and if yes, add the parameter + Map oaidParameters = Reflection.getOaidParameters(adjustConfig.context, logger); + if (oaidParameters != null) { + parameters.putAll(oaidParameters); + } + + // Device identifiers. + deviceInfo.reloadPlayIds(adjustConfig.context); + PackageBuilder.addString(parameters, "android_uuid", activityStateCopy.uuid); + PackageBuilder.addBoolean(parameters, "tracking_enabled", deviceInfo.isTrackingEnabled); + PackageBuilder.addString(parameters, "gps_adid", deviceInfo.playAdId); + PackageBuilder.addString(parameters, "gps_adid_src", deviceInfo.playAdIdSource); + + if (!containsPlayIds(parameters)) { + logger.warn("Google Advertising ID not detected, fallback to non Google Play identifiers will take place"); + deviceInfo.reloadNonPlayIds(adjustConfig.context); + PackageBuilder.addString(parameters, "mac_sha1", deviceInfo.macSha1); + PackageBuilder.addString(parameters, "mac_md5", deviceInfo.macShortMd5); + PackageBuilder.addString(parameters, "android_id", deviceInfo.androidId); + } + + // Rest of the parameters. + PackageBuilder.addString(parameters, "api_level", deviceInfo.apiLevel); + PackageBuilder.addString(parameters, "app_secret", adjustConfig.appSecret); + PackageBuilder.addString(parameters, "app_token", adjustConfig.appToken); + PackageBuilder.addString(parameters, "app_version", deviceInfo.appVersion); + PackageBuilder.addBoolean(parameters, "attribution_deeplink", true); + PackageBuilder.addDateInMilliseconds(parameters, "created_at", createdAt); + PackageBuilder.addBoolean(parameters, "device_known", adjustConfig.deviceKnown); + PackageBuilder.addString(parameters, "device_name", deviceInfo.deviceName); + PackageBuilder.addString(parameters, "device_type", deviceInfo.deviceType); + PackageBuilder.addString(parameters, "environment", adjustConfig.environment); + PackageBuilder.addBoolean(parameters, "event_buffering_enabled", adjustConfig.eventBufferingEnabled); + PackageBuilder.addString(parameters, "external_device_id", adjustConfig.externalDeviceId); PackageBuilder.addString(parameters, "fire_adid", Util.getFireAdvertisingId(contentResolver)); PackageBuilder.addBoolean(parameters, "fire_tracking_enabled", Util.getFireTrackingEnabled(contentResolver)); PackageBuilder.addBoolean(parameters, "needs_response_details", true); @@ -611,20 +717,54 @@ private Map getAdRevenueParameters(String source, JSONObject adR } // Rest of the parameters. + PackageBuilder.addString(parameters, "api_level", deviceInfo.apiLevel); PackageBuilder.addString(parameters, "app_secret", adjustConfig.appSecret); PackageBuilder.addString(parameters, "app_token", adjustConfig.appToken); + PackageBuilder.addString(parameters, "app_version", deviceInfo.appVersion); PackageBuilder.addBoolean(parameters, "attribution_deeplink", true); + PackageBuilder.addLong(parameters, "connectivity_type", Util.getConnectivityType(adjustConfig.context)); + PackageBuilder.addString(parameters, "country", deviceInfo.country); + PackageBuilder.addString(parameters, "cpu_type", deviceInfo.abi); PackageBuilder.addDateInMilliseconds(parameters, "created_at", createdAt); + PackageBuilder.addString(parameters, "default_tracker", adjustConfig.defaultTracker); PackageBuilder.addBoolean(parameters, "device_known", adjustConfig.deviceKnown); + PackageBuilder.addString(parameters, "device_manufacturer", deviceInfo.deviceManufacturer); + PackageBuilder.addString(parameters, "device_name", deviceInfo.deviceName); + PackageBuilder.addString(parameters, "device_type", deviceInfo.deviceType); + PackageBuilder.addString(parameters, "display_height", deviceInfo.displayHeight); + PackageBuilder.addString(parameters, "display_width", deviceInfo.displayWidth); PackageBuilder.addString(parameters, "environment", adjustConfig.environment); PackageBuilder.addBoolean(parameters, "event_buffering_enabled", adjustConfig.eventBufferingEnabled); + PackageBuilder.addString(parameters, "external_device_id", adjustConfig.externalDeviceId); + PackageBuilder.addString(parameters, "fb_id", deviceInfo.fbAttributionId); PackageBuilder.addString(parameters, "fire_adid", Util.getFireAdvertisingId(contentResolver)); PackageBuilder.addBoolean(parameters, "fire_tracking_enabled", Util.getFireTrackingEnabled(contentResolver)); + PackageBuilder.addString(parameters, "hardware_name", deviceInfo.hardwareName); + PackageBuilder.addString(parameters, "installed_at", deviceInfo.appInstallTime); + PackageBuilder.addString(parameters, "language", deviceInfo.language); + PackageBuilder.addDuration(parameters, "last_interval", activityStateCopy.lastInterval); + PackageBuilder.addString(parameters, "mcc", Util.getMcc(adjustConfig.context)); + PackageBuilder.addString(parameters, "mnc", Util.getMnc(adjustConfig.context)); PackageBuilder.addBoolean(parameters, "needs_response_details", true); + PackageBuilder.addLong(parameters, "network_type", Util.getNetworkType(adjustConfig.context)); + PackageBuilder.addString(parameters, "os_build", deviceInfo.buildName); + PackageBuilder.addString(parameters, "os_name", deviceInfo.osName); + PackageBuilder.addString(parameters, "os_version", deviceInfo.osVersion); + PackageBuilder.addString(parameters, "package_name", deviceInfo.packageName); PackageBuilder.addString(parameters, "push_token", activityStateCopy.pushToken); + PackageBuilder.addString(parameters, "screen_density", deviceInfo.screenDensity); + PackageBuilder.addString(parameters, "screen_format", deviceInfo.screenFormat); + PackageBuilder.addString(parameters, "screen_size", deviceInfo.screenSize); PackageBuilder.addString(parameters, "secret_id", adjustConfig.secretId); PackageBuilder.addString(parameters, "source", source); PackageBuilder.addJsonObject(parameters, "payload", adRevenueJson); + PackageBuilder.addLong(parameters, "session_count", activityStateCopy.sessionCount); + PackageBuilder.addDuration(parameters, "session_length", activityStateCopy.sessionLength); + PackageBuilder.addLong(parameters, "subsession_count", activityStateCopy.subsessionCount); + PackageBuilder.addDuration(parameters, "time_spent", activityStateCopy.timeSpent); + PackageBuilder.addString(parameters, "updated_at", deviceInfo.appUpdateTime); + + checkDeviceIds(parameters); return parameters; diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/PackageFactory.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/PackageFactory.java index 6f0f4c07..585009fe 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/PackageFactory.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/PackageFactory.java @@ -116,6 +116,7 @@ public static ActivityPackage buildDeeplinkSdkClickPackage(final Uri url, public static ActivityPackage buildInstallReferrerSdkClickPackage(final String installReferrer, final long clickTimeInSeconds, final long installBeginInSeconds, + final String referrerApi, final ActivityState activityState, final AdjustConfig adjustConfig, final DeviceInfo deviceInfo, @@ -140,6 +141,7 @@ public static ActivityPackage buildInstallReferrerSdkClickPackage(final String i clickPackageBuilder.referrer = installReferrer; clickPackageBuilder.clickTimeInSeconds = clickTimeInSeconds; clickPackageBuilder.installBeginTimeInSeconds = installBeginInSeconds; + clickPackageBuilder.referrerApi = referrerApi; ActivityPackage clickPackage = clickPackageBuilder.buildClickPackage(Constants.INSTALL_REFERRER); diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/PackageHandler.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/PackageHandler.java index a90406bb..66e36d9a 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/PackageHandler.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/PackageHandler.java @@ -37,6 +37,7 @@ public class PackageHandler implements IPackageHandler { private Context context; private ILogger logger; private BackoffStrategy backoffStrategy; + private BackoffStrategy backoffStrategyForInstallSession; private String basePath; private String gdprPath; @@ -75,6 +76,7 @@ public PackageHandler(IActivityHandler activityHandler, this.scheduler = new SingleThreadCachedScheduler("PackageHandler"); this.logger = AdjustFactory.getLogger(); this.backoffStrategy = AdjustFactory.getPackageHandlerBackoffStrategy(); + this.backoffStrategyForInstallSession = AdjustFactory.getInstallSessionBackoffStrategy(); init(activityHandler, context, startsSending); @@ -161,8 +163,15 @@ public void run() { } int retries = activityPackage.increaseRetries(); + long waitTimeMilliSeconds; - long waitTimeMilliSeconds = Util.getWaitingTime(retries, backoffStrategy); + SharedPreferencesManager sharedPreferencesManager = new SharedPreferencesManager(context); + + if (activityPackage.getActivityKind() == ActivityKind.SESSION && !sharedPreferencesManager.getInstallTracked()) { + waitTimeMilliSeconds = Util.getWaitingTime(retries, backoffStrategyForInstallSession); + } else { + waitTimeMilliSeconds = Util.getWaitingTime(retries, backoffStrategy); + } double waitTimeSeconds = waitTimeMilliSeconds / 1000.0; String secondsString = Util.SecondsDisplayFormat.format(waitTimeSeconds); diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/Reflection.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/Reflection.java index 5505d62b..d2af4513 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/Reflection.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/Reflection.java @@ -75,6 +75,10 @@ public static Class forName(String className) { public static Object createDefaultInstance(String className) { Class classObject = forName(className); + if (classObject == null) { + return null; + } + Object instance = createDefaultInstance(classObject); return instance; } diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/RequestHandler.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/RequestHandler.java index 35463699..ea041ac3 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/RequestHandler.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/RequestHandler.java @@ -70,16 +70,16 @@ public void teardown() { private void sendI(ActivityPackage activityPackage, int queueSize) { String url; - if (activityPackage.getActivityKind() != ActivityKind.GDPR) { - url = AdjustFactory.getBaseUrl(); - if (basePath != null) { - url += basePath; - } - } else { + if (activityPackage.getActivityKind() == ActivityKind.GDPR) { url = AdjustFactory.getGdprUrl(); if (gdprPath != null) { url += gdprPath; } + } else { + url = AdjustFactory.getBaseUrl(); + if (basePath != null) { + url += basePath; + } } String targetURL = url + activityPackage.getPath(); diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/SdkClickHandler.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/SdkClickHandler.java index 9b86a03b..654c7e97 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/SdkClickHandler.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/SdkClickHandler.java @@ -300,6 +300,7 @@ private void sendSdkClickI(final ActivityPackage sdkClickPackage) { long clickTime = -1; long installBegin = -1; String installReferrer = null; + String referrerApi = null; if (isInstallReferrer) { // Check if install referrer information is saved to activity state. @@ -308,6 +309,7 @@ private void sendSdkClickI(final ActivityPackage sdkClickPackage) { clickTime = sdkClickPackage.getClickTimeInSeconds(); installBegin = sdkClickPackage.getInstallBeginTimeInSeconds(); installReferrer = sdkClickPackage.getParameters().get("referrer"); + referrerApi = sdkClickPackage.getParameters().get("referrer_api"); } String url = AdjustFactory.getBaseUrl(); @@ -353,6 +355,7 @@ private void sendSdkClickI(final ActivityPackage sdkClickPackage) { responseData.clickTime = clickTime; responseData.installBegin = installBegin; responseData.installReferrer = installReferrer; + responseData.referrerApi = referrerApi; responseData.isInstallReferrer = true; } diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/SdkClickResponseData.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/SdkClickResponseData.java index 4759c207..3562f63f 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/SdkClickResponseData.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/SdkClickResponseData.java @@ -9,4 +9,5 @@ public class SdkClickResponseData extends ResponseData { long clickTime; long installBegin; String installReferrer; + String referrerApi; } diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/SharedPreferencesManager.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/SharedPreferencesManager.java index 1b20c50a..8fcb330a 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/SharedPreferencesManager.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/SharedPreferencesManager.java @@ -37,6 +37,8 @@ public class SharedPreferencesManager { private static final String PREFS_KEY_GDPR_FORGET_ME = "gdpr_forget_me"; + private static final String PREFS_KEY_DISABLE_THIRD_PARTY_SHARING = "disable_third_party_sharing"; + private static final String PREFS_KEY_DEEPLINK_URL = "deeplink_url"; private static final String PREFS_KEY_DEEPLINK_CLICK_TIME = "deeplink_click_time"; @@ -314,6 +316,18 @@ public synchronized void removeGdprForgetMe() { remove(PREFS_KEY_GDPR_FORGET_ME); } + public synchronized void setDisableThirdPartySharing() { + saveBoolean(PREFS_KEY_DISABLE_THIRD_PARTY_SHARING, true); + } + + public synchronized boolean getDisableThirdPartySharing() { + return getBoolean(PREFS_KEY_DISABLE_THIRD_PARTY_SHARING, false); + } + + public synchronized void removeDisableThirdPartySharing() { + remove(PREFS_KEY_DISABLE_THIRD_PARTY_SHARING); + } + public synchronized void saveDeeplink(final Uri deeplink, final long clickTime) { if (deeplink == null) { return; @@ -373,6 +387,16 @@ private synchronized void saveLong(final String key, final long value) { this.sharedPreferences.edit().putLong(key, value).apply(); } + /** + * Write a integer value to shared preferences. + * + * @param key Key to be written to shared preferences + * @param value Value to be written to shared preferences + */ + private synchronized void saveInteger(final String key, final int value) { + this.sharedPreferences.edit().putInt(key, value).apply(); + } + /** * Get a string value from shared preferences. * diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/Util.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/Util.java index 6b5108a3..31ce6c41 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/Util.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/Util.java @@ -26,6 +26,9 @@ import android.telephony.TelephonyManager; import android.text.TextUtils; +import com.adjust.sdk.scheduler.SingleThreadFutureScheduler; +import com.adjust.sdk.scheduler.TimerOnce; + import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.Closeable; @@ -37,19 +40,21 @@ import java.io.ObjectOutputStream; import java.io.PrintWriter; import java.io.StringWriter; -import java.lang.reflect.InvocationTargetException; import java.math.BigInteger; import java.security.MessageDigest; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Random; import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -67,6 +72,9 @@ public class Util { public static final DecimalFormat SecondsDisplayFormat = newLocalDecimalFormat(); public static final SimpleDateFormat dateFormatter = new SimpleDateFormat(DATE_FORMAT, Locale.US); + // https://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html + private static volatile SingleThreadFutureScheduler playAdIdScheduler = null; + private static ILogger getLogger() { return AdjustFactory.getLogger(); } @@ -94,8 +102,29 @@ public static String quote(String string) { return Util.formatString("'%s'", string); } - public static String getPlayAdId(Context context) { - return Reflection.getPlayAdId(context); + public static String getPlayAdId(final Context context) { + if (playAdIdScheduler == null) { + synchronized (Util.class) { + if (playAdIdScheduler == null) { + playAdIdScheduler = new SingleThreadFutureScheduler("PlayAdIdLibrary", true); + } + } + } + ScheduledFuture playAdIdFuture = playAdIdScheduler.scheduleFutureWithReturn(new Callable() { + @Override + public String call() throws Exception { + return Reflection.getPlayAdId(context); + } + }, 0); + + try { + return playAdIdFuture.get(Constants.ONE_SECOND, TimeUnit.MILLISECONDS); + } catch (ExecutionException e) { + } catch (InterruptedException e) { + } catch (TimeoutException e) { + } + + return null; } public static void runInBackground(Runnable command) { diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/UtilNetworking.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/UtilNetworking.java index 84f5a05b..749d2112 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/UtilNetworking.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/UtilNetworking.java @@ -44,11 +44,10 @@ public static ResponseData createPOSTHttpsURLConnection(String urlString, Activi IConnectionOptions connectionOptions = AdjustFactory.getConnectionOptions(); connectionOptions.applyConnectionOptions(connection, activityPackage.getClientSdk()); - String appSecret = extractAppSecret(parameters); - String secretId = extractSecretId(parameters); extractEventCallbackId(parameters); - String authorizationHeader = buildAuthorizationHeader(parameters, appSecret, secretId, activityPackage.getActivityKind().toString()); + String authorizationHeader = buildAuthorizationHeader(parameters, + activityPackage.getActivityKind().toString()); if (authorizationHeader != null) { connection.setRequestProperty("Authorization", authorizationHeader); } @@ -80,8 +79,6 @@ public static ResponseData createGETHttpsURLConnection(ActivityPackage activityP try { Map parameters = new HashMap(activityPackage.getParameters()); - String appSecret = extractAppSecret(parameters); - String secretId = extractSecretId(parameters); extractEventCallbackId(parameters); Uri uri = buildUri(activityPackage.getPath(), parameters, basePath); @@ -91,7 +88,7 @@ public static ResponseData createGETHttpsURLConnection(ActivityPackage activityP IConnectionOptions connectionOptions = AdjustFactory.getConnectionOptions(); connectionOptions.applyConnectionOptions(connection, activityPackage.getClientSdk()); - String authorizationHeader = buildAuthorizationHeader(parameters, appSecret, secretId, activityPackage.getActivityKind().toString()); + String authorizationHeader = buildAuthorizationHeader(parameters, activityPackage.getActivityKind().toString()); if (authorizationHeader != null) { connection.setRequestProperty("Authorization", authorizationHeader); } @@ -175,8 +172,10 @@ private static ResponseData readHttpResponse(HttpsURLConnection connection, Acti responseData.timestamp = jsonResponse.optString("timestamp", null); responseData.adid = jsonResponse.optString("adid", null); String trackingState = jsonResponse.optString("tracking_state", null); - if (trackingState != null && trackingState.equals("opted_out")) { - responseData.trackingState = TrackingState.OPTED_OUT; + if (trackingState != null) { + if (trackingState.equals("opted_out")) { + responseData.trackingState = TrackingState.OPTED_OUT; + } } if (message == null) { @@ -265,22 +264,56 @@ private static Uri buildUri(String path, Map parameters, String return uriBuilder.build(); } - private static String extractAppSecret(Map parameters) { + private static String extractAppSecret(final Map parameters) { return parameters.remove("app_secret"); } - private static String extractSecretId(Map parameters) { + private static String extractSecretId(final Map parameters) { return parameters.remove("secret_id"); } - private static void extractEventCallbackId(Map parameters) { + private static String extractSignature(final Map parameters) { + return parameters.remove("signature"); + } + + private static String extractAlgorithm(final Map parameters) { + return parameters.remove("algorithm"); + } + + private static String extractNativeVersion(final Map parameters) { + return parameters.remove("native_version"); + } + + private static String extractHeadersId(final Map parameters) { + return parameters.remove("headers_id"); + } + + private static void extractEventCallbackId(final Map parameters) { parameters.remove("event_callback_id"); } - private static String buildAuthorizationHeader(Map parameters, - String appSecret, - String secretId, - String activityKind) { + private static String buildAuthorizationHeader(final Map parameters, + final String activityKind) { + String secretId = extractSecretId(parameters); + String headersId = extractHeadersId(parameters); + String signature = extractSignature(parameters); + String algorithm = extractAlgorithm(parameters); + String nativeVersion = extractNativeVersion(parameters); + + String authorizationHeader = buildAuthorizationHeaderV2(signature, secretId, + headersId, algorithm, nativeVersion); + if (authorizationHeader != null) { + return authorizationHeader; + } + + String appSecret = extractAppSecret(parameters); + return buildAuthorizationHeaderV1(parameters, appSecret, secretId, activityKind); + } + + private static String buildAuthorizationHeaderV1(final Map parameters, + final String appSecret, + final String secretId, + final String activityKind) { // check if the secret exists and it's not empty if (appSecret == null || appSecret.length() == 0) { return null; @@ -298,16 +331,39 @@ private static String buildAuthorizationHeader(Map parameters, String algorithmHeader = Util.formatString("algorithm=\"%s\"", algorithm); String fieldsHeader = Util.formatString("headers=\"%s\"", fields); - String authorizationHeader = Util.formatString("Signature %s,%s,%s,%s", secretIdHeader, signatureHeader, algorithmHeader, fieldsHeader); + String authorizationHeader = Util.formatString("Signature %s,%s,%s,%s", + secretIdHeader, signatureHeader, algorithmHeader, fieldsHeader); + getLogger().verbose("authorizationHeader: %s", authorizationHeader); + + return authorizationHeader; + } + + private static String buildAuthorizationHeaderV2(final String signature, + final String secretId, + final String headersId, + final String algorithm, + final String nativeVersion) { + if (secretId == null || signature == null || headersId == null) { + return null; + } + + String signatureHeader = Util.formatString("signature=\"%s\"", signature); + String secretIdHeader = Util.formatString("secret_id=\"%s\"", secretId); + String idHeader = Util.formatString("headers_id=\"%s\"", headersId); + String algorithmHeader = Util.formatString("algorithm=\"%s\"", algorithm != null ? algorithm : "adj1"); + String nativeVersionHeader = Util.formatString("native_version=\"%s\"", nativeVersion != null ? nativeVersion : ""); + + String authorizationHeader = Util.formatString("Signature %s,%s,%s,%s,%s", + signatureHeader, secretIdHeader, algorithmHeader, idHeader, nativeVersionHeader); + getLogger().verbose("authorizationHeader: %s", authorizationHeader); return authorizationHeader; } - private static Map getSignature( - final Map parameters, - final String activityKind, - final String appSecret) + private static Map getSignature(final Map parameters, + final String activityKind, + final String appSecret) { String activityKindName = "activity_kind"; String activityKindValue = activityKind; diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/scheduler/FutureScheduler.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/scheduler/FutureScheduler.java index 357bf6f4..4bf08727 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/scheduler/FutureScheduler.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/scheduler/FutureScheduler.java @@ -1,5 +1,6 @@ package com.adjust.sdk.scheduler; +import java.util.concurrent.Callable; import java.util.concurrent.ScheduledFuture; /** @@ -10,5 +11,7 @@ public interface FutureScheduler { ScheduledFuture scheduleFutureWithFixedDelay(Runnable command, long initialMillisecondDelay, long millisecondDelay); + ScheduledFuture scheduleFutureWithReturn(Callable callable, long millisecondDelay); + void teardown(); } diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/scheduler/SingleThreadFutureScheduler.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/scheduler/SingleThreadFutureScheduler.java index 2d20bac0..7f8c2c13 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/scheduler/SingleThreadFutureScheduler.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/scheduler/SingleThreadFutureScheduler.java @@ -2,6 +2,7 @@ import com.adjust.sdk.AdjustFactory; +import java.util.concurrent.Callable; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; @@ -35,6 +36,22 @@ public ScheduledFuture scheduleFuture(Runnable command, long millisecondDelay return scheduledThreadPoolExecutor.schedule(new RunnableWrapper(command), millisecondDelay, TimeUnit.MILLISECONDS); } + @Override + public ScheduledFuture scheduleFutureWithReturn(final Callable callable, long millisecondDelay) { + return scheduledThreadPoolExecutor.schedule(new Callable() { + @Override + public V call() throws Exception { + try { + return callable.call(); + } catch (Throwable t) { + AdjustFactory.getLogger().error("Callable error [%s] of type [%s]", + t.getMessage(), t.getClass().getCanonicalName()); + return null; + } + } + }, millisecondDelay, TimeUnit.MILLISECONDS); + } + @Override public ScheduledFuture scheduleFutureWithFixedDelay(Runnable command, long initialMillisecondDelay, long millisecondDelay) { return scheduledThreadPoolExecutor.scheduleWithFixedDelay(new RunnableWrapper(command), initialMillisecondDelay, millisecondDelay, TimeUnit.MILLISECONDS); diff --git a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/scheduler/TimerOnce.java b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/scheduler/TimerOnce.java index 959cad75..cec60fca 100644 --- a/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/scheduler/TimerOnce.java +++ b/ext/android/src/AdjustExtension/extension/src/main/java/com/adjust/sdk/scheduler/TimerOnce.java @@ -4,8 +4,10 @@ import com.adjust.sdk.ILogger; import com.adjust.sdk.Util; +import java.util.concurrent.ExecutionException; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; /** * Created by pfms on 08/05/15. diff --git a/ext/ios/sdk b/ext/ios/sdk index 46cddbab..2dad132c 160000 --- a/ext/ios/sdk +++ b/ext/ios/sdk @@ -1 +1 @@ -Subproject commit 46cddbab63baae4593d0a4757f2308144596c0cd +Subproject commit 2dad132c427a9b9e8c1ea428a2ddbb4f80e45ff2 diff --git a/ext/ios/src/AdjustExtension/AdjustExtension/AdjustExtension.m b/ext/ios/src/AdjustExtension/AdjustExtension/AdjustExtension.m index b5453d30..893aa03e 100644 --- a/ext/ios/src/AdjustExtension/AdjustExtension/AdjustExtension.m +++ b/ext/ios/src/AdjustExtension/AdjustExtension/AdjustExtension.m @@ -20,7 +20,7 @@ void AdjustFREContextInitializer( FREContext ctx, uint32_t* numFunctionsToSet, const FRENamedFunction** functionsToSet) { - uint32_t numberOfFunctions = 25; + uint32_t numberOfFunctions = 27; *numFunctionsToSet = numberOfFunctions; @@ -51,6 +51,8 @@ void AdjustFREContextInitializer( setNamedFunction(&func[22], (const uint8_t*)"gdprForgetMe", &ADJgdprForgetMe); setNamedFunction(&func[23], (const uint8_t*)"setTestOptions", &ADJsetTestOptions); setNamedFunction(&func[24], (const uint8_t*)"teardown", &ADJteardown); + setNamedFunction(&func[25], (const uint8_t*)"trackAdRevenue", &ADJtrackAdRevenue); + setNamedFunction(&func[26], (const uint8_t*)"disableThirdPartySharing", &ADJdisableThirdPartySharing); *functionsToSet = func; } diff --git a/ext/ios/src/AdjustExtension/AdjustExtension/AdjustFunction.h b/ext/ios/src/AdjustExtension/AdjustExtension/AdjustFunction.h index 93a23a67..c879de9c 100644 --- a/ext/ios/src/AdjustExtension/AdjustExtension/AdjustFunction.h +++ b/ext/ios/src/AdjustExtension/AdjustExtension/AdjustFunction.h @@ -33,6 +33,7 @@ FREObject ADJgetAttribution(FREContext ctx, void* funcData, uint32_t argc, FREOb FREObject ADJgetSdkVersion(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]); FREObject ADJgdprForgetMe(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]); FREObject ADJtrackAdRevenue(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]); +FREObject ADJdisableThirdPartySharing(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]); // Android methods. FREObject ADJonResume(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]); FREObject ADJonPause(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]); diff --git a/ext/ios/src/AdjustExtension/AdjustExtension/AdjustFunction.m b/ext/ios/src/AdjustExtension/AdjustExtension/AdjustFunction.m index 3f9b647e..ad2f25d8 100644 --- a/ext/ios/src/AdjustExtension/AdjustExtension/AdjustFunction.m +++ b/ext/ios/src/AdjustExtension/AdjustExtension/AdjustFunction.m @@ -18,11 +18,12 @@ @implementation AdjustFunction @end FREObject ADJonCreate(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) { - if (argc == 24) { + if (argc == 27) { NSString *appToken = nil; NSString *environment = nil; NSString *logLevelString = nil; NSString *defaultTracker = nil; + NSString *externalDeviceId = nil; NSString *sdkPrefix = nil; NSString *secretId = nil; NSString *info1 = nil; @@ -127,7 +128,7 @@ FREObject ADJonCreate(FREContext ctx, void* funcData, uint32_t argc, FREObject a } if (argv[16] != nil) { BOOL sendInBackground = NO; - FREGetObjectAsNativeBool(argv[15], &sendInBackground); + FREGetObjectAsNativeBool(argv[16], &sendInBackground); [adjustConfig setSendInBackground:sendInBackground]; } if (argv[17] != nil) { @@ -153,6 +154,24 @@ FREObject ADJonCreate(FREContext ctx, void* funcData, uint32_t argc, FREObject a // arg 23 is for Android only: ReadMobileEquipmentIdentity + if (argv[24] != nil) { + FREGetObjectAsNativeString(argv[24], &externalDeviceId); + + if (externalDeviceId != nil) { + [adjustConfig setExternalDeviceId:externalDeviceId]; + } + } + if (argv[25] != nil) { + BOOL allowiAdInfoReading = YES; + FREGetObjectAsNativeBool(argv[25], &allowiAdInfoReading); + [adjustConfig setAllowiAdInfoReading:allowiAdInfoReading]; + } + if (argv[26] != nil) { + BOOL allowIdfaReading = YES; + FREGetObjectAsNativeBool(argv[26], &allowIdfaReading); + [adjustConfig setAllowIdfaReading:allowIdfaReading]; + } + if (secretId != nil && info1 != nil && info2 != nil && info3 != nil && info4 != nil) { NSUInteger uiSecretId = [[NSNumber numberWithLongLong:[secretId longLongValue]] unsignedIntegerValue]; NSUInteger uiInfo1 = [[NSNumber numberWithLongLong:[info1 longLongValue]] unsignedIntegerValue]; @@ -548,6 +567,18 @@ FREObject ADJgdprForgetMe(FREContext ctx, void* funcData, uint32_t argc, FREObje return return_value; } +FREObject ADJdisableThirdPartySharing(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) { + if (argc == 0) { + [Adjust disableThirdPartySharing]; + } else { + NSLog(@"AdjustFunction: Bridge disableThirdPartySharing method triggered with wrong number of arguments"); + } + + FREObject return_value; + FRENewObjectFromBool(true, &return_value); + return return_value; +} + FREObject ADJtrackAdRevenue(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) { if (argc == 2) { NSString *source = nil; @@ -570,7 +601,7 @@ FREObject ADJtrackAdRevenue(FREContext ctx, void* funcData, uint32_t argc, FREOb } FREObject ADJsetTestOptions(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) { - if (argc == 13) { + if (argc == 14) { AdjustTestOptions * testOptions = [[AdjustTestOptions alloc] init]; // Treating Android's `hasContext` as `deleteState` @@ -632,9 +663,14 @@ FREObject ADJsetTestOptions(FREContext ctx, void* funcData, uint32_t argc, FREOb if (argv[12] != nil) { BOOL value; - FREGetObjectAsNativeBool(argv[10], &value); + FREGetObjectAsNativeBool(argv[12], &value); testOptions.noBackoffWait = value; } + if (argv[13] != nil) { + BOOL value; + FREGetObjectAsNativeBool(argv[13], &value); + testOptions.iAdFrameworkEnabled = value; + } [Adjust setTestOptions:testOptions]; } else { diff --git a/ext/scripts b/ext/scripts index f21a31ff..368bb756 160000 --- a/ext/scripts +++ b/ext/scripts @@ -1 +1 @@ -Subproject commit f21a31ff8a5e4d975dd09779ddae4d6c99d7e4da +Subproject commit 368bb7560e5ceadd8d04092e8dfb61a924d6e72d diff --git a/src/com/adjust/sdk/Adjust.as b/src/com/adjust/sdk/Adjust.as index 2c51f9ae..5146ec95 100644 --- a/src/com/adjust/sdk/Adjust.as +++ b/src/com/adjust/sdk/Adjust.as @@ -4,7 +4,7 @@ package com.adjust.sdk { import flash.external.ExtensionContext; public class Adjust extends EventDispatcher { - private static var sdkPrefix:String = "adobe_air4.18.0"; + private static var sdkPrefix:String = "adobe_air4.21.0"; private static var errorMessage:String = "Adjust: SDK not started. Start it manually using the 'start' method"; private static var hasSdkStarted:Boolean = false; @@ -79,7 +79,10 @@ package com.adjust.sdk { adjustConfig.getInfo3(), adjustConfig.getInfo4(), adjustConfig.getIsDeviceKnown(), - adjustConfig.getReadMobileEquipmentIdentity()); + adjustConfig.getReadMobileEquipmentIdentity(), + adjustConfig.getExternalDeviceId(), + adjustConfig.getAllowiAdInfoReading(), + adjustConfig.getAllowIdfaReading()); // For now, call onResume after onCreate. getExtensionContext().call("onResume"); @@ -204,6 +207,10 @@ package com.adjust.sdk { getExtensionContext().call("trackAdRevenue", source, payload); } + public static function disableThirdPartySharing():void { + getExtensionContext().call("disableThirdPartySharing"); + } + public static function setTestOptions(testOptions:AdjustTestOptions):void { getExtensionContext().call("setTestOptions", testOptions.hasContext, @@ -218,7 +225,8 @@ package com.adjust.sdk { testOptions.subsessionIntervalInMilliseconds, testOptions.teardown, testOptions.tryInstallReferrer, - testOptions.noBackoffWait); + testOptions.noBackoffWait, + testOptions.iAdFrameworkEnabled); } public static function teardown():void { diff --git a/src/com/adjust/sdk/AdjustConfig.as b/src/com/adjust/sdk/AdjustConfig.as index af576fc6..1e90a3cd 100644 --- a/src/com/adjust/sdk/AdjustConfig.as +++ b/src/com/adjust/sdk/AdjustConfig.as @@ -6,6 +6,7 @@ package com.adjust.sdk { private var userAgent:String; private var environment:String; private var defaultTracker:String; + private var externalDeviceId:String; private var sendInBackground:Boolean; private var shouldLaunchDeeplink:Boolean; private var eventBufferingEnabled:Boolean; @@ -21,13 +22,25 @@ package com.adjust.sdk { private var info2:String; private var info3:String; private var info4:String; - // Android only. + // Android only private var processName:String; private var readMobileEquipmentIdentity:Boolean; + // iOS only + private var allowiAdInfoReading:Boolean; + private var allowIdfaReading:Boolean; public function AdjustConfig(appToken:String, environment:String) { this.appToken = appToken; this.environment = environment; + + // set Boolean members to their default values + this.sendInBackground = false; + this.shouldLaunchDeeplink = true; + this.eventBufferingEnabled = false; + this.isDeviceKnown = false; + this.readMobileEquipmentIdentity = false; + this.allowiAdInfoReading = true; + this.allowIdfaReading = true; } public function setLogLevel(logLevel:String):void { @@ -54,6 +67,10 @@ package com.adjust.sdk { this.defaultTracker = defaultTracker; } + public function setExternalDeviceId(externalDeviceId:String):void { + this.externalDeviceId = externalDeviceId; + } + public function setProcessName(processName:String):void { this.processName = processName; } @@ -112,7 +129,15 @@ package com.adjust.sdk { this.readMobileEquipmentIdentity = readMobileEquipmentIdentity; } - // Getters. + public function setAllowiAdInfoReading(allowiAdInfoReading:Boolean):void { + this.allowiAdInfoReading = allowiAdInfoReading; + } + + public function setAllowIdfaReading(allowIdfaReading:Boolean):void { + this.allowIdfaReading = allowIdfaReading; + } + + // Getters public function getAppToken():String { return this.appToken; } @@ -145,6 +170,10 @@ package com.adjust.sdk { return this.defaultTracker; } + public function getExternalDeviceId():String { + return this.externalDeviceId; + } + public function getProcessName():String { return this.processName; } @@ -204,5 +233,13 @@ package com.adjust.sdk { public function getReadMobileEquipmentIdentity():Boolean { return this.readMobileEquipmentIdentity; } + + public function getAllowiAdInfoReading():Boolean { + return this.allowiAdInfoReading; + } + + public function getAllowIdfaReading():Boolean { + return this.allowIdfaReading; + } } } diff --git a/src/com/adjust/sdk/AdjustTestOptions.as b/src/com/adjust/sdk/AdjustTestOptions.as index 76c3bc82..a784768f 100644 --- a/src/com/adjust/sdk/AdjustTestOptions.as +++ b/src/com/adjust/sdk/AdjustTestOptions.as @@ -5,6 +5,7 @@ package com.adjust.sdk { public var noBackoffWait:Boolean = false; public var tryInstallReferrer:Boolean = false; public var useTestConnectionOptions:Boolean = false; + public var iAdFrameworkEnabled:Boolean = false; public var baseUrl:String = null; public var gdprUrl:String = null; public var basePath:String = null; diff --git a/src/extension.xml b/src/extension.xml index 97970476..de758a83 100644 --- a/src/extension.xml +++ b/src/extension.xml @@ -1,6 +1,6 @@ - + com.adjust.sdk - 4.18.0 + 4.21.0 diff --git a/src/platformoptions_ios.xml b/src/platformoptions_ios.xml index aca2482e..c5fff0b8 100644 --- a/src/platformoptions_ios.xml +++ b/src/platformoptions_ios.xml @@ -1,4 +1,4 @@ - + 7.0 diff --git a/test/app/AdjustCommandExecutor.as b/test/app/AdjustCommandExecutor.as index d6151576..de6645e4 100644 --- a/test/app/AdjustCommandExecutor.as +++ b/test/app/AdjustCommandExecutor.as @@ -108,6 +108,7 @@ package { case "sendReferrer" : this.sendReferrer(command.params); break; case "gdprForgetMe" : this.gdprForgetMe(command.params); break; case "trackAdRevenue" : this.trackAdRevenue(command.params); break; + case "disableThirdPartySharing" : this.disableThirdPartySharing(command.params); break; } this.nextToSendCounter++; @@ -148,6 +149,9 @@ package { if (params['noBackoffWait'] != null) { testOptions.noBackoffWait = getFirstParameterValue(params, 'noBackoffWait') == "true"; } + if (params['iAdFrameworkEnabled'] != null) { + testOptions.iAdFrameworkEnabled = getFirstParameterValue(params, 'iAdFrameworkEnabled') == "true"; + } if (params['teardown'] != null) { var teardownOptions:Array = getValueFromKey(params, 'teardown'); for (var i:int = 0; i < teardownOptions.length; i++) { @@ -216,6 +220,10 @@ package { var defaultTracker:String = getFirstParameterValue(params, 'defaultTracker'); adjustConfig.setDefaultTracker(defaultTracker); } + if (params['externalDeviceId'] != null) { + var externalDeviceId:String = getFirstParameterValue(params, 'externalDeviceId'); + adjustConfig.setExternalDeviceId(externalDeviceId); + } if (params['appSecret'] != null) { var appSecretArray:Array = getValueFromKey(params, 'appSecret'); var secretId:Number = Number(appSecretArray[0].toString()); @@ -265,6 +273,16 @@ package { adjustConfig.setShouldLaunchDeeplink(shouldLaunchDeeplink); adjustConfig.setDeferredDeeplinkDelegate(deferredDeeplinkDelegate); } + if (params['allowiAdInfoReading'] != null) { + var allowiAdInfoReadingS:String = getFirstParameterValue(params, 'allowiAdInfoReading'); + var allowiAdInfoReading:Boolean = (allowiAdInfoReadingS === 'true'); + adjustConfig.setAllowiAdInfoReading(allowiAdInfoReading); + } + if (params['allowIdfaReading'] != null) { + var allowIdfaReadingS:String = getFirstParameterValue(params, 'allowIdfaReading'); + var allowIdfaReading:Boolean = (allowIdfaReadingS === 'true'); + adjustConfig.setAllowIdfaReading(allowIdfaReading); + } } private function start(params:Object):void { @@ -430,6 +448,10 @@ package { Adjust.gdprForgetMe(); } + private function disableThirdPartySharing(params:Object):void { + Adjust.disableThirdPartySharing(); + } + private function trackAdRevenue(params:Object):void { var source:String = getFirstParameterValue(params, 'adRevenueSource'); var payload:String = getFirstParameterValue(params, 'adRevenueJsonString'); diff --git a/test/app/Main-app.xml b/test/app/Main-app.xml index 4c78667f..9d3f810c 100644 --- a/test/app/Main-app.xml +++ b/test/app/Main-app.xml @@ -1,7 +1,7 @@ com.adjust.examples - 4.18.0 + 4.21.0 Adjust AIR SDK Test diff --git a/test/app/Main.as b/test/app/Main.as index 81a082cf..2c986407 100644 --- a/test/app/Main.as +++ b/test/app/Main.as @@ -8,7 +8,7 @@ package { public class Main extends Sprite { // Android: Make sure to use HTTPS with port 8443 with a physical device. // iOS: Make sure to use HTTP with port 8080 with a physical device. - public static var ipAddress:String = '192.168.9.235'; + public static var ipAddress:String = '192.168.86.28'; public static var baseUrl:String = 'https://' + ipAddress + ':8443'; public static var gdprUrl:String = 'https://' + ipAddress + ':8443'; public static var controlUrl:String = 'ws://' + ipAddress + ':1987'; diff --git a/test/app/lib/AdjustTest-4.18.0.ane b/test/app/lib/AdjustTest-4.18.0.ane deleted file mode 100644 index 50146d1d..00000000 Binary files a/test/app/lib/AdjustTest-4.18.0.ane and /dev/null differ diff --git a/test/app/lib/AdjustTest-4.21.0.ane b/test/app/lib/AdjustTest-4.21.0.ane new file mode 100644 index 00000000..5268d8b9 Binary files /dev/null and b/test/app/lib/AdjustTest-4.21.0.ane differ diff --git a/test/plugin/android/adjust-android-test.jar b/test/plugin/android/adjust-android-test.jar index 7c0b1aaa..eab49bc0 100644 Binary files a/test/plugin/android/adjust-android-test.jar and b/test/plugin/android/adjust-android-test.jar differ diff --git a/test/plugin/android/src/AdjustTestExtension/extension/build.gradle b/test/plugin/android/src/AdjustTestExtension/extension/build.gradle index 9a4d663d..cfcbc09a 100644 --- a/test/plugin/android/src/AdjustTestExtension/extension/build.gradle +++ b/test/plugin/android/src/AdjustTestExtension/extension/build.gradle @@ -40,6 +40,7 @@ dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'com.android.support:appcompat-v7:28.0.0' implementation files('libs/FlashRuntimeExtensions.jar') - implementation files('libs/gson-2.8.0.jar') - implementation files('libs/Java-WebSocket-1.3.9.jar') + implementation files('libs/gson-2.8.6.jar') + implementation files('libs/Java-WebSocket-1.4.0.jar') + implementation files('libs/slf4j-api-1.7.30.jar') } diff --git a/test/plugin/android/src/AdjustTestExtension/extension/libs/Java-WebSocket-1.3.9.jar b/test/plugin/android/src/AdjustTestExtension/extension/libs/Java-WebSocket-1.3.9.jar deleted file mode 100644 index c0319475..00000000 Binary files a/test/plugin/android/src/AdjustTestExtension/extension/libs/Java-WebSocket-1.3.9.jar and /dev/null differ diff --git a/test/plugin/android/src/AdjustTestExtension/extension/libs/Java-WebSocket-1.4.0.jar b/test/plugin/android/src/AdjustTestExtension/extension/libs/Java-WebSocket-1.4.0.jar new file mode 100644 index 00000000..fc190e3b Binary files /dev/null and b/test/plugin/android/src/AdjustTestExtension/extension/libs/Java-WebSocket-1.4.0.jar differ diff --git a/test/plugin/android/src/AdjustTestExtension/extension/libs/gson-2.8.0.jar b/test/plugin/android/src/AdjustTestExtension/extension/libs/gson-2.8.0.jar deleted file mode 100644 index 1235f638..00000000 Binary files a/test/plugin/android/src/AdjustTestExtension/extension/libs/gson-2.8.0.jar and /dev/null differ diff --git a/test/plugin/android/src/AdjustTestExtension/extension/libs/gson-2.8.6.jar b/test/plugin/android/src/AdjustTestExtension/extension/libs/gson-2.8.6.jar new file mode 100644 index 00000000..4765c4af Binary files /dev/null and b/test/plugin/android/src/AdjustTestExtension/extension/libs/gson-2.8.6.jar differ diff --git a/test/plugin/android/src/AdjustTestExtension/extension/libs/slf4j-api-1.7.30.jar b/test/plugin/android/src/AdjustTestExtension/extension/libs/slf4j-api-1.7.30.jar new file mode 100644 index 00000000..29ac26fb Binary files /dev/null and b/test/plugin/android/src/AdjustTestExtension/extension/libs/slf4j-api-1.7.30.jar differ diff --git a/test/plugin/ios/AdjustTestLibrary.framework/AdjustTestLibrary b/test/plugin/ios/AdjustTestLibrary.framework/AdjustTestLibrary index e6fed85a..9f31bfa2 100644 Binary files a/test/plugin/ios/AdjustTestLibrary.framework/AdjustTestLibrary and b/test/plugin/ios/AdjustTestLibrary.framework/AdjustTestLibrary differ diff --git a/test/plugin/ios/AdjustTestLibrary.framework/Versions/A/AdjustTestLibrary b/test/plugin/ios/AdjustTestLibrary.framework/Versions/A/AdjustTestLibrary index e6fed85a..9f31bfa2 100644 Binary files a/test/plugin/ios/AdjustTestLibrary.framework/Versions/A/AdjustTestLibrary and b/test/plugin/ios/AdjustTestLibrary.framework/Versions/A/AdjustTestLibrary differ diff --git a/test/plugin/ios/AdjustTestLibrary.framework/Versions/Current/AdjustTestLibrary b/test/plugin/ios/AdjustTestLibrary.framework/Versions/Current/AdjustTestLibrary index e6fed85a..9f31bfa2 100644 Binary files a/test/plugin/ios/AdjustTestLibrary.framework/Versions/Current/AdjustTestLibrary and b/test/plugin/ios/AdjustTestLibrary.framework/Versions/Current/AdjustTestLibrary differ diff --git a/test/plugin/ios/src/AdjustTestExtension/AdjustTestExtension/AdjustTestFunction.m b/test/plugin/ios/src/AdjustTestExtension/AdjustTestExtension/AdjustTestFunction.m index cc03f18e..096625f6 100644 --- a/test/plugin/ios/src/AdjustTestExtension/AdjustTestExtension/AdjustTestFunction.m +++ b/test/plugin/ios/src/AdjustTestExtension/AdjustTestExtension/AdjustTestFunction.m @@ -21,7 +21,7 @@ @implementation AdjustTestFunction @end FREObject ADJstartTestSession(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) { - if (argc == 2) { + if (argc == 3) { NSString *baseUrl = nil; NSString *controlUrl = nil; NSString *clientSdk = nil; diff --git a/test/plugin/ios/src/AdjustTestExtension/AdjustTestLibrary.framework/AdjustTestLibrary b/test/plugin/ios/src/AdjustTestExtension/AdjustTestLibrary.framework/AdjustTestLibrary index e6fed85a..9f31bfa2 100644 Binary files a/test/plugin/ios/src/AdjustTestExtension/AdjustTestLibrary.framework/AdjustTestLibrary and b/test/plugin/ios/src/AdjustTestExtension/AdjustTestLibrary.framework/AdjustTestLibrary differ diff --git a/test/plugin/ios/src/AdjustTestExtension/AdjustTestLibrary.framework/Versions/A/AdjustTestLibrary b/test/plugin/ios/src/AdjustTestExtension/AdjustTestLibrary.framework/Versions/A/AdjustTestLibrary index e6fed85a..9f31bfa2 100644 Binary files a/test/plugin/ios/src/AdjustTestExtension/AdjustTestLibrary.framework/Versions/A/AdjustTestLibrary and b/test/plugin/ios/src/AdjustTestExtension/AdjustTestLibrary.framework/Versions/A/AdjustTestLibrary differ diff --git a/test/plugin/ios/src/AdjustTestExtension/AdjustTestLibrary.framework/Versions/Current/AdjustTestLibrary b/test/plugin/ios/src/AdjustTestExtension/AdjustTestLibrary.framework/Versions/Current/AdjustTestLibrary index e6fed85a..9f31bfa2 100644 Binary files a/test/plugin/ios/src/AdjustTestExtension/AdjustTestLibrary.framework/Versions/Current/AdjustTestLibrary and b/test/plugin/ios/src/AdjustTestExtension/AdjustTestLibrary.framework/Versions/Current/AdjustTestLibrary differ diff --git a/test/plugin/src/extension.xml b/test/plugin/src/extension.xml index 618c5c45..31d5389e 100644 --- a/test/plugin/src/extension.xml +++ b/test/plugin/src/extension.xml @@ -1,6 +1,6 @@ - + com.adjust.test - 4.18.0 + 4.21.0 diff --git a/test/plugin/src/platformoptions_android.xml b/test/plugin/src/platformoptions_android.xml deleted file mode 100644 index 5de0950a..00000000 --- a/test/plugin/src/platformoptions_android.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - gson-2.8.0.jar - - diff --git a/test/plugin/src/platformoptions_android_test.xml b/test/plugin/src/platformoptions_android_test.xml new file mode 100644 index 00000000..1defabe7 --- /dev/null +++ b/test/plugin/src/platformoptions_android_test.xml @@ -0,0 +1,7 @@ + + + gson-2.8.6.jar + Java-WebSocket-1.4.0.jar + slf4j-api-1.7.30.jar + + diff --git a/test/plugin/src/platformoptions_ios.xml b/test/plugin/src/platformoptions_ios_test.xml similarity index 70% rename from test/plugin/src/platformoptions_ios.xml rename to test/plugin/src/platformoptions_ios_test.xml index c34449fe..a6b515bb 100644 --- a/test/plugin/src/platformoptions_ios.xml +++ b/test/plugin/src/platformoptions_ios_test.xml @@ -1,5 +1,5 @@ - - 6.0 + + 8.0