diff --git a/CHANGELOG.md b/CHANGELOG.md index fb7f96e..79a8f96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +### Version 5.4.0 (13th June 2025) +#### Added +- Added support for configuring store information via the `AdjustStoreInfo` object. You can now specify the store name and store app ID by assigning the `storeInfo` member of your `AdjustConfig` instance. This enables the SDK to record the intended app store source during initialization. For more details about this feature, refer to the [official documentation](https://dev.adjust.com/en/sdk/flutter/setup/store-type). +- Added ability to initialize the SDK for the first session in delayed mode. You can start the SDK in the delayed mode by setting the `isFirstSessionDelayEnabled` member on your `AdjustConfig` instance to `true`. To end the delay, make sure to call `endFirstSessionDelay` method of `Adjust` instance. For more details about this feature, refer to the [official documentation](https://dev.adjust.com/en/sdk/flutter/features/first-session-delay). +- Added ability to send organic search referrer together with deep link. You can send it via `referrer` member of the `AdjustDeeplink` instance. For more details about this feature, refer to the [official documentation](https://dev.adjust.com/en/sdk/flutter/features/deep-links#handling-deeplinks-with-referrer). +- Added ability to disable SDK's interaction with `AppTrackingTransparency.framework` API. You can disable it by setting the `isAppTrackingTransparencyUsageEnabled` member on your `AdjustConfig` instance to `false`. For more details about this feature, refer to the [official documentation](https://dev.adjust.com/en/sdk/flutter/features/att#disable-att-framework). + +#### Native SDKs +- [iOS@v5.4.0][ios_sdk_v5.4.0] +- [Android@v5.4.0][android_sdk_v5.4.0] + +--- + ### Version 5.1.1 (March 5th 2025) #### Fixed - Fixed crashes happening in cases where native iOS `jsonResponse` is `nil` (https://github.com/adjust/flutter_sdk/pull/160). @@ -536,6 +549,7 @@ In case you were using beta version of the SDK v5, please switch to the official [ios_sdk_v5.0.0]: https://github.com/adjust/ios_sdk/tree/v5.0.0 [ios_sdk_v5.0.1]: https://github.com/adjust/ios_sdk/tree/v5.0.1 [ios_sdk_v5.1.1]: https://github.com/adjust/ios_sdk/tree/v5.1.1 +[ios_sdk_v5.4.0]: https://github.com/adjust/ios_sdk/tree/v5.4.0 [android_sdk_v4.17.0]: https://github.com/adjust/android_sdk/tree/v4.17.0 [android_sdk_v4.18.0]: https://github.com/adjust/android_sdk/tree/v4.18.0 @@ -564,3 +578,4 @@ In case you were using beta version of the SDK v5, please switch to the official [android_sdk_v5.0.1]: https://github.com/adjust/android_sdk/tree/v5.0.1 [android_sdk_v5.0.2]: https://github.com/adjust/android_sdk/tree/v5.0.2 [android_sdk_v5.1.0]: https://github.com/adjust/android_sdk/tree/v5.1.0 +[android_sdk_v5.4.0]: https://github.com/adjust/android_sdk/tree/v5.4.0 diff --git a/VERSION b/VERSION index ac14c3d..8a30e8f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.1.1 +5.4.0 diff --git a/android/build.gradle b/android/build.gradle index 9737c82..7577056 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -37,5 +37,5 @@ android { } dependencies { - implementation 'com.adjust.sdk:adjust-android:5.1.0' + implementation 'com.adjust.sdk:adjust-android:5.4.0' } diff --git a/android/src/main/java/com/adjust/sdk/flutter/AdjustSdk.java b/android/src/main/java/com/adjust/sdk/flutter/AdjustSdk.java index 85cc116..c6f4507 100644 --- a/android/src/main/java/com/adjust/sdk/flutter/AdjustSdk.java +++ b/android/src/main/java/com/adjust/sdk/flutter/AdjustSdk.java @@ -23,6 +23,7 @@ import com.adjust.sdk.AdjustSessionSuccess; import com.adjust.sdk.AdjustPlayStoreSubscription; import com.adjust.sdk.AdjustPurchaseVerificationResult; +import com.adjust.sdk.AdjustStoreInfo; import com.adjust.sdk.AdjustThirdPartySharing; import com.adjust.sdk.AdjustTestOptions; import com.adjust.sdk.LogLevel; @@ -85,29 +86,21 @@ public void onDetachedFromEngine(FlutterPluginBinding binding) { @Override public void onMethodCall(MethodCall call, final Result result) { switch (call.method) { + // common case "initSdk": initSdk(call, result); break; case "trackEvent": trackEvent(call, result); break; - case "isEnabled": - isEnabled(result); - break; - case "enable": - enable(result); - break; - case "disable": - disable(result); - break; - case "switchToOfflineMode": - switchToOfflineMode(result); + case "trackAdRevenue": + trackAdRevenue(call, result); break; - case "switchBackToOnlineMode": - switchBackToOnlineMode(result); + case "trackThirdPartySharing": + trackThirdPartySharing(call, result); break; - case "setPushToken": - setPushToken(call, result); + case "trackMeasurementConsent": + trackMeasurementConsent(call, result); break; case "processDeeplink": processDeeplink(call, result); @@ -115,23 +108,23 @@ public void onMethodCall(MethodCall call, final Result result) { case "processAndResolveDeeplink": processAndResolveDeeplink(call, result); break; - case "getAdid": - getAdid(result); + case "setPushToken": + setPushToken(call, result); break; - case "getGoogleAdId": - getGoogleAdId(result); + case "gdprForgetMe": + gdprForgetMe(result); break; - case "getAmazonAdId": - getAmazonAdId(result); + case "enable": + enable(result); break; - case "getAttribution": - getAttribution(result); + case "disable": + disable(result); break; - case "getSdkVersion": - getSdkVersion(result); + case "switchToOfflineMode": + switchToOfflineMode(result); break; - case "gdprForgetMe": - gdprForgetMe(result); + case "switchBackToOnlineMode": + switchBackToOnlineMode(result); break; case "addGlobalCallbackParameter": addGlobalCallbackParameter(call, result); @@ -151,53 +144,81 @@ public void onMethodCall(MethodCall call, final Result result) { case "removeGlobalPartnerParameters": removeGlobalPartnerParameters(result); break; - case "trackAdRevenue": - trackAdRevenue(call, result); + case "endFirstSessionDelay": + endFirstSessionDelay(call, result); break; - case "trackPlayStoreSubscription": - trackPlayStoreSubscription(call, result); + case "enableCoppaComplianceInDelay": + enableCoppaComplianceInDelay(call, result); break; - case "trackThirdPartySharing": - trackThirdPartySharing(call, result); + case "disableCoppaComplianceInDelay": + disableCoppaComplianceInDelay(call, result); break; - case "trackMeasurementConsent": - trackMeasurementConsent(call, result); + case "enablePlayStoreKidsComplianceInDelay": + enablePlayStoreKidsComplianceInDelay(call, result); + break; + case "disablePlayStoreKidsComplianceInDelay": + disablePlayStoreKidsComplianceInDelay(call, result); + break; + case "setExternalDeviceIdInDelay": + setExternalDeviceIdInDelay(call, result); + break; + case "isEnabled": + isEnabled(result); + break; + case "getAttribution": + getAttribution(result); + break; + case "getAdid": + getAdid(result); break; case "getLastDeeplink": getLastDeeplink(result); break; + case "getSdkVersion": + getSdkVersion(result); + break; + // android only + case "trackPlayStoreSubscription": + trackPlayStoreSubscription(call, result); + break; case "verifyPlayStorePurchase": verifyPlayStorePurchase(call, result); break; case "verifyAndTrackPlayStorePurchase": verifyAndTrackPlayStorePurchase(call, result); break; - // ios only methods - case "getIdfa": - getIdfa(result); + case "getGoogleAdId": + getGoogleAdId(result); break; - case "getIdfv": - getIdfv(result); + case "getAmazonAdId": + getAmazonAdId(result); break; + // ios only methods case "trackAppStoreSubscription": trackAppStoreSubscription(result); break; + case "verifyAppStorePurchase": + verifyAppStorePurchase(call, result); + break; + case "verifyAndTrackAppStorePurchase": + verifyAndTrackAppStorePurchase(call, result); + break; case "requestAppTrackingAuthorization": requestAppTrackingAuthorization(result); break; case "updateSkanConversionValue": updateSkanConversionValue(result); break; - case "getAppTrackingAuthorizationStatus": - getAppTrackingAuthorizationStatus(call, result); + case "getIdfa": + getIdfa(result); break; - case "verifyAppStorePurchase": - verifyAppStorePurchase(call, result); + case "getIdfv": + getIdfv(result); break; - case "verifyAndTrackAppStorePurchase": - verifyAndTrackAppStorePurchase(call, result); + case "getAppTrackingAuthorizationStatus": + getAppTrackingAuthorizationStatus(call, result); break; - // used for testing only + // testing only case "onPause": onPause(result); break; @@ -214,6 +235,8 @@ public void onMethodCall(MethodCall call, final Result result) { } } + // common + private void initSdk(final MethodCall call, final Result result) { Map configMap = (Map) call.arguments; if (configMap == null) { @@ -283,6 +306,15 @@ private void initSdk(final MethodCall call, final Result result) { } } + // first session delay + if (configMap.containsKey("isFirstSessionDelayEnabled")) { + String strIsFirstSessionDelayEnabled = (String) configMap.get("isFirstSessionDelayEnabled"); + boolean isFirstSessionDelayEnabled = Boolean.parseBoolean(strIsFirstSessionDelayEnabled); + if (isFirstSessionDelayEnabled) { + adjustConfig.enableFirstSessionDelay(); + } + } + // COPPA compliance if (configMap.containsKey("isCoppaComplianceEnabled")) { String strIsCoppaComplianceEnabled = (String) configMap.get("isCoppaComplianceEnabled"); @@ -319,6 +351,24 @@ private void initSdk(final MethodCall call, final Result result) { } catch (Exception e) {} } + // set store info + if (configMap.containsKey("storeInfo")) { + try { + String strStoreInfo = (String) configMap.get("storeInfo"); + JSONObject storeInfo = new JSONObject(strStoreInfo); + + if (storeInfo.has("storeName") && !storeInfo.isNull("storeName")) { + String storeName = storeInfo.getString("storeName"); + AdjustStoreInfo adjustStoreInfo = new AdjustStoreInfo(storeName); + if (storeInfo.has("storeAppId") && !storeInfo.isNull("storeAppId")) { + String storeAppId = storeInfo.getString("storeAppId"); + adjustStoreInfo.setStoreAppId(storeAppId); + } + adjustConfig.setStoreInfo(adjustStoreInfo); + } + } catch (JSONException ignored) {} + } + // URL strategy if (configMap.containsKey("urlStrategyDomains") && configMap.containsKey("useSubdomains") @@ -640,126 +690,225 @@ private void trackEvent(final MethodCall call, final Result result) { result.success(null); } - private void switchToOfflineMode(final Result result) { - Adjust.switchToOfflineMode(); - result.success(null); - } + private void trackAdRevenue(final MethodCall call, final Result result) { + Map adRevenueMap = (Map) call.arguments; + if (adRevenueMap == null) { + return; + } - private void switchBackToOnlineMode(final Result result) { - Adjust.switchBackToOnlineMode(); - result.success(null); - } + // ad revenue source + String source = null; + if (adRevenueMap.containsKey("source")) { + source = (String) adRevenueMap.get("source"); + } - private void setPushToken(final MethodCall call, final Result result) { - Map tokenParamsMap = (Map) call.arguments; - String pushToken = null; - if (tokenParamsMap.containsKey("pushToken")) { - pushToken = tokenParamsMap.get("pushToken").toString(); + // create ad revenue object + AdjustAdRevenue adRevenue = new AdjustAdRevenue(source); + + // revenue and currency + if (adRevenueMap.containsKey("revenue") || adRevenueMap.containsKey("currency")) { + double revenue = -1.0; + String strRevenue = (String) adRevenueMap.get("revenue"); + + try { + revenue = Double.parseDouble(strRevenue); + String currency = (String) adRevenueMap.get("currency"); + adRevenue.setRevenue(revenue, currency); + } catch (NumberFormatException ignore) {} } - Adjust.setPushToken(pushToken, applicationContext); - result.success(null); - } - private void enable(final Result result) { - Adjust.enable(); - result.success(null); - } - private void disable( final Result result) { - Adjust.disable(); - result.success(null); - } + // ad impressions count + if (adRevenueMap.containsKey("adImpressionsCount")) { + String strAdImpressionsCount = (String) adRevenueMap.get("adImpressionsCount"); + int adImpressionsCount = Integer.parseInt(strAdImpressionsCount); + adRevenue.setAdImpressionsCount(adImpressionsCount); + } - private void processDeeplink(final MethodCall call, final Result result) { - Map urlParamsMap = (Map) call.arguments; - String url = null; - if (urlParamsMap.containsKey("deeplink")) { - url = urlParamsMap.get("deeplink").toString(); + // ad revenue network + if (adRevenueMap.containsKey("adRevenueNetwork")) { + String adRevenueNetwork = (String) adRevenueMap.get("adRevenueNetwork"); + adRevenue.setAdRevenueNetwork(adRevenueNetwork); } - Adjust.processDeeplink(new AdjustDeeplink(Uri.parse(url)), applicationContext); - result.success(null); - } - private void isEnabled(final Result result) { - Adjust.isEnabled(applicationContext, new OnIsEnabledListener() { - @Override - public void onIsEnabledRead(boolean isEnabled) { - result.success(isEnabled); - } - }); - } + // ad revenue unit + if (adRevenueMap.containsKey("adRevenueUnit")) { + String adRevenueUnit = (String) adRevenueMap.get("adRevenueUnit"); + adRevenue.setAdRevenueUnit(adRevenueUnit); + } - private void getAdid(final Result result) { - Adjust.getAdid(new OnAdidReadListener() { - @Override - public void onAdidRead(String adid) { - result.success(adid); - } - }); - } + // ad revenue placement + if (adRevenueMap.containsKey("adRevenuePlacement")) { + String adRevenuePlacement = (String) adRevenueMap.get("adRevenuePlacement"); + adRevenue.setAdRevenuePlacement(adRevenuePlacement); + } - private void getGoogleAdId(final Result result) { - Adjust.getGoogleAdId(applicationContext, new OnGoogleAdIdReadListener() { - @Override - public void onGoogleAdIdRead(String googleAdId) { - result.success(googleAdId); + // callback parameters + if (adRevenueMap.containsKey("callbackParameters")) { + String strCallbackParametersJson = (String) adRevenueMap.get("callbackParameters"); + try { + JSONObject jsonCallbackParameters = new JSONObject(strCallbackParametersJson); + JSONArray callbackParametersKeys = jsonCallbackParameters.names(); + for (int i = 0; i < callbackParametersKeys.length(); ++i) { + String key = callbackParametersKeys.getString(i); + String value = jsonCallbackParameters.getString(key); + adRevenue.addCallbackParameter(key, value); + } + } catch (JSONException e) { + Log.e(TAG, "Failed to parse ad revenue callback parameter! Details: " + e); } - }); - } + } - private void getAmazonAdId(final Result result) { - Adjust.getAmazonAdId(applicationContext, new OnAmazonAdIdReadListener() { - @Override - public void onAmazonAdIdRead(String amazonAdId) { - result.success(amazonAdId); + // partner parameters + if (adRevenueMap.containsKey("partnerParameters")) { + String strPartnerParametersJson = (String) adRevenueMap.get("partnerParameters"); + try { + JSONObject jsonPartnerParameters = new JSONObject(strPartnerParametersJson); + JSONArray partnerParametersKeys = jsonPartnerParameters.names(); + for (int i = 0; i < partnerParametersKeys.length(); ++i) { + String key = partnerParametersKeys.getString(i); + String value = jsonPartnerParameters.getString(key); + adRevenue.addPartnerParameter(key, value); + } + } catch (JSONException e) { + Log.e(TAG, "Failed to parse ad revenue partner parameter! Details: " + e); } - }); - } + } - private void gdprForgetMe(final Result result) { - Adjust.gdprForgetMe(applicationContext); + // track ad revenue + Adjust.trackAdRevenue(adRevenue); result.success(null); } - private void getAttribution(final Result result) { - Adjust.getAttribution(new OnAttributionReadListener() { - @Override - public void onAttributionRead(AdjustAttribution attribution) { - HashMap adjustAttributionMap = new HashMap(); - adjustAttributionMap.put("trackerToken", attribution.trackerToken); - adjustAttributionMap.put("trackerName", attribution.trackerName); - adjustAttributionMap.put("network", attribution.network); - adjustAttributionMap.put("campaign", attribution.campaign); - adjustAttributionMap.put("adgroup", attribution.adgroup); - adjustAttributionMap.put("creative", attribution.creative); - adjustAttributionMap.put("clickLabel", attribution.clickLabel); - adjustAttributionMap.put("costType", attribution.costType); - adjustAttributionMap.put("costAmount", attribution.costAmount != null ? - attribution.costAmount.toString() : ""); - adjustAttributionMap.put("costCurrency", attribution.costCurrency); - adjustAttributionMap.put("fbInstallReferrer", attribution.fbInstallReferrer); - if (attribution.jsonResponse != null) { - adjustAttributionMap.put("jsonResponse", attribution.jsonResponse); - } - result.success(adjustAttributionMap); + private void trackThirdPartySharing(final MethodCall call, final Result result) { + Map thirdPartySharingMap = (Map) call.arguments; + if (thirdPartySharingMap == null) { + return; + } + + Boolean isEnabled = null; + if (thirdPartySharingMap.containsKey("isEnabled")) { + isEnabled = (Boolean) thirdPartySharingMap.get("isEnabled"); + } + + // create third party sharing object + AdjustThirdPartySharing thirdPartySharing = new AdjustThirdPartySharing(isEnabled); + + // granular options + if (thirdPartySharingMap.containsKey("granularOptions")) { + String strGranularOptions = (String) thirdPartySharingMap.get("granularOptions"); + String[] arrayGranularOptions = strGranularOptions.split("__ADJ__", -1); + for (int i = 0; i < arrayGranularOptions.length; i += 3) { + thirdPartySharing.addGranularOption( + arrayGranularOptions[i], + arrayGranularOptions[i+1], + arrayGranularOptions[i+2]); } - }); + } + + // partner sharing settings + if (thirdPartySharingMap.containsKey("partnerSharingSettings")) { + String strPartnerSharingSettings = (String) thirdPartySharingMap.get("partnerSharingSettings"); + String[] arrayPartnerSharingSettings = strPartnerSharingSettings.split("__ADJ__", -1); + for (int i = 0; i < arrayPartnerSharingSettings.length; i += 3) { + thirdPartySharing.addPartnerSharingSetting( + arrayPartnerSharingSettings[i], + arrayPartnerSharingSettings[i+1], + Boolean.parseBoolean(arrayPartnerSharingSettings[i+2])); + } + } + + // track third party sharing + Adjust.trackThirdPartySharing(thirdPartySharing); + result.success(null); } - private void getSdkVersion(final Result result) { - Adjust.getSdkVersion(new OnSdkVersionReadListener (){ + private void trackMeasurementConsent(final MethodCall call, final Result result) { + Map measurementConsentMap = (Map) call.arguments; + if (!measurementConsentMap.containsKey("measurementConsent")) { + result.error("0", "Arguments null or wrong (missing argument of 'trackMeasurementConsent' method.", null); + return; + } + + boolean measurementConsent = (boolean) measurementConsentMap.get("measurementConsent"); + Adjust.trackMeasurementConsent(measurementConsent); + result.success(null); + } + + private void processDeeplink(final MethodCall call, final Result result) { + Map deeplinkMap = (Map) call.arguments; + if (deeplinkMap == null) { + return; + } + + AdjustDeeplink adjustDeeplink = null; + if (deeplinkMap.containsKey("deeplink")) { + String deeplink = (String) deeplinkMap.get("deeplink"); + adjustDeeplink = new AdjustDeeplink(Uri.parse(deeplink)); + if (deeplinkMap.containsKey("referrer")) { + String referrer = (String) deeplinkMap.get("referrer"); + adjustDeeplink.setReferrer(Uri.parse(referrer)); + } + } + + Adjust.processDeeplink(adjustDeeplink, applicationContext); + result.success(null); + } + + private void processAndResolveDeeplink(final MethodCall call, final Result result) { + Map deeplinkMap = (Map) call.arguments; + if (deeplinkMap == null) { + return; + } + + AdjustDeeplink adjustDeeplink = null; + if (deeplinkMap.containsKey("deeplink")) { + String deeplink = (String) deeplinkMap.get("deeplink"); + adjustDeeplink = new AdjustDeeplink(Uri.parse(deeplink)); + if (deeplinkMap.containsKey("referrer")) { + String referrer = (String) deeplinkMap.get("referrer"); + adjustDeeplink.setReferrer(Uri.parse(referrer)); + } + } + + Adjust.processAndResolveDeeplink(adjustDeeplink, applicationContext, new OnDeeplinkResolvedListener() { @Override - public void onSdkVersionRead(String sdkVersion) { - result.success(sdkVersion); + public void onDeeplinkResolved(String resolvedLink) { + result.success(resolvedLink); } }); } - private void setReferrer(final MethodCall call, final Result result) { - String referrer = null; - if (call.hasArgument("referrer")) { - referrer = (String) call.argument("referrer"); + private void setPushToken(final MethodCall call, final Result result) { + Map tokenParamsMap = (Map) call.arguments; + String pushToken = null; + if (tokenParamsMap.containsKey("pushToken")) { + pushToken = tokenParamsMap.get("pushToken").toString(); } - Adjust.setReferrer(referrer, applicationContext); + Adjust.setPushToken(pushToken, applicationContext); + result.success(null); + } + + private void gdprForgetMe(final Result result) { + Adjust.gdprForgetMe(applicationContext); + result.success(null); + } + + private void enable(final Result result) { + Adjust.enable(); + result.success(null); + } + private void disable( final Result result) { + Adjust.disable(); + result.success(null); + } + + private void switchToOfflineMode(final Result result) { + Adjust.switchToOfflineMode(); + result.success(null); + } + + private void switchBackToOnlineMode(final Result result) { + Adjust.switchBackToOnlineMode(); result.success(null); } @@ -813,95 +962,103 @@ private void removeGlobalPartnerParameters(final Result result) { result.success(null); } - private void trackAdRevenue(final MethodCall call, final Result result) { - Map adRevenueMap = (Map) call.arguments; - if (adRevenueMap == null) { - return; - } - - // ad revenue source - String source = null; - if (adRevenueMap.containsKey("source")) { - source = (String) adRevenueMap.get("source"); - } + private void endFirstSessionDelay(final MethodCall call, final Result result) { + Adjust.endFirstSessionDelay(); + } - // create ad revenue object - AdjustAdRevenue adRevenue = new AdjustAdRevenue(source); + private void enableCoppaComplianceInDelay(final MethodCall call, final Result result) { + Adjust.enableCoppaComplianceInDelay(); + } - // revenue and currency - if (adRevenueMap.containsKey("revenue") || adRevenueMap.containsKey("currency")) { - double revenue = -1.0; - String strRevenue = (String) adRevenueMap.get("revenue"); + private void disableCoppaComplianceInDelay(final MethodCall call, final Result result) { + Adjust.disableCoppaComplianceInDelay(); + } - try { - revenue = Double.parseDouble(strRevenue); - String currency = (String) adRevenueMap.get("currency"); - adRevenue.setRevenue(revenue, currency); - } catch (NumberFormatException ignore) {} - } + private void enablePlayStoreKidsComplianceInDelay(final MethodCall call, final Result result) { + Adjust.enablePlayStoreKidsComplianceInDelay(); + } - // ad impressions count - if (adRevenueMap.containsKey("adImpressionsCount")) { - String strAdImpressionsCount = (String) adRevenueMap.get("adImpressionsCount"); - int adImpressionsCount = Integer.parseInt(strAdImpressionsCount); - adRevenue.setAdImpressionsCount(adImpressionsCount); - } + private void disablePlayStoreKidsComplianceInDelay(final MethodCall call, final Result result) { + Adjust.disablePlayStoreKidsComplianceInDelay(); + } - // ad revenue network - if (adRevenueMap.containsKey("adRevenueNetwork")) { - String adRevenueNetwork = (String) adRevenueMap.get("adRevenueNetwork"); - adRevenue.setAdRevenueNetwork(adRevenueNetwork); + private void setExternalDeviceIdInDelay(final MethodCall call, final Result result) { + Map externalDeviceMap = (Map) call.arguments; + String externalDeviceId = null; + if (externalDeviceMap.containsKey("externalDeviceId")) { + externalDeviceId = externalDeviceMap.get("externalDeviceId").toString(); } + Adjust.setExternalDeviceIdInDelay(externalDeviceId); + result.success(null); + } - // ad revenue unit - if (adRevenueMap.containsKey("adRevenueUnit")) { - String adRevenueUnit = (String) adRevenueMap.get("adRevenueUnit"); - adRevenue.setAdRevenueUnit(adRevenueUnit); - } + private void isEnabled(final Result result) { + Adjust.isEnabled(applicationContext, new OnIsEnabledListener() { + @Override + public void onIsEnabledRead(boolean isEnabled) { + result.success(isEnabled); + } + }); + } - // ad revenue placement - if (adRevenueMap.containsKey("adRevenuePlacement")) { - String adRevenuePlacement = (String) adRevenueMap.get("adRevenuePlacement"); - adRevenue.setAdRevenuePlacement(adRevenuePlacement); - } + private void getAdid(final Result result) { + Adjust.getAdid(new OnAdidReadListener() { + @Override + public void onAdidRead(String adid) { + result.success(adid); + } + }); + } - // callback parameters - if (adRevenueMap.containsKey("callbackParameters")) { - String strCallbackParametersJson = (String) adRevenueMap.get("callbackParameters"); - try { - JSONObject jsonCallbackParameters = new JSONObject(strCallbackParametersJson); - JSONArray callbackParametersKeys = jsonCallbackParameters.names(); - for (int i = 0; i < callbackParametersKeys.length(); ++i) { - String key = callbackParametersKeys.getString(i); - String value = jsonCallbackParameters.getString(key); - adRevenue.addCallbackParameter(key, value); + private void getAttribution(final Result result) { + Adjust.getAttribution(new OnAttributionReadListener() { + @Override + public void onAttributionRead(AdjustAttribution attribution) { + HashMap adjustAttributionMap = new HashMap(); + adjustAttributionMap.put("trackerToken", attribution.trackerToken); + adjustAttributionMap.put("trackerName", attribution.trackerName); + adjustAttributionMap.put("network", attribution.network); + adjustAttributionMap.put("campaign", attribution.campaign); + adjustAttributionMap.put("adgroup", attribution.adgroup); + adjustAttributionMap.put("creative", attribution.creative); + adjustAttributionMap.put("clickLabel", attribution.clickLabel); + adjustAttributionMap.put("costType", attribution.costType); + adjustAttributionMap.put("costAmount", attribution.costAmount != null ? + attribution.costAmount.toString() : ""); + adjustAttributionMap.put("costCurrency", attribution.costCurrency); + adjustAttributionMap.put("fbInstallReferrer", attribution.fbInstallReferrer); + if (attribution.jsonResponse != null) { + adjustAttributionMap.put("jsonResponse", attribution.jsonResponse); } - } catch (JSONException e) { - Log.e(TAG, "Failed to parse ad revenue callback parameter! Details: " + e); + result.success(adjustAttributionMap); } - } + }); + } - // partner parameters - if (adRevenueMap.containsKey("partnerParameters")) { - String strPartnerParametersJson = (String) adRevenueMap.get("partnerParameters"); - try { - JSONObject jsonPartnerParameters = new JSONObject(strPartnerParametersJson); - JSONArray partnerParametersKeys = jsonPartnerParameters.names(); - for (int i = 0; i < partnerParametersKeys.length(); ++i) { - String key = partnerParametersKeys.getString(i); - String value = jsonPartnerParameters.getString(key); - adRevenue.addPartnerParameter(key, value); + private void getLastDeeplink(final Result result) { + Adjust.getLastDeeplink(applicationContext, new OnLastDeeplinkReadListener() { + @Override + public void onLastDeeplinkRead(Uri deeplink) { + if (deeplink != null) { + result.success(deeplink.toString()); + } else { + result.success(""); } - } catch (JSONException e) { - Log.e(TAG, "Failed to parse ad revenue partner parameter! Details: " + e); } - } + }); + } - // track ad revenue - Adjust.trackAdRevenue(adRevenue); - result.success(null); + private void getSdkVersion(final Result result) { + Adjust.getSdkVersion(new OnSdkVersionReadListener() { + @Override + public void onSdkVersionRead(String sdkVersion) { + result.success(sdkVersion); + } + }); } + // android only + private void trackPlayStoreSubscription(final MethodCall call, final Result result) { Map subscriptionMap = (Map) call.arguments; if (subscriptionMap == null) { @@ -1000,74 +1157,6 @@ private void trackPlayStoreSubscription(final MethodCall call, final Result resu result.success(null); } - private void trackThirdPartySharing(final MethodCall call, final Result result) { - Map thirdPartySharingMap = (Map) call.arguments; - if (thirdPartySharingMap == null) { - return; - } - - Boolean isEnabled = null; - if (thirdPartySharingMap.containsKey("isEnabled")) { - isEnabled = (Boolean) thirdPartySharingMap.get("isEnabled"); - } - - // create third party sharing object - AdjustThirdPartySharing thirdPartySharing = new AdjustThirdPartySharing(isEnabled); - - // granular options - if (thirdPartySharingMap.containsKey("granularOptions")) { - String strGranularOptions = (String) thirdPartySharingMap.get("granularOptions"); - String[] arrayGranularOptions = strGranularOptions.split("__ADJ__", -1); - for (int i = 0; i < arrayGranularOptions.length; i += 3) { - thirdPartySharing.addGranularOption( - arrayGranularOptions[i], - arrayGranularOptions[i+1], - arrayGranularOptions[i+2]); - } - } - - // partner sharing settings - if (thirdPartySharingMap.containsKey("partnerSharingSettings")) { - String strPartnerSharingSettings = (String) thirdPartySharingMap.get("partnerSharingSettings"); - String[] arrayPartnerSharingSettings = strPartnerSharingSettings.split("__ADJ__", -1); - for (int i = 0; i < arrayPartnerSharingSettings.length; i += 3) { - thirdPartySharing.addPartnerSharingSetting( - arrayPartnerSharingSettings[i], - arrayPartnerSharingSettings[i+1], - Boolean.parseBoolean(arrayPartnerSharingSettings[i+2])); - } - } - - // track third party sharing - Adjust.trackThirdPartySharing(thirdPartySharing); - result.success(null); - } - - private void trackMeasurementConsent(final MethodCall call, final Result result) { - Map measurementConsentMap = (Map) call.arguments; - if (!measurementConsentMap.containsKey("measurementConsent")) { - result.error("0", "Arguments null or wrong (missing argument of 'trackMeasurementConsent' method.", null); - return; - } - - boolean measurementConsent = (boolean) measurementConsentMap.get("measurementConsent"); - Adjust.trackMeasurementConsent(measurementConsent); - result.success(null); - } - - private void getLastDeeplink(final Result result) { - Adjust.getLastDeeplink(applicationContext, new OnLastDeeplinkReadListener() { - @Override - public void onLastDeeplinkRead(Uri deeplink) { - if (deeplink != null) { - result.success(deeplink.toString()); - } else { - result.success(""); - } - } - }); - } - private void verifyPlayStorePurchase(final MethodCall call, final Result result) { Map purchaseMap = (Map) call.arguments; if (purchaseMap == null) { @@ -1199,28 +1288,45 @@ public void onVerificationFinished(AdjustPurchaseVerificationResult verification }); } - private void processAndResolveDeeplink(final MethodCall call, final Result result) { - Map urlParamsMap = (Map) call.arguments; - String url = null; - if (urlParamsMap.containsKey("deeplink")) { - url = urlParamsMap.get("deeplink").toString(); + private void setReferrer(final MethodCall call, final Result result) { + String referrer = null; + if (call.hasArgument("referrer")) { + referrer = (String) call.argument("referrer"); } + Adjust.setReferrer(referrer, applicationContext); + result.success(null); + } - Adjust.processAndResolveDeeplink(new AdjustDeeplink(Uri.parse(url)), applicationContext, new OnDeeplinkResolvedListener() { + private void getGoogleAdId(final Result result) { + Adjust.getGoogleAdId(applicationContext, new OnGoogleAdIdReadListener() { @Override - public void onDeeplinkResolved(String resolvedLink) { - result.success(resolvedLink); + public void onGoogleAdIdRead(String googleAdId) { + result.success(googleAdId); } }); } - // ios only methods - private void getIdfa(final Result result) { - result.success("Error. No getIdfa on Android platform!"); + private void getAmazonAdId(final Result result) { + Adjust.getAmazonAdId(applicationContext, new OnAmazonAdIdReadListener() { + @Override + public void onAmazonAdIdRead(String amazonAdId) { + result.success(amazonAdId); + } + }); } - private void getIdfv(final Result result) { - result.success("Error. No getIdfv on Android platform!"); + // ios only + + private void trackAppStoreSubscription(final Result result) { + result.success("Error. No trackAppStoreSubscription on Android platform!"); + } + + private void verifyAppStorePurchase(final MethodCall call, final Result result) { + result.success("Error. No verifyAppStorePurchase on Android platform!"); + } + + private void verifyAndTrackAppStorePurchase(final MethodCall call, final Result result) { + result.success("Error. No verifyAndTrackAppStorePurchase on Android platform!"); } private void requestAppTrackingAuthorization(final Result result) { @@ -1231,23 +1337,20 @@ private void updateSkanConversionValue(final Result result) { result.success("Error. No updateSkanConversionValue on Android platform!"); } - private void getAppTrackingAuthorizationStatus(final MethodCall call, final Result result) { - result.success(-1); + private void getIdfa(final Result result) { + result.success("Error. No getIdfa on Android platform!"); } - private void trackAppStoreSubscription(final Result result) { - result.success("Error. No trackAppStoreSubscription on Android platform!"); + private void getIdfv(final Result result) { + result.success("Error. No getIdfv on Android platform!"); } - private void verifyAppStorePurchase(final MethodCall call, final Result result) { - result.success("Error. No verifyAppStorePurchase on Android platform!"); + private void getAppTrackingAuthorizationStatus(final MethodCall call, final Result result) { + result.success(-1); } - private void verifyAndTrackAppStorePurchase(final MethodCall call, final Result result) { - result.success("Error. No verifyAndTrackAppStorePurchase on Android platform!"); - } + // testing only - // used for testing only private void onResume(final Result result) { Adjust.onResume(); result.success(null); @@ -1286,11 +1389,6 @@ private void setTestOptions(final MethodCall call, final Result result) { if (testOptionsMap.containsKey("purchaseVerificationPath")) { testOptions.purchaseVerificationPath = (String) testOptionsMap.get("purchaseVerificationPath"); } - // kept for the record - // not needed anymore with test options extraction - // if (testOptionsMap.containsKey("useTestConnectionOptions")) { - // testOptions.useTestConnectionOptions = testOptionsMap.get("useTestConnectionOptions").toString().equals("true"); - // } if (testOptionsMap.containsKey("noBackoffWait")) { testOptions.noBackoffWait = testOptionsMap.get("noBackoffWait").toString().equals("true"); } diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 8919837..6822fae 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -54,5 +54,5 @@ flutter { } dependencies { - implementation 'com.adjust.sdk:adjust-android:5.1.0' + implementation 'com.adjust.sdk:adjust-android:5.4.0' } \ No newline at end of file diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 5679850..ca29ecb 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -51,13 +51,13 @@ 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9D934E022612994B00BDDA0B /* AdServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdServices.framework; path = System/Library/Frameworks/AdServices.framework; sourceTree = SDKROOT; }; + 9DD8A2442DF887F700A682DE /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; 9DF8055A24F9214500A001CE /* iAd.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = iAd.framework; path = System/Library/Frameworks/iAd.framework; sourceTree = SDKROOT; }; 9DF8055C24F9214900A001CE /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; }; 9DF8055E24F9215100A001CE /* AppTrackingTransparency.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppTrackingTransparency.framework; path = System/Library/Frameworks/AppTrackingTransparency.framework; sourceTree = SDKROOT; }; 9DF8056024F9215600A001CE /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; }; 9DF8056224F9215B00A001CE /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; }; E1131B9CA4E134D6F01B8E27 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - E4C0BB812D37D39D005D23F8 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -119,7 +119,7 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( - E4C0BB812D37D39D005D23F8 /* Runner.entitlements */, + 9DD8A2442DF887F700A682DE /* Runner.entitlements */, 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 9050e99..4590184 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -48,6 +48,7 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" + enableGPUValidationMode = "1" allowLocationSimulation = "YES"> diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift index 9fa40f4..a8b1481 100644 --- a/example/ios/Runner/AppDelegate.swift +++ b/example/ios/Runner/AppDelegate.swift @@ -2,7 +2,7 @@ import UIKit import AdjustSdk import Flutter -@UIApplicationMain +@main @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, diff --git a/example/ios/Runner/Runner.entitlements b/example/ios/Runner/Runner.entitlements new file mode 100644 index 0000000..5df5cf7 --- /dev/null +++ b/example/ios/Runner/Runner.entitlements @@ -0,0 +1,12 @@ + + + + + + diff --git a/ios/Classes/AdjustSdk.m b/ios/Classes/AdjustSdk.m index 3a3c395..421ce48 100644 --- a/ios/Classes/AdjustSdk.m +++ b/ios/Classes/AdjustSdk.m @@ -20,6 +20,8 @@ @interface AdjustSdk () @implementation AdjustSdk +#pragma mark - Flutter methods + + (void)registerWithRegistrar:(NSObject *)registrar { FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:CHANNEL_API_NAME binaryMessenger:[registrar messenger]]; @@ -74,6 +76,18 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result [self trackMeasurementConsent:call withResult:result]; } else if ([@"updateSkanConversionValue" isEqualToString:call.method ]){ [self updateSkanConversionValue:call withResult:result]; + } else if ([@"endFirstSessionDelay" isEqualToString:call.method ]){ + [self endFirstSessionDelay:call withResult:result]; + } else if ([@"enableCoppaComplianceInDelay" isEqualToString:call.method ]){ + [self enableCoppaComplianceInDelay:call withResult:result]; + } else if ([@"disableCoppaComplianceInDelay" isEqualToString:call.method ]){ + [self disableCoppaComplianceInDelay:call withResult:result]; + } else if ([@"enablePlayStoreKidsComplianceInDelay" isEqualToString:call.method ]){ + [self enablePlayStoreKidsComplianceInDelay:call withResult:result]; + } else if ([@"disablePlayStoreKidsComplianceInDelay" isEqualToString:call.method ]){ + [self disablePlayStoreKidsComplianceInDelay:call withResult:result]; + } else if ([@"setExternalDeviceIdInDelay" isEqualToString:call.method ]){ + [self setExternalDeviceIdInDelay:call withResult:result]; } else if ([@"addGlobalCallbackParameter" isEqualToString:call.method]) { NSString *key = call.arguments[@"key"]; NSString *value = call.arguments[@"value"]; @@ -141,6 +155,8 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result } } +#pragma mark - Common methods + - (void)initSdk:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSString *appToken = call.arguments[@"appToken"]; NSString *environment = call.arguments[@"environment"]; @@ -156,10 +172,13 @@ - (void)initSdk:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSInteger eventDeduplicationIdsMaxSize = [call.arguments[@"eventDeduplicationIdsMaxSize"] integerValue]; NSString *isCostDataInAttributionEnabled = call.arguments[@"isCostDataInAttributionEnabled"]; NSString *isCoppaComplianceEnabled = call.arguments[@"isCoppaComplianceEnabled"]; + NSString *isFirstSessionDelayEnabled = call.arguments[@"isFirstSessionDelayEnabled"]; + NSString *isAppTrackingTransparencyUsageEnabled = call.arguments[@"isAppTrackingTransparencyUsageEnabled"]; NSString *isLinkMeEnabled = call.arguments[@"isLinkMeEnabled"]; NSString *isAdServicesEnabled = call.arguments[@"isAdServicesEnabled"]; NSString *isIdfaReadingEnabled = call.arguments[@"isIdfaReadingEnabled"]; NSString *isIdfvReadingEnabled = call.arguments[@"isIdfvReadingEnabled"]; + NSString *strStoreInfoJson = call.arguments[@"storeInfo"]; NSString *isSkanAttributionEnabled = call.arguments[@"isSkanAttributionEnabled"]; NSString *isDeviceIdsReadingOnceEnabled = call.arguments[@"isDeviceIdsReadingOnceEnabled"]; NSString *dartAttributionCallback = call.arguments[@"attributionCallback"]; @@ -179,7 +198,6 @@ - (void)initSdk:(FlutterMethodCall *)call withResult:(FlutterResult)result { } } - // create config object ADJConfig *adjustConfig = [[ADJConfig alloc] initWithAppToken:appToken environment:environment suppressLogLevel:allowSuppressLogLevel]; @@ -207,6 +225,20 @@ - (void)initSdk:(FlutterMethodCall *)call withResult:(FlutterResult)result { } } + // first session delay + if ([self isFieldValid:isFirstSessionDelayEnabled]) { + if ([isFirstSessionDelayEnabled boolValue] == YES) { + [adjustConfig enableFirstSessionDelay]; + } + } + + // ATT usage + if ([self isFieldValid:isAppTrackingTransparencyUsageEnabled]) { + if ([isAppTrackingTransparencyUsageEnabled boolValue] == NO) { + [adjustConfig disableAppTrackingTransparencyUsage]; + } + } + // default tracker if ([self isFieldValid:defaultTracker]) { [adjustConfig setDefaultTracker:defaultTracker]; @@ -217,6 +249,23 @@ - (void)initSdk:(FlutterMethodCall *)call withResult:(FlutterResult)result { [adjustConfig setExternalDeviceId:externalDeviceId]; } + // store info + if ([self isFieldValid:strStoreInfoJson]) { + NSData *jsonData = [strStoreInfoJson dataUsingEncoding:NSUTF8StringEncoding]; + NSDictionary *storeInfoDict = [NSJSONSerialization JSONObjectWithData:jsonData + options:0 + error:nil]; + NSString *storeName = storeInfoDict[@"storeName"]; + if ([self isFieldValid:storeName]) { + ADJStoreInfo *adjStoreInfo = [[ADJStoreInfo alloc] initWithStoreName:storeName]; + NSString *storeAppId = storeInfoDict[@"storeAppId"]; + if ([self isFieldValid:storeAppId]) { + [adjStoreInfo setStoreAppId:storeAppId]; + } + [adjustConfig setStoreInfo:adjStoreInfo]; + } + } + // URL strategy if ([self isFieldValid:strUrlStrategyDomainsJson]) { NSData *data = [strUrlStrategyDomainsJson dataUsingEncoding:NSUTF8StringEncoding]; @@ -332,7 +381,7 @@ - (void)trackEvent:(FlutterMethodCall *)call withResult:(FlutterResult)result { [adjustEvent setRevenue:revenueValue currency:currency]; } - // rroduct ID + // product ID if ([self isFieldValid:productId]) { [adjustEvent setProductId:productId]; } @@ -381,51 +430,6 @@ - (void)trackEvent:(FlutterMethodCall *)call withResult:(FlutterResult)result { result(nil); } -- (void)enable:(FlutterMethodCall *)call withResult:(FlutterResult)result { - [Adjust enable]; - result(nil); -} - -- (void)disable:(FlutterMethodCall *)call withResult:(FlutterResult)result { - [Adjust disable]; - result(nil); -} - -- (void)gdprForgetMe:(FlutterMethodCall *)call withResult:(FlutterResult)result { - [Adjust gdprForgetMe]; - result(nil); -} - -- (void)switchToOfflineMode:(FlutterMethodCall *)call withResult:(FlutterResult)result { - [Adjust switchToOfflineMode]; - result(nil); -} - -- (void)switchBackToOnlineMode:(FlutterMethodCall *)call withResult:(FlutterResult)result { - [Adjust switchBackToOnlineMode]; - result(nil); -} - -- (void)setPushToken:(FlutterMethodCall *)call withResult:(FlutterResult)result { - NSString *pushToken = call.arguments[@"pushToken"]; - if ([self isFieldValid:pushToken]) { - [Adjust setPushTokenAsString:pushToken]; - } - result(nil); -} - -- (void)processDeeplink:(FlutterMethodCall *)call withResult:(FlutterResult)result { - NSString *urlString = call.arguments[@"deeplink"]; - if (urlString == nil) { - return; - } - - NSURL *url = [NSURL URLWithString:urlString]; - ADJDeeplink *deeplink = [[ADJDeeplink alloc] initWithDeeplink:url]; - [Adjust processDeeplink:deeplink]; -} - - - (void)trackAdRevenue:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSString *source = call.arguments[@"source"]; NSString *revenue = call.arguments[@"revenue"]; @@ -496,66 +500,141 @@ - (void)trackAdRevenue:(FlutterMethodCall *)call withResult:(FlutterResult)resul result(nil); } -- (void)trackAppStoreSubscription:(FlutterMethodCall *)call withResult:(FlutterResult)result { - NSString *price = call.arguments[@"price"]; - NSString *currency = call.arguments[@"currency"]; - NSString *transactionId = call.arguments[@"transactionId"]; - NSString *transactionDate = call.arguments[@"transactionDate"]; - NSString *salesRegion = call.arguments[@"salesRegion"]; - // NSString *billingStore = call.arguments[@"billingStore"]; - NSString *strCallbackParametersJson = call.arguments[@"callbackParameters"]; - NSString *strPartnerParametersJson = call.arguments[@"partnerParameters"]; +- (void)trackThirdPartySharing:(FlutterMethodCall *)call withResult:(FlutterResult)result { + NSNumber *isEnabled = call.arguments[@"isEnabled"]; + NSString *strGranularOptions = call.arguments[@"granularOptions"]; + NSString *strPartnerSharingSettings = call.arguments[@"partnerSharingSettings"]; - // price - NSDecimalNumber *priceValue; - if ([self isFieldValid:price]) { - priceValue = [NSDecimalNumber decimalNumberWithString:price]; - } + ADJThirdPartySharing *adjustThirdPartySharing = + [[ADJThirdPartySharing alloc] initWithIsEnabled:[self isFieldValid:isEnabled] ? isEnabled : nil]; - // create subscription object - ADJAppStoreSubscription *subscription = - [[ADJAppStoreSubscription alloc] initWithPrice:priceValue - currency:currency - transactionId:transactionId]; + // granular options + if (strGranularOptions != nil) { + NSArray *arrayGranularOptions = [strGranularOptions componentsSeparatedByString:@"__ADJ__"]; + if (arrayGranularOptions != nil) { + for (int i = 0; i < [arrayGranularOptions count]; i += 3) { + [adjustThirdPartySharing addGranularOption:[arrayGranularOptions objectAtIndex:i] + key:[arrayGranularOptions objectAtIndex:i+1] + value:[arrayGranularOptions objectAtIndex:i+2]]; + } + } + } - // transaction date - if ([self isFieldValid:transactionDate]) { - NSTimeInterval transactionDateInterval = [transactionDate doubleValue]; - NSDate *oTransactionDate = [NSDate dateWithTimeIntervalSince1970:transactionDateInterval]; - [subscription setTransactionDate:oTransactionDate]; + // partner sharing settings + if (strPartnerSharingSettings != nil) { + NSArray *arrayPartnerSharingSettings = [strPartnerSharingSettings componentsSeparatedByString:@"__ADJ__"]; + if (arrayPartnerSharingSettings != nil) { + for (int i = 0; i < [arrayPartnerSharingSettings count]; i += 3) { + [adjustThirdPartySharing addPartnerSharingSetting:[arrayPartnerSharingSettings objectAtIndex:i] + key:[arrayPartnerSharingSettings objectAtIndex:i+1] + value:[[arrayPartnerSharingSettings objectAtIndex:i+2] boolValue]]; + } + } } - // sales region - if ([self isFieldValid:salesRegion]) { - [subscription setSalesRegion:salesRegion]; + // track third party sharing + [Adjust trackThirdPartySharing:adjustThirdPartySharing]; + result(nil); +} + +- (void)trackMeasurementConsent:(FlutterMethodCall *)call withResult:(FlutterResult)result { + NSString *measurementConsent = call.arguments[@"measurementConsent"]; + if ([self isFieldValid:measurementConsent]) { + [Adjust trackMeasurementConsent:[measurementConsent boolValue]]; } + result(nil); +} - // callback parameters - if (strCallbackParametersJson != nil) { - NSData *callbackParametersData = [strCallbackParametersJson dataUsingEncoding:NSUTF8StringEncoding]; - id callbackParametersJson = [NSJSONSerialization JSONObjectWithData:callbackParametersData - options:0 - error:NULL]; - for (id key in callbackParametersJson) { - NSString *value = [callbackParametersJson objectForKey:key]; - [subscription addCallbackParameter:key value:value]; +- (void)processDeeplink:(FlutterMethodCall *)call withResult:(FlutterResult)result { + NSString *deeplink = call.arguments[@"deeplink"]; + NSString *referrer = call.arguments[@"referrer"]; + + if ([self isFieldValid:deeplink]) { + NSURL *urlDeeplink = [NSURL URLWithString:deeplink]; + ADJDeeplink *deeplink = [[ADJDeeplink alloc] initWithDeeplink:urlDeeplink]; + if ([self isFieldValid:referrer]) { + NSURL *urlReferrer = [NSURL URLWithString:referrer]; + [deeplink setReferrer:urlReferrer]; } + [Adjust processDeeplink:deeplink]; } +} - // partner parameters - if (strPartnerParametersJson != nil) { - NSData *partnerParametersData = [strPartnerParametersJson dataUsingEncoding:NSUTF8StringEncoding]; - id partnerParametersJson = [NSJSONSerialization JSONObjectWithData:partnerParametersData - options:0 - error:NULL]; - for (id key in partnerParametersJson) { - NSString *value = [partnerParametersJson objectForKey:key]; - [subscription addPartnerParameter:key value:value]; +- (void)processAndResolveDeeplink:(FlutterMethodCall *)call withResult:(FlutterResult)result { + NSString *deeplink = call.arguments[@"deeplink"]; + NSString *referrer = call.arguments[@"referrer"]; + + if ([self isFieldValid:deeplink]) { + NSURL *urlDeeplink = [NSURL URLWithString:deeplink]; + ADJDeeplink *deeplink = [[ADJDeeplink alloc] initWithDeeplink:urlDeeplink]; + if ([self isFieldValid:referrer]) { + NSURL *urlReferrer = [NSURL URLWithString:referrer]; + [deeplink setReferrer:urlReferrer]; } + [Adjust processAndResolveDeeplink:deeplink + withCompletionHandler:^(NSString * _Nullable resolvedLink) { + if (![self isFieldValid:resolvedLink]) { + result(nil); + } else { + result(resolvedLink); + } + }]; } +} - // track subscription - [Adjust trackAppStoreSubscription:subscription]; +- (void)setPushToken:(FlutterMethodCall *)call withResult:(FlutterResult)result { + NSString *pushToken = call.arguments[@"pushToken"]; + if ([self isFieldValid:pushToken]) { + [Adjust setPushTokenAsString:pushToken]; + } + result(nil); +} + +- (void)gdprForgetMe:(FlutterMethodCall *)call withResult:(FlutterResult)result { + [Adjust gdprForgetMe]; + result(nil); +} + +- (void)enable:(FlutterMethodCall *)call withResult:(FlutterResult)result { + [Adjust enable]; + result(nil); +} + +- (void)disable:(FlutterMethodCall *)call withResult:(FlutterResult)result { + [Adjust disable]; + result(nil); +} + +- (void)switchToOfflineMode:(FlutterMethodCall *)call withResult:(FlutterResult)result { + [Adjust switchToOfflineMode]; + result(nil); +} + +- (void)switchBackToOnlineMode:(FlutterMethodCall *)call withResult:(FlutterResult)result { + [Adjust switchBackToOnlineMode]; + result(nil); +} + +- (void)endFirstSessionDelay:(FlutterMethodCall *)call withResult:(FlutterResult)result { + [Adjust endFirstSessionDelay]; + result(nil); +} + +- (void)enableCoppaComplianceInDelay:(FlutterMethodCall *)call withResult:(FlutterResult)result { + [Adjust enableCoppaComplianceInDelay]; + result(nil); +} + +- (void)disableCoppaComplianceInDelay:(FlutterMethodCall *)call withResult:(FlutterResult)result { + [Adjust disableCoppaComplianceInDelay]; + result(nil); +} + +- (void)setExternalDeviceIdInDelay:(FlutterMethodCall *)call withResult:(FlutterResult)result { + NSString *externalDeviceId = call.arguments[@"externalDeviceId"]; + if ([self isFieldValid:externalDeviceId]) { + [Adjust setExternalDeviceIdInDelay:externalDeviceId]; + } result(nil); } @@ -576,8 +655,6 @@ - (void)getAttribution:(FlutterMethodCall *)call withResult:(FlutterResult)resul [self addValueOrEmpty:attribution.costType withKey:@"costType" toDictionary:dictionary]; [self addNumberOrEmpty:attribution.costAmount withKey:@"costAmount" toDictionary:dictionary]; [self addValueOrEmpty:attribution.costCurrency withKey:@"costCurrency" toDictionary:dictionary]; - - // Add nil check before serializing jsonResponse if (attribution.jsonResponse != nil) { NSData *dataJsonResponse = [NSJSONSerialization dataWithJSONObject:attribution.jsonResponse options:0 @@ -593,15 +670,13 @@ - (void)getAttribution:(FlutterMethodCall *)call withResult:(FlutterResult)resul }]; } -- (void)getIdfa:(FlutterMethodCall *)call withResult:(FlutterResult)result { - [Adjust idfaWithCompletionHandler:^(NSString * _Nullable idfa) { - result(idfa); - }]; -} - -- (void)getIdfv:(FlutterMethodCall *)call withResult:(FlutterResult)result { - [Adjust idfvWithCompletionHandler:^(NSString * _Nullable idfv) { - result(idfv); +- (void)getLastDeeplink:(FlutterMethodCall *)call withResult:(FlutterResult)result { + [Adjust lastDeeplinkWithCompletionHandler:^(NSURL * _Nullable lastDeeplink) { + if (![self isFieldValid:lastDeeplink]) { + result(nil); + } else { + result([lastDeeplink absoluteString]); + } }]; } @@ -611,81 +686,75 @@ - (void)getSdkVersion:(FlutterMethodCall *)call withResult:(FlutterResult)result }]; } -- (void)requestAppTrackingAuthorization:(FlutterMethodCall *)call withResult:(FlutterResult)result { - [Adjust requestAppTrackingAuthorizationWithCompletionHandler:^(NSUInteger status) { - result([NSNumber numberWithUnsignedLong:status]); - }]; -} +#pragma mark - iOS only methods -- (void)getAppTrackingAuthorizationStatus:(FlutterMethodCall *)call withResult:(FlutterResult)result { - result([NSNumber numberWithInt:[Adjust appTrackingAuthorizationStatus]]); -} +- (void)trackAppStoreSubscription:(FlutterMethodCall *)call withResult:(FlutterResult)result { + NSString *price = call.arguments[@"price"]; + NSString *currency = call.arguments[@"currency"]; + NSString *transactionId = call.arguments[@"transactionId"]; + NSString *transactionDate = call.arguments[@"transactionDate"]; + NSString *salesRegion = call.arguments[@"salesRegion"]; + NSString *strCallbackParametersJson = call.arguments[@"callbackParameters"]; + NSString *strPartnerParametersJson = call.arguments[@"partnerParameters"]; -- (void)trackThirdPartySharing:(FlutterMethodCall *)call withResult:(FlutterResult)result { - NSNumber *isEnabled = call.arguments[@"isEnabled"]; - NSString *strGranularOptions = call.arguments[@"granularOptions"]; - NSString *strPartnerSharingSettings = call.arguments[@"partnerSharingSettings"]; + // price + NSDecimalNumber *priceValue; + if ([self isFieldValid:price]) { + priceValue = [NSDecimalNumber decimalNumberWithString:price]; + } - // create third party sharing object - ADJThirdPartySharing *adjustThirdPartySharing = [[ADJThirdPartySharing alloc] - initWithIsEnabled:[self isFieldValid:isEnabled] ? isEnabled : nil]; + ADJAppStoreSubscription *subscription = + [[ADJAppStoreSubscription alloc] initWithPrice:priceValue + currency:currency + transactionId:transactionId]; - // granular options - if (strGranularOptions != nil) { - NSArray *arrayGranularOptions = [strGranularOptions componentsSeparatedByString:@"__ADJ__"]; - if (arrayGranularOptions != nil) { - for (int i = 0; i < [arrayGranularOptions count]; i += 3) { - [adjustThirdPartySharing addGranularOption:[arrayGranularOptions objectAtIndex:i] - key:[arrayGranularOptions objectAtIndex:i+1] - value:[arrayGranularOptions objectAtIndex:i+2]]; - } - } + // transaction date + if ([self isFieldValid:transactionDate]) { + NSTimeInterval transactionDateInterval = [transactionDate doubleValue]; + NSDate *oTransactionDate = [NSDate dateWithTimeIntervalSince1970:transactionDateInterval]; + [subscription setTransactionDate:oTransactionDate]; } - // partner sharing settings - if (strPartnerSharingSettings != nil) { - NSArray *arrayPartnerSharingSettings = [strPartnerSharingSettings componentsSeparatedByString:@"__ADJ__"]; - if (arrayPartnerSharingSettings != nil) { - for (int i = 0; i < [arrayPartnerSharingSettings count]; i += 3) { - [adjustThirdPartySharing addPartnerSharingSetting:[arrayPartnerSharingSettings objectAtIndex:i] - key:[arrayPartnerSharingSettings objectAtIndex:i+1] - value:[[arrayPartnerSharingSettings objectAtIndex:i+2] boolValue]]; - } - } + // sales region + if ([self isFieldValid:salesRegion]) { + [subscription setSalesRegion:salesRegion]; } - // track third party sharing - [Adjust trackThirdPartySharing:adjustThirdPartySharing]; - result(nil); -} + // callback parameters + if (strCallbackParametersJson != nil) { + NSData *callbackParametersData = [strCallbackParametersJson dataUsingEncoding:NSUTF8StringEncoding]; + id callbackParametersJson = [NSJSONSerialization JSONObjectWithData:callbackParametersData + options:0 + error:NULL]; + for (id key in callbackParametersJson) { + NSString *value = [callbackParametersJson objectForKey:key]; + [subscription addCallbackParameter:key value:value]; + } + } -- (void)trackMeasurementConsent:(FlutterMethodCall *)call withResult:(FlutterResult)result { - NSString *measurementConsent = call.arguments[@"measurementConsent"]; - if ([self isFieldValid:measurementConsent]) { - [Adjust trackMeasurementConsent:[measurementConsent boolValue]]; + // partner parameters + if (strPartnerParametersJson != nil) { + NSData *partnerParametersData = [strPartnerParametersJson dataUsingEncoding:NSUTF8StringEncoding]; + id partnerParametersJson = [NSJSONSerialization JSONObjectWithData:partnerParametersData + options:0 + error:NULL]; + for (id key in partnerParametersJson) { + NSString *value = [partnerParametersJson objectForKey:key]; + [subscription addPartnerParameter:key value:value]; + } } - result(nil); -} -- (void)updateSkanConversionValue:(FlutterMethodCall *)call withResult:(FlutterResult)result { - NSInteger conversionValue = [call.arguments[@"conversionValue"] integerValue]; - NSString *coarseValue = call.arguments[@"coarseValue"]; - NSNumber *lockWindow = call.arguments[@"lockWindow"]; - [Adjust updateSkanConversionValue:conversionValue - coarseValue:coarseValue - lockWindow:lockWindow - withCompletionHandler:^(NSError * _Nullable error) { - result(error.description); - }]; + // track subscription + [Adjust trackAppStoreSubscription:subscription]; + result(nil); } - (void)verifyAppStorePurchase:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSString *productId = call.arguments[@"productId"]; NSString *transactionId = call.arguments[@"transactionId"]; - // create purchase instance ADJAppStorePurchase *purchase = [[ADJAppStorePurchase alloc] initWithTransactionId:transactionId - productId:productId]; + productId:productId]; // verify purchase [Adjust verifyAppStorePurchase:purchase withCompletionHandler:^(ADJPurchaseVerificationResult * _Nonnull verificationResult) { @@ -707,22 +776,6 @@ - (void)verifyAppStorePurchase:(FlutterMethodCall *)call withResult:(FlutterResu }]; } -- (void)processAndResolveDeeplink:(FlutterMethodCall *)call withResult:(FlutterResult)result { - NSString *deeplink = call.arguments[@"deeplink"]; - if ([self isFieldValid:deeplink]) { - NSURL *nsUrl = [NSURL URLWithString:deeplink]; - ADJDeeplink *deeplink = [[ADJDeeplink alloc] initWithDeeplink:nsUrl]; - [Adjust processAndResolveDeeplink:deeplink - withCompletionHandler:^(NSString * _Nullable resolvedLink) { - if (![self isFieldValid:resolvedLink]) { - result(nil); - } else { - result(resolvedLink); - } - }]; - } -} - - (void)verifyAndTrackAppStorePurchase:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSString *eventToken = call.arguments[@"eventToken"]; NSString *revenue = call.arguments[@"revenue"]; @@ -734,7 +787,6 @@ - (void)verifyAndTrackAppStorePurchase:(FlutterMethodCall *)call withResult:(Flu NSString *strCallbackParametersJson = call.arguments[@"callbackParameters"]; NSString *strPartnerParametersJson = call.arguments[@"partnerParameters"]; - // create event object ADJEvent *adjustEvent = [[ADJEvent alloc] initWithEventToken:eventToken]; // revenue @@ -808,16 +860,78 @@ - (void)verifyAndTrackAppStorePurchase:(FlutterMethodCall *)call withResult:(Flu }]; } -- (void)getLastDeeplink:(FlutterMethodCall *)call withResult:(FlutterResult)result { - [Adjust lastDeeplinkWithCompletionHandler:^(NSURL * _Nullable lastDeeplink) { - if (![self isFieldValid:lastDeeplink]) { - result(nil); - } else { - result([lastDeeplink absoluteString]); - } +- (void)updateSkanConversionValue:(FlutterMethodCall *)call withResult:(FlutterResult)result { + NSInteger conversionValue = [call.arguments[@"conversionValue"] integerValue]; + NSString *coarseValue = call.arguments[@"coarseValue"]; + NSNumber *lockWindow = call.arguments[@"lockWindow"]; + [Adjust updateSkanConversionValue:conversionValue + coarseValue:coarseValue + lockWindow:lockWindow + withCompletionHandler:^(NSError * _Nullable error) { + result(error.description); }]; } +- (void)requestAppTrackingAuthorization:(FlutterMethodCall *)call withResult:(FlutterResult)result { + [Adjust requestAppTrackingAuthorizationWithCompletionHandler:^(NSUInteger status) { + result([NSNumber numberWithUnsignedLong:status]); + }]; +} + +- (void)getIdfa:(FlutterMethodCall *)call withResult:(FlutterResult)result { + [Adjust idfaWithCompletionHandler:^(NSString * _Nullable idfa) { + result(idfa); + }]; +} + +- (void)getIdfv:(FlutterMethodCall *)call withResult:(FlutterResult)result { + [Adjust idfvWithCompletionHandler:^(NSString * _Nullable idfv) { + result(idfv); + }]; +} + +- (void)getAppTrackingAuthorizationStatus:(FlutterMethodCall *)call withResult:(FlutterResult)result { + result([NSNumber numberWithInt:[Adjust appTrackingAuthorizationStatus]]); +} + +#pragma mark - Android only methods + +- (void)getGoogleAdId:(FlutterMethodCall *)call withResult:(FlutterResult)result { + result([FlutterError errorWithCode:@"non_existing_method" + message:@"getGoogleAdId not available on iOS platform!" + details:nil]); +} + +- (void)trackPlayStoreSubscription:(FlutterMethodCall *)call withResult:(FlutterResult)result { + result([FlutterError errorWithCode:@"non_existing_method" + message:@"trackPlayStoreSubscription not available on iOS platform!" + details:nil]); +} + +- (void)verifyPlayStorePurchase:(FlutterMethodCall *)call withResult:(FlutterResult)result { + result([FlutterError errorWithCode:@"non_existing_method" + message:@"verifyPlayStorePurchase not available on iOS platform!" + details:nil]); +} + +- (void)verifyAndTrackPlayStorePurchase:(FlutterMethodCall *)call withResult:(FlutterResult)result { + result([FlutterError errorWithCode:@"non_existing_method" + message:@"verifyAndTrackPlayStorePurchase not available on iOS platform!" + details:nil]); +} + +- (void)enablePlayStoreKidsComplianceInDelay:(FlutterMethodCall *)call withResult:(FlutterResult)result { + result([FlutterError errorWithCode:@"non_existing_method" + message:@"enablePlayStoreKidsComplianceInDelay not available on iOS platform!" + details:nil]); +} + +- (void)disablePlayStoreKidsComplianceInDelay:(FlutterMethodCall *)call withResult:(FlutterResult)result { + result([FlutterError errorWithCode:@"non_existing_method" + message:@"disablePlayStoreKidsComplianceInDelay not available on iOS platform!" + details:nil]); +} + #pragma mark - Testing only methods - (void)setTestOptions:(FlutterMethodCall *)call withResult:(FlutterResult)result { @@ -875,32 +989,6 @@ - (void)setTestOptions:(FlutterMethodCall *)call withResult:(FlutterResult)resul [Adjust setTestOptions:testOptions]; } -#pragma mark - Android only methods - -- (void)getGoogleAdId:(FlutterMethodCall *)call withResult:(FlutterResult)result { - result([FlutterError errorWithCode:@"non_existing_method" - message:@"getGoogleAdId not available on iOS platform!" - details:nil]); -} - -- (void)trackPlayStoreSubscription:(FlutterMethodCall *)call withResult:(FlutterResult)result { - result([FlutterError errorWithCode:@"non_existing_method" - message:@"trackPlayStoreSubscription not available on iOS platform!" - details:nil]); -} - -- (void)verifyPlayStorePurchase:(FlutterMethodCall *)call withResult:(FlutterResult)result { - result([FlutterError errorWithCode:@"non_existing_method" - message:@"verifyPlayStorePurchase not available on iOS platform!" - details:nil]); -} - -- (void)verifyAndTrackPlayStorePurchase:(FlutterMethodCall *)call withResult:(FlutterResult)result { - result([FlutterError errorWithCode:@"non_existing_method" - message:@"verifyAndTrackPlayStorePurchase not available on iOS platform!" - details:nil]); -} - #pragma mark - Utility & helper methods - (BOOL)isFieldValid:(NSObject *)field { diff --git a/ios/adjust_sdk.podspec b/ios/adjust_sdk.podspec index 8e48349..ecba12c 100644 --- a/ios/adjust_sdk.podspec +++ b/ios/adjust_sdk.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'adjust_sdk' - s.version = '5.1.1' + s.version = '5.4.0' s.summary = 'Adjust Flutter SDK for iOS platform' s.description = <<-DESC Adjust Flutter SDK for iOS platform. @@ -14,5 +14,5 @@ Pod::Spec.new do |s| s.ios.deployment_target = '12.0' s.dependency 'Flutter' - s.dependency 'Adjust', '5.1.1' + s.dependency 'Adjust', '5.4.0' end diff --git a/lib/adjust.dart b/lib/adjust.dart index 3dc98e3..52f37e0 100644 --- a/lib/adjust.dart +++ b/lib/adjust.dart @@ -24,10 +24,12 @@ import 'package:flutter/services.dart'; import 'package:meta/meta.dart'; class Adjust { - static const String _sdkPrefix = 'flutter5.1.1'; + static const String _sdkPrefix = 'flutter5.4.0'; static const MethodChannel _channel = const MethodChannel('com.adjust.sdk/api'); + // common + static void initSdk(AdjustConfig config) { config.sdkPrefix = _sdkPrefix; _channel.invokeMethod('initSdk', config.toMap); @@ -37,85 +39,52 @@ class Adjust { _channel.invokeMethod('trackEvent', event.toMap); } - static void enable() { - _channel.invokeMethod('enable'); + static void trackAdRevenue(AdjustAdRevenue adRevenue) { + _channel.invokeMethod('trackAdRevenue', adRevenue.toMap); } - static void disable() { - _channel.invokeMethod('disable'); + static void trackThirdPartySharing( + AdjustThirdPartySharing thirdPartySharing) { + _channel.invokeMethod('trackThirdPartySharing', thirdPartySharing.toMap); } - static void switchToOfflineMode() { - _channel.invokeMethod('switchToOfflineMode'); + static void trackMeasurementConsent(bool measurementConsent) { + _channel.invokeMethod( + 'trackMeasurementConsent', {'measurementConsent': measurementConsent}); } - static void switchBackToOnlineMode() { - _channel.invokeMethod('switchBackToOnlineMode'); + static void processDeeplink(AdjustDeeplink deeplink) { + _channel.invokeMethod('processDeeplink', deeplink.toMap); } - static void setPushToken(String token) { - _channel.invokeMethod('setPushToken', {'pushToken': token}); + static Future processAndResolveDeeplink(AdjustDeeplink deeplink) async { + final resolvedLink = + await _channel.invokeMethod('processAndResolveDeeplink', deeplink.toMap); + return resolvedLink; } - static void processDeeplink(AdjustDeeplink deeplink) { - _channel.invokeMethod('processDeeplink', {'deeplink': deeplink.deeplink}); + static void setPushToken(String token) { + _channel.invokeMethod('setPushToken', {'pushToken': token}); } static void gdprForgetMe() { _channel.invokeMethod('gdprForgetMe'); } - static Future isEnabled() async { - final bool isEnabled = await _channel.invokeMethod('isEnabled'); - return isEnabled; - } - - static Future getAdid() async { - final String? adid = await _channel.invokeMethod('getAdid'); - return adid; - } - - static Future getIdfa() async { - final String? idfa = await _channel.invokeMethod('getIdfa'); - return idfa; - } - - static Future getIdfv() async { - final String? idfv = await _channel.invokeMethod('getIdfv'); - return idfv; - } - - static Future getAmazonAdId() async { - final String? amazonAdId = await _channel.invokeMethod('getAmazonAdId'); - return amazonAdId; - } - - static Future getGoogleAdId() async { - final String? googleAdId = await _channel.invokeMethod('getGoogleAdId'); - return googleAdId; - } - - static Future requestAppTrackingAuthorization() async { - final num status = await _channel - .invokeMethod('requestAppTrackingAuthorization'); - return status; + static void enable() { + _channel.invokeMethod('enable'); } - static Future getAppTrackingAuthorizationStatus() async { - final int authorizationStatus = - await _channel.invokeMethod('getAppTrackingAuthorizationStatus'); - return authorizationStatus; + static void disable() { + _channel.invokeMethod('disable'); } - static Future getAttribution() async { - final dynamic attributionMap = - await _channel.invokeMethod('getAttribution'); - return AdjustAttribution.fromMap(attributionMap); + static void switchToOfflineMode() { + _channel.invokeMethod('switchToOfflineMode'); } - static Future getSdkVersion() async { - final String sdkVersion = await _channel.invokeMethod('getSdkVersion'); - return _sdkPrefix + '@' + sdkVersion; + static void switchBackToOnlineMode() { + _channel.invokeMethod('switchBackToOnlineMode'); } static void addGlobalCallbackParameter(String key, String value) { @@ -144,28 +113,73 @@ class Adjust { _channel.invokeMethod('removeGlobalPartnerParameters'); } - static void trackAdRevenue(AdjustAdRevenue adRevenue) { - _channel.invokeMethod('trackAdRevenue', adRevenue.toMap); + static void endFirstSessionDelay() { + _channel.invokeMethod('endFirstSessionDelay'); + } + + static void enableCoppaComplianceInDelay() { + _channel.invokeMethod('enableCoppaComplianceInDelay'); + } + + static void disableCoppaComplianceInDelay() { + _channel.invokeMethod('disableCoppaComplianceInDelay'); + } + + static void setExternalDeviceIdInDelay(String externalDeviceId) { + _channel.invokeMethod('setExternalDeviceIdInDelay',{'externalDeviceId': externalDeviceId}); + } + + static Future isEnabled() async { + final bool isEnabled = await _channel.invokeMethod('isEnabled'); + return isEnabled; + } + + static Future getAdid() async { + final String? adid = await _channel.invokeMethod('getAdid'); + return adid; + } + + static Future getAttribution() async { + final dynamic attributionMap = + await _channel.invokeMethod('getAttribution'); + return AdjustAttribution.fromMap(attributionMap); + } + + static Future getLastDeeplink() async { + final String? deeplink = await _channel.invokeMethod('getLastDeeplink'); + return deeplink; + } + + static Future getSdkVersion() async { + final String sdkVersion = await _channel.invokeMethod('getSdkVersion'); + return _sdkPrefix + '@' + sdkVersion; } + // ios only + static void trackAppStoreSubscription( AdjustAppStoreSubscription subscription) { _channel.invokeMethod('trackAppStoreSubscription', subscription.toMap); } - static void trackPlayStoreSubscription( - AdjustPlayStoreSubscription subscription) { - _channel.invokeMethod('trackPlayStoreSubscription', subscription.toMap); + static Future verifyAppStorePurchase( + AdjustAppStorePurchase purchase) async { + final dynamic appStorePurchaseMap = + await _channel.invokeMethod('verifyAppStorePurchase', purchase.toMap); + return AdjustPurchaseVerificationResult.fromMap(appStorePurchaseMap); } - static void trackThirdPartySharing( - AdjustThirdPartySharing thirdPartySharing) { - _channel.invokeMethod('trackThirdPartySharing', thirdPartySharing.toMap); + static Future verifyAndTrackAppStorePurchase( + AdjustEvent event) async { + final dynamic appStorePurchaseMap = + await _channel.invokeMethod('verifyAndTrackAppStorePurchase', event.toMap); + return AdjustPurchaseVerificationResult.fromMap(appStorePurchaseMap); } - static void trackMeasurementConsent(bool measurementConsent) { - _channel.invokeMethod( - 'trackMeasurementConsent', {'measurementConsent': measurementConsent}); + static Future requestAppTrackingAuthorization() async { + final num status = await _channel + .invokeMethod('requestAppTrackingAuthorization'); + return status; } static Future updateSkanConversionValue(int conversionValue, String coarseValue, bool lockWindow) async { @@ -177,9 +191,27 @@ class Adjust { return error; } - static Future getLastDeeplink() async { - final String? deeplink = await _channel.invokeMethod('getLastDeeplink'); - return deeplink; + static Future getIdfa() async { + final String? idfa = await _channel.invokeMethod('getIdfa'); + return idfa; + } + + static Future getIdfv() async { + final String? idfv = await _channel.invokeMethod('getIdfv'); + return idfv; + } + + static Future getAppTrackingAuthorizationStatus() async { + final int authorizationStatus = + await _channel.invokeMethod('getAppTrackingAuthorizationStatus'); + return authorizationStatus; + } + + // android only + + static void trackPlayStoreSubscription( + AdjustPlayStoreSubscription subscription) { + _channel.invokeMethod('trackPlayStoreSubscription', subscription.toMap); } static Future verifyPlayStorePurchase( @@ -196,32 +228,26 @@ class Adjust { return AdjustPurchaseVerificationResult.fromMap(playStorePurchaseMap); } - static Future verifyAppStorePurchase( - AdjustAppStorePurchase purchase) async { - final dynamic appStorePurchaseMap = - await _channel.invokeMethod('verifyAppStorePurchase', purchase.toMap); - return AdjustPurchaseVerificationResult.fromMap(appStorePurchaseMap); + static void enablePlayStoreKidsComplianceInDelay() { + _channel.invokeMethod('enablePlayStoreKidsComplianceInDelay'); } - static Future verifyAndTrackAppStorePurchase( - AdjustEvent event) async { - final dynamic appStorePurchaseMap = - await _channel.invokeMethod('verifyAndTrackAppStorePurchase', event.toMap); - return AdjustPurchaseVerificationResult.fromMap(appStorePurchaseMap); + static void disablePlayStoreKidsComplianceInDelay() { + _channel.invokeMethod('disablePlayStoreKidsComplianceInDelay'); } - static Future processAndResolveDeeplink(AdjustDeeplink deeplink) async { - final resolvedLink = - await _channel.invokeMethod('processAndResolveDeeplink', {'deeplink': deeplink.deeplink}); - return resolvedLink; + static Future getAmazonAdId() async { + final String? amazonAdId = await _channel.invokeMethod('getAmazonAdId'); + return amazonAdId; } - // for testing purposes only, do not use in production! - @visibleForTesting - static void setTestOptions(final dynamic testOptions) { - _channel.invokeMethod('setTestOptions', testOptions); + static Future getGoogleAdId() async { + final String? googleAdId = await _channel.invokeMethod('getGoogleAdId'); + return googleAdId; } + // for testing purposes only, do not use in production! + @visibleForTesting static void onResume() { _channel.invokeMethod('onResume'); @@ -231,4 +257,9 @@ class Adjust { static void onPause() { _channel.invokeMethod('onPause'); } + + @visibleForTesting + static void setTestOptions(final dynamic testOptions) { + _channel.invokeMethod('setTestOptions', testOptions); + } } diff --git a/lib/adjust_attribution.dart b/lib/adjust_attribution.dart index 34397a7..055a152 100644 --- a/lib/adjust_attribution.dart +++ b/lib/adjust_attribution.dart @@ -18,7 +18,7 @@ class AdjustAttribution { final num? costAmount; final String? costCurrency; final String? jsonResponse; - // Android only + // android only final String? fbInstallReferrer; AdjustAttribution({ diff --git a/lib/adjust_config.dart b/lib/adjust_config.dart index b27af39..573b767 100644 --- a/lib/adjust_config.dart +++ b/lib/adjust_config.dart @@ -13,6 +13,7 @@ import 'package:adjust_sdk/adjust_event_failure.dart'; import 'package:adjust_sdk/adjust_event_success.dart'; import 'package:adjust_sdk/adjust_session_failure.dart'; import 'package:adjust_sdk/adjust_session_success.dart'; +import 'package:adjust_sdk/adjust_store_info.dart'; import 'package:flutter/services.dart'; enum AdjustLogLevel { verbose, debug, info, warn, error, suppress } @@ -53,6 +54,8 @@ class AdjustConfig { bool? isCoppaComplianceEnabled; bool? isPlayStoreKidsComplianceEnabled; bool? isDeferredDeeplinkOpeningEnabled; + bool? isFirstSessionDelayEnabled; + bool? isAppTrackingTransparencyUsageEnabled; num? attConsentWaitingInterval; num? eventDeduplicationIdsMaxSize; @@ -70,6 +73,7 @@ class AdjustConfig { AdjustLogLevel? logLevel; AttributionCallback? attributionCallback; + AdjustStoreInfo? storeInfo; SessionSuccessCallback? sessionSuccessCallback; SessionFailureCallback? sessionFailureCallback; EventSuccessCallback? eventSuccessCallback; @@ -175,6 +179,9 @@ class AdjustConfig { if (fbAppId != null) { configMap['fbAppId'] = fbAppId; } + if (storeInfo != null) { + configMap['storeInfo'] = json.encode(storeInfo!.toMap); + } if (_urlStrategyDomains.isEmpty != true ) { configMap['urlStrategyDomains'] = json.encode(_urlStrategyDomains); } @@ -202,6 +209,12 @@ class AdjustConfig { if (isCoppaComplianceEnabled != null) { configMap['isCoppaComplianceEnabled'] = isCoppaComplianceEnabled.toString(); } + if (isFirstSessionDelayEnabled != null) { + configMap['isFirstSessionDelayEnabled'] = isFirstSessionDelayEnabled.toString(); + } + if (isAppTrackingTransparencyUsageEnabled != null) { + configMap['isAppTrackingTransparencyUsageEnabled'] = isAppTrackingTransparencyUsageEnabled.toString(); + } if (isDeviceIdsReadingOnceEnabled != null) { configMap['isDeviceIdsReadingOnceEnabled'] = isDeviceIdsReadingOnceEnabled.toString(); } diff --git a/lib/adjust_deeplink.dart b/lib/adjust_deeplink.dart index 4dfb5d2..8c4db04 100644 --- a/lib/adjust_deeplink.dart +++ b/lib/adjust_deeplink.dart @@ -6,8 +6,24 @@ // Copyright (c) 2024-Present Adjust GmbH. All rights reserved. // +import 'dart:convert'; + class AdjustDeeplink { - final String deeplink; + String deeplink; + String? referrer; AdjustDeeplink(this.deeplink); + + Map get toMap { + Map deeplinkMap = new Map(); + + if (deeplink != null) { + deeplinkMap['deeplink'] = deeplink; + } + if (referrer != null) { + deeplinkMap['referrer'] = referrer; + } + + return deeplinkMap; + } } diff --git a/lib/adjust_store_info.dart b/lib/adjust_store_info.dart new file mode 100644 index 0000000..fbcbff2 --- /dev/null +++ b/lib/adjust_store_info.dart @@ -0,0 +1,29 @@ +// +// adjust_deeplink.dart +// Adjust SDK +// +// Created by Mahdi ZTD (@MahdiZTD) on 6th June 2025. +// Copyright (c) 2025-Present Adjust GmbH. All rights reserved. +// + +import 'dart:convert'; + +class AdjustStoreInfo { + String? storeName; + String? storeAppId; + + AdjustStoreInfo(this.storeName); + + Map get toMap { + Map storeInfoMap = new Map(); + + if (storeName != null) { + storeInfoMap['storeName'] = storeName; + } + if (storeAppId != null) { + storeInfoMap['storeAppId'] = storeAppId; + } + + return storeInfoMap; + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 218978c..5e1780f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: adjust_sdk description: This is the Flutter SDK of Adjust™. You can read more about Adjust™ at adjust.com. homepage: https://github.com/adjust/flutter_sdk -version: 5.1.1 +version: 5.4.0 environment: sdk: ">=2.12.0 <3.0.0" diff --git a/test/android/libs/adjust-test-library.jar b/test/android/libs/adjust-test-library.jar index 499f01b..0646551 100644 Binary files a/test/android/libs/adjust-test-library.jar and b/test/android/libs/adjust-test-library.jar differ diff --git a/test/android/libs/adjust-test-options.jar b/test/android/libs/adjust-test-options.jar index 813fdde..e290b14 100644 Binary files a/test/android/libs/adjust-test-options.jar and b/test/android/libs/adjust-test-options.jar differ diff --git a/test/app/lib/command_executor.dart b/test/app/lib/command_executor.dart index d93d275..b710e5a 100644 --- a/test/app/lib/command_executor.dart +++ b/test/app/lib/command_executor.dart @@ -25,6 +25,7 @@ import 'package:adjust_sdk/adjust_session_success.dart'; import 'package:adjust_sdk/adjust_third_party_sharing.dart'; import 'package:adjust_sdk/adjust_purchase_verification_result.dart'; import 'package:adjust_sdk/adjust_deeplink.dart'; +import 'package:adjust_sdk/adjust_store_info.dart'; import 'package:test_app/command.dart'; import 'package:test_lib/test_lib.dart'; @@ -129,6 +130,18 @@ class CommandExecutor { case 'verifyTrack': _verifyTrack(); break; + case 'endFirstSessionDelay': + _endFirstSessionDelay(); + break; + case 'coppaComplianceInDelay': + _coppaComplianceInDelay(); + break; + case 'playStoreKidsComplianceInDelay': + _playStoreKidsComplianceInDelay(); + break; + case 'externalDeviceIdInDelay': + _externalDeviceIdInDelay(); + break; case 'processDeeplink': _processDeeplink(); break; @@ -271,6 +284,23 @@ class CommandExecutor { _savedConfigs.putIfAbsent(configNumber, () => adjustConfig); } + if (_command.containsParameter("storeName") && _command.containsParameter("storeAppId")) + { + var storeName = _command.getFirstParameterValue("storeName"); + var storeAppId = _command.getFirstParameterValue("storeAppId"); + AdjustStoreInfo storeInfo = new AdjustStoreInfo(storeName); + storeInfo.storeAppId = storeAppId; + + adjustConfig!.storeInfo = storeInfo; + } + + if (_command.containsParameter('firstSessionDelayEnabled')) { + if(_command.getFirstParameterValue('firstSessionDelayEnabled') == + 'true'){ + adjustConfig!.isFirstSessionDelayEnabled = true; + } + } + if (_command.containsParameter('logLevel')) { String? logLevelString = _command.getFirstParameterValue('logLevel'); AdjustLogLevel? logLevel; @@ -348,6 +378,12 @@ class CommandExecutor { } } + if (_command.containsParameter('allowAttUsage')) { + if(_command.getFirstParameterValue('allowAttUsage') == 'false') { + adjustConfig!.isAppTrackingTransparencyUsageEnabled = false; + } + } + if (_command.containsParameter('attConsentWaitingSeconds')) { adjustConfig!.attConsentWaitingInterval = double.parse(_command.getFirstParameterValue('attConsentWaitingSeconds')!); @@ -635,7 +671,9 @@ class CommandExecutor { void _openDeeplink() { String deeplink = _command.getFirstParameterValue('deeplink')!; + String? referrer = _command.getFirstParameterValue('referrer'); AdjustDeeplink adjustDeeplink = new AdjustDeeplink(deeplink); + adjustDeeplink!.referrer = referrer; Adjust.processDeeplink(adjustDeeplink); } @@ -940,9 +978,40 @@ class CommandExecutor { _savedEvents.remove(eventNumber); } + void _endFirstSessionDelay(){ + Adjust.endFirstSessionDelay(); + } + + void _coppaComplianceInDelay(){ + bool isEnabled = _command.getFirstParameterValue('isEnabled') == 'true'; + if(isEnabled) { + Adjust.enableCoppaComplianceInDelay(); + }else{ + Adjust.disableCoppaComplianceInDelay(); + } + } + + void _playStoreKidsComplianceInDelay(){ + bool isEnabled = _command.getFirstParameterValue('isEnabled') == 'true'; + if(isEnabled) { + print("enablePlayStoreKidsComplianceInDelay"); + Adjust.enablePlayStoreKidsComplianceInDelay(); + }else{ + print("disablePlayStoreKidsComplianceInDelay"); + Adjust.disablePlayStoreKidsComplianceInDelay(); + } + } + + void _externalDeviceIdInDelay(){ + String externalDeviceId = _command.getFirstParameterValue("externalDeviceId")!; + Adjust.setExternalDeviceIdInDelay(externalDeviceId); + } + void _processDeeplink() { String deeplink = _command.getFirstParameterValue('deeplink')!; + String? referrer = _command.getFirstParameterValue('referrer'); AdjustDeeplink adjustDeeplink = new AdjustDeeplink(deeplink); + adjustDeeplink!.referrer = referrer; Adjust.processAndResolveDeeplink(adjustDeeplink).then((resolvedLink) { String? localBasePath = _basePath; TestLib.addInfoToSend('resolved_link', resolvedLink); diff --git a/test/app/lib/main.dart b/test/app/lib/main.dart index a819d93..e020d0d 100644 --- a/test/app/lib/main.dart +++ b/test/app/lib/main.dart @@ -26,13 +26,13 @@ class _MyAppState extends State { super.initState(); if (Platform.isAndroid) { - String _address = '192.168.86.187'; + String _address = '192.168.86.227'; String _protocol = 'https'; String _port = '8443'; _overwriteUrl = _protocol + '://' + _address + ':' + _port; _controlUrl = 'ws://' + _address + ':1987'; } else { - String _address = '192.168.86.187'; + String _address = '192.168.86.227'; String _protocol = 'http'; String _port = '8080'; _overwriteUrl = _protocol + '://' + _address + ':' + _port; @@ -71,7 +71,7 @@ class _MyAppState extends State { 'Start Test Session', () => Adjust.getSdkVersion().then((sdkVersion) { // TestLib.addTestDirectory('event-callbacks'); - // TestLib.addTest('Test_AttributionGetter_after_install'); + // TestLib.addTest('Test_Parameters_FeatureFlags_present'); TestLib.startTestSession(sdkVersion); })) ]))) diff --git a/test/ios/AdjustTestLibrary.framework/AdjustTestLibrary b/test/ios/AdjustTestLibrary.framework/AdjustTestLibrary index c05ecb0..ace4bee 100644 Binary files a/test/ios/AdjustTestLibrary.framework/AdjustTestLibrary and b/test/ios/AdjustTestLibrary.framework/AdjustTestLibrary differ diff --git a/test/ios/AdjustTestLibrary.framework/Headers/ATLControlSignal.h b/test/ios/AdjustTestLibrary.framework/Headers/ATLControlSignal.h deleted file mode 100644 index 22f0ab7..0000000 --- a/test/ios/AdjustTestLibrary.framework/Headers/ATLControlSignal.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// ATLControlSignal.h -// AdjustTestLibrary -// -// Created by Serj on 20.02.19. -// Copyright © 2019 adjust. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -typedef enum { - ATLSignalTypeInfo = 1, - ATLSignalTypeInitTestSession = 2, - ATLSignalTypeEndWait = 3, - ATLSignalTypeCancelCurrentTest = 4, - ATLSignalTypeUnknown = 5 -} ATLSignalType; - -@interface ATLControlSignal : NSObject - -- (id)initWithSignalType:(ATLSignalType)signalType; - -- (id)initWithSignalType:(ATLSignalType)signalType - andSignalValue:(NSString*)signalValue; - -- (id)initWithJson:(NSString*)json; - -- (NSString*)toJson; - -- (NSString*)getValue; - -- (ATLSignalType)getType; - -@end - -NS_ASSUME_NONNULL_END diff --git a/test/ios/AdjustTestLibrary.framework/Versions/A/AdjustTestLibrary b/test/ios/AdjustTestLibrary.framework/Versions/A/AdjustTestLibrary deleted file mode 100644 index c05ecb0..0000000 Binary files a/test/ios/AdjustTestLibrary.framework/Versions/A/AdjustTestLibrary and /dev/null differ diff --git a/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLBlockingQueue.h b/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLBlockingQueue.h deleted file mode 100644 index d61fddb..0000000 --- a/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLBlockingQueue.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// ATLBlockingQueue.h -// AdjustTestLibrary -// -// Created by Pedro on 11.01.18. -// Copyright © 2018 adjust. All rights reserved. -// - -#import -#import "ATLUtil.h" - -@interface ATLBlockingQueue : NSObject - -/** - * Enqueues an object to the queue. - * @param object Object to enqueue - */ -- (void)enqueue:(id)object; - -/** - * Dequeues an object from the queue. This method will block. - */ -- (id)dequeue; - -- (void)teardown; - -@end diff --git a/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLConstants.h b/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLConstants.h deleted file mode 100644 index 52add01..0000000 --- a/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLConstants.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// ATLConstants.h -// AdjustTestLibrary -// -// Created by Pedro on 20.04.17. -// Copyright © 2017 adjust. All rights reserved. -// - -#ifndef ATLConstants_h -#define ATLConstants_h - -static int const ONE_SECOND = 1000; -static int const ONE_MINUTE = 60 * ONE_SECOND; - -static NSString * const TEST_LIBRARY_CLASSNAME = @"TestLibrary"; -static NSString * const ADJUST_CLASSNAME = @"Adjust"; -static NSString * const WAIT_FOR_CONTROL = @"control"; -static NSString * const WAIT_FOR_SLEEP = @"sleep"; -static NSString * const BASE_PATH_PARAM = @"basePath"; -static NSString * const TEST_NAME_PARAM = @"basePath"; -static NSString * const TEST_SESSION_ID_HEADER = @"Test-Session-Id"; - -// web socket values -static NSString * const SIGNAL_INFO = @"info"; -static NSString * const SIGNAL_INIT_TEST_SESSION = @"init-test-session"; -static NSString * const SIGNAL_END_WAIT = @"end-wait"; -static NSString * const SIGNAL_CANCEL_CURRENT_TEST = @"cancel-current-test"; -static NSString * const SIGNAL_UNKNOWN = @"unknown"; - -#endif /* ATLConstants_h */ diff --git a/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLControlSignal.h b/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLControlSignal.h deleted file mode 100644 index 22f0ab7..0000000 --- a/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLControlSignal.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// ATLControlSignal.h -// AdjustTestLibrary -// -// Created by Serj on 20.02.19. -// Copyright © 2019 adjust. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -typedef enum { - ATLSignalTypeInfo = 1, - ATLSignalTypeInitTestSession = 2, - ATLSignalTypeEndWait = 3, - ATLSignalTypeCancelCurrentTest = 4, - ATLSignalTypeUnknown = 5 -} ATLSignalType; - -@interface ATLControlSignal : NSObject - -- (id)initWithSignalType:(ATLSignalType)signalType; - -- (id)initWithSignalType:(ATLSignalType)signalType - andSignalValue:(NSString*)signalValue; - -- (id)initWithJson:(NSString*)json; - -- (NSString*)toJson; - -- (NSString*)getValue; - -- (ATLSignalType)getType; - -@end - -NS_ASSUME_NONNULL_END diff --git a/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLControlWebSocketClient.h b/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLControlWebSocketClient.h deleted file mode 100644 index 0dd5e21..0000000 --- a/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLControlWebSocketClient.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// ATLControlWebSocketClient.h -// AdjustTestLibrary -// -// Created by Serj on 20.02.19. -// Copyright © 2019 adjust. All rights reserved. -// - -#import -#import "PocketSocket/PSWebSocket.h" -#import "ATLTestLibrary.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface ATLControlWebSocketClient : NSObject - -- (void)initializeWebSocketWithControlUrl:(NSString*)controlUrl - andTestLibrary:(ATLTestLibrary*)testLibrary; - -- (void)reconnectIfNeeded; - -- (void)sendInitTestSessionSignal:(NSString*)testSessionId; - -@end - -NS_ASSUME_NONNULL_END diff --git a/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLNetworking.h b/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLNetworking.h deleted file mode 100644 index 90c2a10..0000000 --- a/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLNetworking.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// ATLNetworking.h -// AdjustTestLibrary -// -// Created by Pedro Silva on 24.05.24. -// Copyright © 2024 adjust. All rights reserved. -// - -#import - -@interface ATLHttpResponse : NSObject - -@property (nonatomic, nullable, strong) NSString * responseString; -@property (nonatomic, nullable, strong) id jsonFoundation; -@property (nonatomic, nullable, strong) NSDictionary *headerFields; -@property (nonatomic, assign) NSInteger statusCode; - -@end - -@interface ATLHttpRequest : NSObject - -@property (nonatomic, nonnull, readonly, strong) NSString *path; -@property (nonatomic, nullable, readonly, strong) NSString *base; -@property (nonatomic, nullable, strong) NSString *bodyString; -@property (nonatomic, nullable, strong) NSDictionary *headerFields; - -- (nonnull id)initWithPath:(nonnull NSString *)path - base:(nullable NSString *)base; -@end - -typedef void (^httpResponseHandler)(ATLHttpResponse *_Nonnull httpResponse); - -@interface ATLNetworking : NSObject - -- (void)sendPostRequestWithData:(nonnull ATLHttpRequest *)requestData - baseUrl:(nonnull NSURL *)baseUrl - responseHandler:(nonnull httpResponseHandler)responseHandler; - -@end diff --git a/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLTestLibrary.h b/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLTestLibrary.h deleted file mode 100644 index 14f763b..0000000 --- a/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLTestLibrary.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// AdjustTestLibrary.h -// AdjustTestLibrary -// -// Created by Pedro on 18.04.17. -// Copyright © 2017 adjust. All rights reserved. -// - -#import -#import "ATLNetworking.h" -#import "ATLBlockingQueue.h" - -@protocol AdjustCommandDelegate -@optional -- (void)executeCommand:(NSString *)className - methodName:(NSString *)methodName - parameters:(NSDictionary *)parameters; - -- (void)executeCommand:(NSString *)className - methodName:(NSString *)methodName - jsonParameters:(NSString *)jsonParameters; - -- (void)executeCommandRawJson:(NSString *)json; -@end - -@interface ATLTestLibrary : NSObject - -- (NSString *)currentBasePath; - -- (ATLBlockingQueue *)waitControlQueue; - -- (void)addTest:(NSString *)testName; - -- (void)addTestDirectory:(NSString *)testDirectory; - -- (void)startTestSession:(NSString *)clientSdk; - -- (void)resetTestLibrary; - -- (void)readResponse:(ATLHttpResponse *)httpResponse; - -- (void)addInfoToSend:(NSString *)key - value:(NSString *)value; - -- (void)sendInfoToServer:(NSString *)basePath; - -- (void)signalEndWaitWithReason:(NSString *)reason; - -- (void)cancelTestAndGetNext; - -- (void)doNotExitAfterEnd; - -+ (ATLTestLibrary *)testLibraryWithBaseUrl:(NSString *)baseUrl - andControlUrl:(NSString *)controlUrl - andCommandDelegate:(NSObject *)commandDelegate; -@end diff --git a/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLUtil.h b/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLUtil.h deleted file mode 100644 index cffe946..0000000 --- a/test/ios/AdjustTestLibrary.framework/Versions/A/Headers/ATLUtil.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// ATLUtil.h -// AdjustTestLibrary -// -// Created by Pedro on 18.04.17. -// Copyright © 2017 adjust. All rights reserved. -// - -#import - -typedef void (^selfInjectedBlock)(id); -typedef void (^operationBlock)(NSBlockOperation *); - -@interface ATLUtil : NSObject - -+ (void)debug:(NSString *)format, ...; -+ (void)launchInQueue:(dispatch_queue_t)queue - selfInject:(id)selfInject - block:(selfInjectedBlock)block; -+ (void)addOperationAfterLast:(NSOperationQueue *)operationQueue - block:(dispatch_block_t)block; -+ (void)addOperationAfterLast:(NSOperationQueue *)operationQueue - blockWithOperation:(operationBlock)blockWithOperation; -+ (BOOL)isNull:(id)value; -+ (NSString *)adjTrim:(NSString *)value; -+ (NSString *)formatDate:(NSDate *)value; -+ (NSString *)parseDictionaryToJsonString:(NSDictionary *) dictionary; -+ (NSString *)appendBasePath:(NSString *)basePath path:(NSString *)path; -+ (NSString *)queryString:(NSDictionary *)parameters; -@end diff --git a/test/ios/AdjustTestLibrary.framework/Versions/Current/AdjustTestLibrary b/test/ios/AdjustTestLibrary.framework/Versions/Current/AdjustTestLibrary deleted file mode 100644 index c05ecb0..0000000 Binary files a/test/ios/AdjustTestLibrary.framework/Versions/Current/AdjustTestLibrary and /dev/null differ diff --git a/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLBlockingQueue.h b/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLBlockingQueue.h deleted file mode 100644 index d61fddb..0000000 --- a/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLBlockingQueue.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// ATLBlockingQueue.h -// AdjustTestLibrary -// -// Created by Pedro on 11.01.18. -// Copyright © 2018 adjust. All rights reserved. -// - -#import -#import "ATLUtil.h" - -@interface ATLBlockingQueue : NSObject - -/** - * Enqueues an object to the queue. - * @param object Object to enqueue - */ -- (void)enqueue:(id)object; - -/** - * Dequeues an object from the queue. This method will block. - */ -- (id)dequeue; - -- (void)teardown; - -@end diff --git a/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLConstants.h b/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLConstants.h deleted file mode 100644 index 52add01..0000000 --- a/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLConstants.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// ATLConstants.h -// AdjustTestLibrary -// -// Created by Pedro on 20.04.17. -// Copyright © 2017 adjust. All rights reserved. -// - -#ifndef ATLConstants_h -#define ATLConstants_h - -static int const ONE_SECOND = 1000; -static int const ONE_MINUTE = 60 * ONE_SECOND; - -static NSString * const TEST_LIBRARY_CLASSNAME = @"TestLibrary"; -static NSString * const ADJUST_CLASSNAME = @"Adjust"; -static NSString * const WAIT_FOR_CONTROL = @"control"; -static NSString * const WAIT_FOR_SLEEP = @"sleep"; -static NSString * const BASE_PATH_PARAM = @"basePath"; -static NSString * const TEST_NAME_PARAM = @"basePath"; -static NSString * const TEST_SESSION_ID_HEADER = @"Test-Session-Id"; - -// web socket values -static NSString * const SIGNAL_INFO = @"info"; -static NSString * const SIGNAL_INIT_TEST_SESSION = @"init-test-session"; -static NSString * const SIGNAL_END_WAIT = @"end-wait"; -static NSString * const SIGNAL_CANCEL_CURRENT_TEST = @"cancel-current-test"; -static NSString * const SIGNAL_UNKNOWN = @"unknown"; - -#endif /* ATLConstants_h */ diff --git a/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLControlSignal.h b/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLControlSignal.h deleted file mode 100644 index 22f0ab7..0000000 --- a/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLControlSignal.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// ATLControlSignal.h -// AdjustTestLibrary -// -// Created by Serj on 20.02.19. -// Copyright © 2019 adjust. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -typedef enum { - ATLSignalTypeInfo = 1, - ATLSignalTypeInitTestSession = 2, - ATLSignalTypeEndWait = 3, - ATLSignalTypeCancelCurrentTest = 4, - ATLSignalTypeUnknown = 5 -} ATLSignalType; - -@interface ATLControlSignal : NSObject - -- (id)initWithSignalType:(ATLSignalType)signalType; - -- (id)initWithSignalType:(ATLSignalType)signalType - andSignalValue:(NSString*)signalValue; - -- (id)initWithJson:(NSString*)json; - -- (NSString*)toJson; - -- (NSString*)getValue; - -- (ATLSignalType)getType; - -@end - -NS_ASSUME_NONNULL_END diff --git a/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLControlWebSocketClient.h b/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLControlWebSocketClient.h deleted file mode 100644 index 0dd5e21..0000000 --- a/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLControlWebSocketClient.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// ATLControlWebSocketClient.h -// AdjustTestLibrary -// -// Created by Serj on 20.02.19. -// Copyright © 2019 adjust. All rights reserved. -// - -#import -#import "PocketSocket/PSWebSocket.h" -#import "ATLTestLibrary.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface ATLControlWebSocketClient : NSObject - -- (void)initializeWebSocketWithControlUrl:(NSString*)controlUrl - andTestLibrary:(ATLTestLibrary*)testLibrary; - -- (void)reconnectIfNeeded; - -- (void)sendInitTestSessionSignal:(NSString*)testSessionId; - -@end - -NS_ASSUME_NONNULL_END diff --git a/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLNetworking.h b/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLNetworking.h deleted file mode 100644 index 90c2a10..0000000 --- a/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLNetworking.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// ATLNetworking.h -// AdjustTestLibrary -// -// Created by Pedro Silva on 24.05.24. -// Copyright © 2024 adjust. All rights reserved. -// - -#import - -@interface ATLHttpResponse : NSObject - -@property (nonatomic, nullable, strong) NSString * responseString; -@property (nonatomic, nullable, strong) id jsonFoundation; -@property (nonatomic, nullable, strong) NSDictionary *headerFields; -@property (nonatomic, assign) NSInteger statusCode; - -@end - -@interface ATLHttpRequest : NSObject - -@property (nonatomic, nonnull, readonly, strong) NSString *path; -@property (nonatomic, nullable, readonly, strong) NSString *base; -@property (nonatomic, nullable, strong) NSString *bodyString; -@property (nonatomic, nullable, strong) NSDictionary *headerFields; - -- (nonnull id)initWithPath:(nonnull NSString *)path - base:(nullable NSString *)base; -@end - -typedef void (^httpResponseHandler)(ATLHttpResponse *_Nonnull httpResponse); - -@interface ATLNetworking : NSObject - -- (void)sendPostRequestWithData:(nonnull ATLHttpRequest *)requestData - baseUrl:(nonnull NSURL *)baseUrl - responseHandler:(nonnull httpResponseHandler)responseHandler; - -@end diff --git a/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLTestLibrary.h b/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLTestLibrary.h deleted file mode 100644 index 14f763b..0000000 --- a/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLTestLibrary.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// AdjustTestLibrary.h -// AdjustTestLibrary -// -// Created by Pedro on 18.04.17. -// Copyright © 2017 adjust. All rights reserved. -// - -#import -#import "ATLNetworking.h" -#import "ATLBlockingQueue.h" - -@protocol AdjustCommandDelegate -@optional -- (void)executeCommand:(NSString *)className - methodName:(NSString *)methodName - parameters:(NSDictionary *)parameters; - -- (void)executeCommand:(NSString *)className - methodName:(NSString *)methodName - jsonParameters:(NSString *)jsonParameters; - -- (void)executeCommandRawJson:(NSString *)json; -@end - -@interface ATLTestLibrary : NSObject - -- (NSString *)currentBasePath; - -- (ATLBlockingQueue *)waitControlQueue; - -- (void)addTest:(NSString *)testName; - -- (void)addTestDirectory:(NSString *)testDirectory; - -- (void)startTestSession:(NSString *)clientSdk; - -- (void)resetTestLibrary; - -- (void)readResponse:(ATLHttpResponse *)httpResponse; - -- (void)addInfoToSend:(NSString *)key - value:(NSString *)value; - -- (void)sendInfoToServer:(NSString *)basePath; - -- (void)signalEndWaitWithReason:(NSString *)reason; - -- (void)cancelTestAndGetNext; - -- (void)doNotExitAfterEnd; - -+ (ATLTestLibrary *)testLibraryWithBaseUrl:(NSString *)baseUrl - andControlUrl:(NSString *)controlUrl - andCommandDelegate:(NSObject *)commandDelegate; -@end diff --git a/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLUtil.h b/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLUtil.h deleted file mode 100644 index cffe946..0000000 --- a/test/ios/AdjustTestLibrary.framework/Versions/Current/Headers/ATLUtil.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// ATLUtil.h -// AdjustTestLibrary -// -// Created by Pedro on 18.04.17. -// Copyright © 2017 adjust. All rights reserved. -// - -#import - -typedef void (^selfInjectedBlock)(id); -typedef void (^operationBlock)(NSBlockOperation *); - -@interface ATLUtil : NSObject - -+ (void)debug:(NSString *)format, ...; -+ (void)launchInQueue:(dispatch_queue_t)queue - selfInject:(id)selfInject - block:(selfInjectedBlock)block; -+ (void)addOperationAfterLast:(NSOperationQueue *)operationQueue - block:(dispatch_block_t)block; -+ (void)addOperationAfterLast:(NSOperationQueue *)operationQueue - blockWithOperation:(operationBlock)blockWithOperation; -+ (BOOL)isNull:(id)value; -+ (NSString *)adjTrim:(NSString *)value; -+ (NSString *)formatDate:(NSDate *)value; -+ (NSString *)parseDictionaryToJsonString:(NSDictionary *) dictionary; -+ (NSString *)appendBasePath:(NSString *)basePath path:(NSString *)path; -+ (NSString *)queryString:(NSDictionary *)parameters; -@end diff --git a/test/ios/test_lib.podspec b/test/ios/test_lib.podspec index d403a84..d5b9efc 100644 --- a/test/ios/test_lib.podspec +++ b/test/ios/test_lib.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'test_lib' - s.version = '5.1.1' + s.version = '5.4.0' s.summary = 'Adjust test library for iOS platform' s.description = <<-DESC Adjust test library for iOS platform. diff --git a/test/pubspec.yaml b/test/pubspec.yaml index ee9988c..521c9b4 100644 --- a/test/pubspec.yaml +++ b/test/pubspec.yaml @@ -1,6 +1,6 @@ name: test_lib description: Flutter plugin for Adjust Testing Library. Intended exclusively for internal use. -version: 5.1.1 +version: 5.4.0 author: Adjust (sdk@adjust.com) environment: