From 440f9212d833b0562060582217e57bfe6955527f Mon Sep 17 00:00:00 2001 From: uerceg Date: Mon, 4 Sep 2023 09:41:30 +0200 Subject: [PATCH 01/16] build: update native dependencies --- android/build.gradle | 2 +- ios/adjust_sdk.podspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 654bd39..dfe380d 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -36,5 +36,5 @@ android { } dependencies { - api 'com.adjust.sdk:adjust-android:4.33.3' + api 'com.adjust.sdk:adjust-android:4.34.0' } diff --git a/ios/adjust_sdk.podspec b/ios/adjust_sdk.podspec index 744a797..9f69bc2 100644 --- a/ios/adjust_sdk.podspec +++ b/ios/adjust_sdk.podspec @@ -14,5 +14,5 @@ Pod::Spec.new do |s| s.ios.deployment_target = '8.0' s.dependency 'Flutter' - s.dependency 'Adjust', '4.33.4' + s.dependency 'Adjust', '4.34.1' end From 3954ca5ad6785e46c2369505b1d02745d05bdf88 Mon Sep 17 00:00:00 2001 From: uerceg Date: Mon, 4 Sep 2023 09:44:44 +0200 Subject: [PATCH 02/16] feat: update version number to 4.34.0 --- README.md | 2 +- VERSION | 2 +- ios/adjust_sdk.podspec | 2 +- lib/adjust.dart | 2 +- pubspec.yaml | 2 +- test/ios/test_lib.podspec | 2 +- test/pubspec.yaml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d5b0d4a..9d0073c 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ You can add Adjust SDK to your Flutter app by adding following to your `pubspec. ```yaml dependencies: - adjust_sdk: ^4.33.1 + adjust_sdk: ^4.34.0 ``` Then navigate to your project in the terminal and run: diff --git a/VERSION b/VERSION index deeeec6..b6a2358 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.33.1 +4.34.0 diff --git a/ios/adjust_sdk.podspec b/ios/adjust_sdk.podspec index 9f69bc2..8311077 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 = '4.33.1' + s.version = '4.34.0' s.summary = 'Adjust Flutter SDK for iOS platform' s.description = <<-DESC Adjust Flutter SDK for iOS platform. diff --git a/lib/adjust.dart b/lib/adjust.dart index f142a9a..64e95df 100644 --- a/lib/adjust.dart +++ b/lib/adjust.dart @@ -19,7 +19,7 @@ import 'package:flutter/services.dart'; import 'package:meta/meta.dart'; class Adjust { - static const String _sdkPrefix = 'flutter4.33.1'; + static const String _sdkPrefix = 'flutter4.34.0'; static const MethodChannel _channel = const MethodChannel('com.adjust.sdk/api'); diff --git a/pubspec.yaml b/pubspec.yaml index d5f39ab..710b748 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: 4.33.1 +version: 4.34.0 environment: sdk: ">=2.12.0 <3.0.0" diff --git a/test/ios/test_lib.podspec b/test/ios/test_lib.podspec index ab6c42d..891906f 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 = '4.33.1' + s.version = '4.34.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 2ffc803..739131e 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: 4.33.1 +version: 4.34.0 author: Adjust (sdk@adjust.com) environment: From 0f0f51a6ed207b1d941e73c8b012a0154b469e18 Mon Sep 17 00:00:00 2001 From: uerceg Date: Mon, 4 Sep 2023 09:50:49 +0200 Subject: [PATCH 03/16] fix: update cupertino_icons version of the example app (null safety) --- example/android/build.gradle | 2 +- example/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/example/android/build.gradle b/example/android/build.gradle index cba6c84..859edc8 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -26,6 +26,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 87bc3dc..e73f09c 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -29,7 +29,7 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^0.1.3 + cupertino_icons: ^1.0.0 dev_dependencies: flutter_test: From 01abc0b8143c7f3b860bd46f3037aee8814afce8 Mon Sep 17 00:00:00 2001 From: uerceg Date: Mon, 4 Sep 2023 10:36:06 +0200 Subject: [PATCH 04/16] build: update gradle and compileSdkVersion versions for android plugin --- android/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index dfe380d..fbc3570 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath('com.android.tools.build:gradle:7.1.1') + classpath('com.android.tools.build:gradle:7.1.3') } } rootProject.allprojects { @@ -24,7 +24,7 @@ rootProject.allprojects { } apply plugin: 'com.android.library' android { - compileSdkVersion 31 + compileSdkVersion 33 defaultConfig { minSdkVersion 16 From 90bfac5e5d520ab289519cb2c4f789115ed06aaf Mon Sep 17 00:00:00 2001 From: uerceg Date: Mon, 4 Sep 2023 10:36:34 +0200 Subject: [PATCH 05/16] build: make example android app to use gradle 8 --- example/android/app/build.gradle | 5 +++-- example/android/app/src/debug/AndroidManifest.xml | 3 +-- example/android/app/src/main/AndroidManifest.xml | 3 +-- example/android/app/src/profile/AndroidManifest.xml | 3 +-- example/android/build.gradle | 4 ++-- example/android/gradle/wrapper/gradle-wrapper.properties | 6 +++--- 6 files changed, 11 insertions(+), 13 deletions(-) diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 546eb71..f4dbb7b 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 32 + compileSdkVersion 33 sourceSets { main.java.srcDirs += 'src/main/kotlin' @@ -36,7 +36,7 @@ android { defaultConfig { applicationId "com.adjust.examples" minSdkVersion 16 - targetSdkVersion 32 + targetSdkVersion 33 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } @@ -52,6 +52,7 @@ android { checkReleaseBuilds false disable 'InvalidPackage' } + namespace 'com.adjust.examples' } flutter { diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml index 15de6bd..f880684 100644 --- a/example/android/app/src/debug/AndroidManifest.xml +++ b/example/android/app/src/debug/AndroidManifest.xml @@ -1,5 +1,4 @@ - + diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 8c7eb34..de76e07 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,4 @@ - + diff --git a/example/android/build.gradle b/example/android/build.gradle index 859edc8..34d0a89 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.6.10' + ext.kotlin_version = '1.7.10' repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.1.1' + classpath 'com.android.tools.build:gradle:8.1.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index 668579c..dea44d0 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Aug 28 12:41:30 CEST 2020 +#Mon Sep 04 10:30:21 CEST 2023 distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip +zipStoreBase=GRADLE_USER_HOME From 180f75019b0fd59ea486d85f0bc416dc28424334 Mon Sep 17 00:00:00 2001 From: uerceg Date: Mon, 4 Sep 2023 10:39:37 +0200 Subject: [PATCH 06/16] build: make flutter cli understand which jdk to be used --- example/android/gradle.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/example/android/gradle.properties b/example/android/gradle.properties index 94adc3a..dfff1c8 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -1,3 +1,4 @@ org.gradle.jvmargs=-Xmx1536M android.useAndroidX=true android.enableJetifier=true +org.gradle.java.home=/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home From 565343c8590906a04fa62dd81325f32644fea958 Mon Sep 17 00:00:00 2001 From: uerceg Date: Mon, 4 Sep 2023 11:07:27 +0200 Subject: [PATCH 07/16] feat: make android pluggin gradle 8.0+ friendly --- android/build.gradle | 1 + android/src/main/AndroidManifest.xml | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index fbc3570..f3c7b7f 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -33,6 +33,7 @@ android { lintOptions { disable 'InvalidPackage' } + namespace 'com.adjust.sdk.flutter' } dependencies { diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 72a37b8..a2f47b6 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,3 +1,2 @@ - + From 3ddf0aec98d5d4a37f4ab8deb498c609419a31e0 Mon Sep 17 00:00:00 2001 From: uerceg Date: Mon, 4 Sep 2023 15:59:59 +0200 Subject: [PATCH 08/16] feat: add play store purchase verification feature --- .../com/adjust/sdk/flutter/AdjustSdk.java | 46 +++++++++++++++++ lib/adjust.dart | 10 ++++ lib/adjust_play_store_purchase.dart | 27 ++++++++++ lib/adjust_purchase_verification_info.dart | 50 +++++++++++++++++++ test/app/android/build.gradle | 2 +- test/app/lib/command_executor.dart | 37 +++++++++++++- test/app/lib/main.dart | 7 ++- test/app/pubspec.yaml | 2 +- 8 files changed, 176 insertions(+), 5 deletions(-) create mode 100644 lib/adjust_play_store_purchase.dart create mode 100644 lib/adjust_purchase_verification_info.dart 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 0dd50ad..8cda8a8 100644 --- a/android/src/main/java/com/adjust/sdk/flutter/AdjustSdk.java +++ b/android/src/main/java/com/adjust/sdk/flutter/AdjustSdk.java @@ -22,6 +22,8 @@ import com.adjust.sdk.AdjustSessionFailure; import com.adjust.sdk.AdjustSessionSuccess; import com.adjust.sdk.AdjustPlayStoreSubscription; +import com.adjust.sdk.AdjustPurchase; +import com.adjust.sdk.AdjustPurchaseVerificationResult; import com.adjust.sdk.AdjustThirdPartySharing; import com.adjust.sdk.AdjustTestOptions; import com.adjust.sdk.LogLevel; @@ -32,6 +34,7 @@ import com.adjust.sdk.OnEventTrackingSucceededListener; import com.adjust.sdk.OnSessionTrackingFailedListener; import com.adjust.sdk.OnSessionTrackingSucceededListener; +import com.adjust.sdk.OnPurchaseVerificationFinishedListener; import org.json.JSONArray; import org.json.JSONException; @@ -204,6 +207,9 @@ public void onMethodCall(MethodCall call, final Result result) { case "getLastDeeplink": getLastDeeplink(call, result); break; + case "verifyPlayStorePurchase": + verifyPlayStorePurchase(call, result); + break; case "setTestOptions": setTestOptions(call, result); break; @@ -1104,6 +1110,40 @@ private void getLastDeeplink(final MethodCall call, final Result result) { result.success("Error. No getLastDeeplink for Android platform!"); } + private void verifyPlayStorePurchase(final MethodCall call, final Result result) { + Map purchaseMap = (Map) call.arguments; + if (purchaseMap == null) { + return; + } + + // Product ID. + String productId = null; + if (purchaseMap.containsKey("productId")) { + productId = (String) purchaseMap.get("productId"); + } + + // Purchase token. + String purchaseToken = null; + if (purchaseMap.containsKey("purchaseToken")) { + purchaseToken = (String) purchaseMap.get("purchaseToken"); + } + + // Create purchase instance. + AdjustPurchase purchase = new AdjustPurchase(productId, purchaseToken); + + // Verify purchase. + Adjust.verifyPurchase(purchase, new OnPurchaseVerificationFinishedListener() { + @Override + public void onVerificationFinished(AdjustPurchaseVerificationResult verificationResult) { + HashMap adjustPurchaseMap = new HashMap(); + adjustPurchaseMap.put("code", String.valueOf(verificationResult.getCode())); + adjustPurchaseMap.put("verificationStatus", verificationResult.getVerificationStatus()); + adjustPurchaseMap.put("message", verificationResult.getMessage()); + result.success(adjustPurchaseMap); + } + }); + } + private void setTestOptions(final MethodCall call, final Result result) { AdjustTestOptions testOptions = new AdjustTestOptions(); Map testOptionsMap = (Map) call.arguments; @@ -1117,6 +1157,9 @@ private void setTestOptions(final MethodCall call, final Result result) { if (testOptionsMap.containsKey("subscriptionUrl")) { testOptions.subscriptionUrl = (String) testOptionsMap.get("subscriptionUrl"); } + if (testOptionsMap.containsKey("purchaseVerificationUrl")) { + testOptions.purchaseVerificationUrl = (String) testOptionsMap.get("purchaseVerificationUrl"); + } if (testOptionsMap.containsKey("basePath")) { testOptions.basePath = (String) testOptionsMap.get("basePath"); } @@ -1126,6 +1169,9 @@ private void setTestOptions(final MethodCall call, final Result result) { if (testOptionsMap.containsKey("subscriptionPath")) { testOptions.subscriptionPath = (String) testOptionsMap.get("subscriptionPath"); } + 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"); diff --git a/lib/adjust.dart b/lib/adjust.dart index 64e95df..18d2a5d 100644 --- a/lib/adjust.dart +++ b/lib/adjust.dart @@ -13,8 +13,11 @@ import 'package:adjust_sdk/adjust_app_store_subscription.dart'; import 'package:adjust_sdk/adjust_attribution.dart'; import 'package:adjust_sdk/adjust_config.dart'; import 'package:adjust_sdk/adjust_event.dart'; +import 'package:adjust_sdk/adjust_play_store_purchase.dart'; import 'package:adjust_sdk/adjust_play_store_subscription.dart'; +import 'package:adjust_sdk/adjust_purchase_verification_info.dart'; import 'package:adjust_sdk/adjust_third_party_sharing.dart'; + import 'package:flutter/services.dart'; import 'package:meta/meta.dart'; @@ -206,6 +209,13 @@ class Adjust { return error; } + static Future verifyPlayStorePurchase( + AdjustPlayStorePurchase purchase) async { + final dynamic playStorePurchaseMap = + await _channel.invokeMethod('verifyPlayStorePurchase', purchase.toMap); + return AdjustPurchaseVerificationInfo.fromMap(playStorePurchaseMap); + } + // For testing purposes only. Do not use in production. @visibleForTesting static void setTestOptions(final dynamic testOptions) { diff --git a/lib/adjust_play_store_purchase.dart b/lib/adjust_play_store_purchase.dart new file mode 100644 index 0000000..33c8c54 --- /dev/null +++ b/lib/adjust_play_store_purchase.dart @@ -0,0 +1,27 @@ +// +// adjust_play_store_purchase.dart +// Adjust SDK +// +// Created by Ugljesa Erceg (@uerceg) on 4th September 2023. +// Copyright (c) 2020-Present Adjust GmbH. All rights reserved. +// + +class AdjustPlayStorePurchase { + String? productId; + String? purchaseToken; + + AdjustPlayStorePurchase(this.productId, this.purchaseToken); + + Map get toMap { + Map purchaseMap = new Map(); + + if (productId != null) { + purchaseMap['productId'] = productId; + } + if (purchaseToken != null) { + purchaseMap['purchaseToken'] = purchaseToken; + } + + return purchaseMap; + } +} diff --git a/lib/adjust_purchase_verification_info.dart b/lib/adjust_purchase_verification_info.dart new file mode 100644 index 0000000..3a9a828 --- /dev/null +++ b/lib/adjust_purchase_verification_info.dart @@ -0,0 +1,50 @@ +// +// adjust_purchase_verification_info.dart +// Adjust SDK +// +// Created by Ugljesa Erceg (@uerceg) on 4th September 2020. +// Copyright (c) 2020-Present Adjust GmbH. All rights reserved. +// + +import 'dart:convert'; + +class AdjustPurchaseVerificationInfo { + final num? code; + final String? message; + final String? verificationStatus; + + AdjustPurchaseVerificationInfo(this.code, this.message, this.verificationStatus); + + factory AdjustPurchaseVerificationInfo.fromMap(dynamic map) { + try { + int parsedCode = -1; + try { + if (map['code'] != null) { + parsedCode = int.parse(map['code']); + } + } catch (ex) {} + + return AdjustPurchaseVerificationInfo(parsedCode, map['message'], map['verificationStatus']); + } catch (e) { + throw Exception( + '[AdjustFlutter]: Failed to create AdjustPurchaseVerificationInfo object from given map object. Details: ' + + e.toString()); + } + } + + Map get toMap { + Map verificationInfoMap = new Map(); + + if (code != null) { + verificationInfoMap['code'] = code.toString(); + } + if (message != null) { + verificationInfoMap['message'] = message; + } + if (verificationStatus != null) { + verificationInfoMap['verificationStatus'] = verificationStatus; + } + + return verificationInfoMap; + } +} diff --git a/test/app/android/build.gradle b/test/app/android/build.gradle index cba6c84..859edc8 100644 --- a/test/app/android/build.gradle +++ b/test/app/android/build.gradle @@ -26,6 +26,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/test/app/lib/command_executor.dart b/test/app/lib/command_executor.dart index 135366a..5c96daa 100644 --- a/test/app/lib/command_executor.dart +++ b/test/app/lib/command_executor.dart @@ -17,9 +17,11 @@ import 'package:adjust_sdk/adjust_event.dart'; import 'package:adjust_sdk/adjust_event_failure.dart'; import 'package:adjust_sdk/adjust_event_success.dart'; import 'package:adjust_sdk/adjust_play_store_subscription.dart'; +import 'package:adjust_sdk/adjust_play_store_purchase.dart'; import 'package:adjust_sdk/adjust_session_failure.dart'; import 'package:adjust_sdk/adjust_session_success.dart'; import 'package:adjust_sdk/adjust_third_party_sharing.dart'; +import 'package:adjust_sdk/adjust_purchase_verification_info.dart'; import 'package:test_app/command.dart'; import 'package:test_lib/test_lib.dart'; @@ -30,15 +32,22 @@ class CommandExecutor { String? _gdprPath; String? _subscriptionUrl; String? _subscriptionPath; + String? _purchaseVerificationUrl; + String? _purchaseVerificationPath; String? _extraPath; late Command _command; Map _savedEvents = new Map(); Map _savedConfigs = new Map(); - CommandExecutor(String? baseUrl, String? gdprUrl, String? subscriptionUrl) { + CommandExecutor( + String? baseUrl, + String? gdprUrl, + String? subscriptionUrl, + String? purchaseVerificationUrl) { _baseUrl = baseUrl; _gdprUrl = gdprUrl; _subscriptionUrl = subscriptionUrl; + _purchaseVerificationUrl = purchaseVerificationUrl; } void executeCommand(Command command) { @@ -128,6 +137,9 @@ class CommandExecutor { case 'getLastDeeplink': _getLastDeeplink(); break; + case 'verifyPurchase': + _verifyPurchase(); + break; } } @@ -136,10 +148,12 @@ class CommandExecutor { testOptions['baseUrl'] = _baseUrl; testOptions['gdprUrl'] = _gdprUrl; testOptions['subscriptionUrl'] = _subscriptionUrl; + testOptions['purchaseVerificationUrl'] = _purchaseVerificationUrl; if (_command.containsParameter('basePath')) { _basePath = _command.getFirstParameterValue('basePath'); _gdprPath = _command.getFirstParameterValue('basePath'); _subscriptionPath = _command.getFirstParameterValue('basePath'); + _purchaseVerificationPath = _command.getFirstParameterValue('basePath'); _extraPath = _command.getFirstParameterValue('basePath'); } if (_command.containsParameter('timerInterval')) { @@ -179,6 +193,7 @@ class CommandExecutor { testOptions['basePath'] = _basePath; testOptions['gdprPath'] = _gdprPath; testOptions['subscriptionPath'] = _subscriptionPath; + testOptions['purchaseVerificationPath'] = _purchaseVerificationPath; testOptions['extraPath'] = _extraPath; // Android specific testOptions['useTestConnectionOptions'] = 'true'; @@ -847,4 +862,24 @@ class CommandExecutor { }); } } + + void _verifyPurchase() { + if (Platform.isIOS) { + + } else if (Platform.isAndroid) { + String? productId = _command.getFirstParameterValue('productId'); + String? purchaseToken = _command.getFirstParameterValue('purchaseToken'); + + AdjustPlayStorePurchase purchase = + new AdjustPlayStorePurchase(productId, purchaseToken); + + Adjust.verifyPlayStorePurchase(purchase).then((result) { + String? localBasePath = _basePath; + TestLib.addInfoToSend('verification_status', result?.verificationStatus); + TestLib.addInfoToSend('code', result?.code.toString()); + TestLib.addInfoToSend('message', result?.message); + TestLib.sendInfoToServer(localBasePath); + }); + } + } } diff --git a/test/app/lib/main.dart b/test/app/lib/main.dart index 6554567..36fad97 100644 --- a/test/app/lib/main.dart +++ b/test/app/lib/main.dart @@ -20,6 +20,7 @@ class _MyAppState extends State { String? _baseUrl; String? _gdprUrl; String? _subscriptionUrl; + String? _purchaseVerificationUrl; late String _controlUrl; late CommandExecutor _commandExecutor; @@ -27,13 +28,14 @@ class _MyAppState extends State { void initState() { super.initState(); - String _address = '192.168.8.184'; + String _address = '192.168.2.112'; if (Platform.isAndroid) { String _protocol = 'https'; String _port = '8443'; _baseUrl = _protocol + '://' + _address + ':' + _port; _gdprUrl = _protocol + '://' + _address + ':' + _port; _subscriptionUrl = _protocol + '://' + _address + ':' + _port; + _purchaseVerificationUrl = _protocol + '://' + _address + ':' + _port; _controlUrl = 'ws://' + _address + ':1987'; } else { String _protocol = 'http'; @@ -41,12 +43,13 @@ class _MyAppState extends State { _baseUrl = _protocol + '://' + _address + ':' + _port; _gdprUrl = _protocol + '://' + _address + ':' + _port; _subscriptionUrl = _protocol + '://' + _address + ':' + _port; + _purchaseVerificationUrl = _protocol + '://' + _address + ':' + _port; _controlUrl = 'ws://' + _address + ':1987'; } // Initialise command executor. _commandExecutor = - new CommandExecutor(_baseUrl, _gdprUrl, _subscriptionUrl); + new CommandExecutor(_baseUrl, _gdprUrl, _subscriptionUrl, _purchaseVerificationUrl); // Initialise test library. TestLib.setExecuteCommandHalder((final dynamic callArgs) { diff --git a/test/app/pubspec.yaml b/test/app/pubspec.yaml index ef3b2d4..ba8adce 100644 --- a/test/app/pubspec.yaml +++ b/test/app/pubspec.yaml @@ -31,7 +31,7 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^0.1.3 + cupertino_icons: ^1.0.0 dev_dependencies: flutter_test: From cd17934d589882ab41898635519723f0e91f56c9 Mon Sep 17 00:00:00 2001 From: uerceg Date: Mon, 4 Sep 2023 16:01:48 +0200 Subject: [PATCH 09/16] chore: exclude app store purchase verificatino for android --- .../src/main/java/com/adjust/sdk/flutter/AdjustSdk.java | 7 +++++++ 1 file changed, 7 insertions(+) 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 8cda8a8..a4ef046 100644 --- a/android/src/main/java/com/adjust/sdk/flutter/AdjustSdk.java +++ b/android/src/main/java/com/adjust/sdk/flutter/AdjustSdk.java @@ -210,6 +210,9 @@ public void onMethodCall(MethodCall call, final Result result) { case "verifyPlayStorePurchase": verifyPlayStorePurchase(call, result); break; + case "verifyAppStorePurchase": + verifyAppStorePurchase(call, result); + break; case "setTestOptions": setTestOptions(call, result); break; @@ -1144,6 +1147,10 @@ public void onVerificationFinished(AdjustPurchaseVerificationResult verification }); } + private void verifyAppStorePurchase(final MethodCall call, final Result result) { + result.success("Error. No verifyAppStorePurchase for Android platform!"); + } + private void setTestOptions(final MethodCall call, final Result result) { AdjustTestOptions testOptions = new AdjustTestOptions(); Map testOptionsMap = (Map) call.arguments; From 72901911911d705f36100c17088b2c8887f381d1 Mon Sep 17 00:00:00 2001 From: uerceg Date: Mon, 4 Sep 2023 16:13:59 +0200 Subject: [PATCH 10/16] feat: add ability to track only verified android revenue --- .../java/com/adjust/sdk/flutter/AdjustSdk.java | 12 ++++++++++++ lib/adjust_event.dart | 15 +++++++++++---- test/app/lib/command_executor.dart | 6 ++++++ 3 files changed, 29 insertions(+), 4 deletions(-) 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 a4ef046..c70734a 100644 --- a/android/src/main/java/com/adjust/sdk/flutter/AdjustSdk.java +++ b/android/src/main/java/com/adjust/sdk/flutter/AdjustSdk.java @@ -606,6 +606,18 @@ private void trackEvent(final MethodCall call, final Result result) { event.setOrderId(orderId); } + // Product ID. + if (eventMap.containsKey("productId")) { + String productId = (String) eventMap.get("productId"); + event.setProductId(productId); + } + + // Purchase token. + if (eventMap.containsKey("purchaseToken")) { + String purchaseToken = (String) eventMap.get("purchaseToken"); + event.setPurchaseToken(purchaseToken); + } + // Callback ID. if (eventMap.containsKey("callbackId")) { String callbackId = (String) eventMap.get("callbackId"); diff --git a/lib/adjust_event.dart b/lib/adjust_event.dart index 82cc128..5b5f2e2 100644 --- a/lib/adjust_event.dart +++ b/lib/adjust_event.dart @@ -10,13 +10,14 @@ import 'dart:convert'; class AdjustEvent { String _eventToken; - num? _revenue; String? _currency; - Map? _callbackParameters; - Map? _partnerParameters; - String? transactionId; + String? productId; + String? purchaseToken; String? callbackId; + num? _revenue; + Map? _callbackParameters; + Map? _partnerParameters; AdjustEvent(this._eventToken) { _callbackParameters = new Map(); @@ -48,6 +49,12 @@ class AdjustEvent { if (transactionId != null) { eventMap['transactionId'] = transactionId; } + if (productId != null) { + eventMap['productId'] = productId; + } + if (purchaseToken != null) { + eventMap['purchaseToken'] = purchaseToken; + } if (callbackId != null) { eventMap['callbackId'] = callbackId; } diff --git a/test/app/lib/command_executor.dart b/test/app/lib/command_executor.dart index 5c96daa..15b74c9 100644 --- a/test/app/lib/command_executor.dart +++ b/test/app/lib/command_executor.dart @@ -556,6 +556,12 @@ class CommandExecutor { if (_command.containsParameter('orderId')) { adjustEvent!.transactionId = _command.getFirstParameterValue('orderId'); } + if (_command.containsParameter('productId')) { + adjustEvent!.productId = _command.getFirstParameterValue('productId'); + } + if (_command.containsParameter('purchaseToken')) { + adjustEvent!.purchaseToken = _command.getFirstParameterValue('purchaseToken'); + } if (_command.containsParameter('callbackId')) { adjustEvent!.callbackId = _command.getFirstParameterValue('callbackId'); } From deb9f70e4a80df782fd48bb5b8f7169a4f02e00e Mon Sep 17 00:00:00 2001 From: uerceg Date: Tue, 5 Sep 2023 09:24:35 +0200 Subject: [PATCH 11/16] feat: add app store purchase verification feature --- ios/Classes/AdjustSdk.m | 53 ++++++++++++++++++- lib/adjust.dart | 8 +++ lib/adjust_app_store_purchase.dart | 31 +++++++++++ test/app/ios/Runner.xcodeproj/project.pbxproj | 1 + test/app/lib/command_executor.dart | 14 +++++ 5 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 lib/adjust_app_store_purchase.dart diff --git a/ios/Classes/AdjustSdk.m b/ios/Classes/AdjustSdk.m index fa2cd8f..7f52781 100644 --- a/ios/Classes/AdjustSdk.m +++ b/ios/Classes/AdjustSdk.m @@ -127,6 +127,10 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result [self updateConversionValueWithErrorCallback:call withResult:result]; } else if ([@"updateConversionValueWithErrorCallbackSkad4" isEqualToString:call.method]) { [self updateConversionValueWithErrorCallbackSkad4:call withResult:result]; + } else if ([@"verifyAppStorePurchase" isEqualToString:call.method]) { + [self verifyAppStorePurchase:call withResult:result]; + } else if ([@"verifyPlayStorePurchase" isEqualToString:call.method]) { + [self verifyAppStorePurchase:call withResult:result]; } else { result(FlutterMethodNotImplemented); } @@ -579,7 +583,7 @@ - (void)trackAppStoreSubscription:(FlutterMethodCall *)call withResult:(FlutterR } } - // Track event. + // Track subscription. [Adjust trackSubscription:subscription]; result(nil); } @@ -720,11 +724,55 @@ - (void)updateConversionValueWithErrorCallbackSkad4:(FlutterMethodCall *)call wi } } +- (void)verifyPlayStorePurchase:(FlutterMethodCall *)call withResult:(FlutterResult)result { + result([FlutterError errorWithCode:@"non_existing_method" + message:@"verifyPlayStorePurchase not available for iOS platform" + details:nil]); +} + +- (void)verifyAppStorePurchase:(FlutterMethodCall *)call withResult:(FlutterResult)result { + NSString *receipt = call.arguments[@"receipt"]; + NSString *productId = call.arguments[@"productId"]; + NSString *transactionId = call.arguments[@"transactionId"]; + + // Receipt. + NSData *receiptValue; + if ([self isFieldValid:receipt]) { + receiptValue = [receipt dataUsingEncoding:NSUTF8StringEncoding]; + } + + // Create purchase instance. + ADJPurchase *purchase = [[ADJPurchase alloc] initWithTransactionId:transactionId + productId:productId + andReceipt:receiptValue]; + + // Verify purchase. + [Adjust verifyPurchase:purchase + completionHandler:^(ADJPurchaseVerificationResult * _Nonnull verificationResult) { + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + if (verificationResult == nil) { + result(dictionary); + } + + [self addValueOrEmpty:verificationResult.verificationStatus + withKey:@"verificationStatus" + toDictionary:dictionary]; + [self addValueOrEmpty:[NSString stringWithFormat:@"%d", verificationResult.code] + withKey:@"code" + toDictionary:dictionary]; + [self addValueOrEmpty:verificationResult.message + withKey:@"message" + toDictionary:dictionary]; + result(dictionary); + }]; +} + - (void)setTestOptions:(FlutterMethodCall *)call withResult:(FlutterResult)result { AdjustTestOptions *testOptions = [[AdjustTestOptions alloc] init]; NSString *baseUrl = call.arguments[@"baseUrl"]; NSString *gdprUrl = call.arguments[@"gdprUrl"]; NSString *subscriptionUrl = call.arguments[@"subscriptionUrl"]; + NSString *purchaseVerificationUrl = call.arguments[@"purchaseVerificationUrl"]; NSString *extraPath = call.arguments[@"extraPath"]; NSString *timerIntervalInMilliseconds = call.arguments[@"timerIntervalInMilliseconds"]; NSString *timerStartInMilliseconds = call.arguments[@"timerStartInMilliseconds"]; @@ -744,6 +792,9 @@ - (void)setTestOptions:(FlutterMethodCall *)call withResult:(FlutterResult)resul if ([self isFieldValid:subscriptionUrl]) { testOptions.subscriptionUrl = subscriptionUrl; } + if ([self isFieldValid:purchaseVerificationUrl]) { + testOptions.purchaseVerificationUrl = purchaseVerificationUrl; + } if ([self isFieldValid:extraPath]) { testOptions.extraPath = extraPath; } diff --git a/lib/adjust.dart b/lib/adjust.dart index 18d2a5d..59aa117 100644 --- a/lib/adjust.dart +++ b/lib/adjust.dart @@ -10,6 +10,7 @@ import 'dart:async'; import 'package:adjust_sdk/adjust_ad_revenue.dart'; import 'package:adjust_sdk/adjust_app_store_subscription.dart'; +import 'package:adjust_sdk/adjust_app_store_purchase.dart'; import 'package:adjust_sdk/adjust_attribution.dart'; import 'package:adjust_sdk/adjust_config.dart'; import 'package:adjust_sdk/adjust_event.dart'; @@ -216,6 +217,13 @@ class Adjust { return AdjustPurchaseVerificationInfo.fromMap(playStorePurchaseMap); } + static Future verifyAppStorePurchase( + AdjustAppStorePurchase purchase) async { + final dynamic appStorePurchaseMap = + await _channel.invokeMethod('verifyAppStorePurchase', purchase.toMap); + return AdjustPurchaseVerificationInfo.fromMap(appStorePurchaseMap); + } + // For testing purposes only. Do not use in production. @visibleForTesting static void setTestOptions(final dynamic testOptions) { diff --git a/lib/adjust_app_store_purchase.dart b/lib/adjust_app_store_purchase.dart new file mode 100644 index 0000000..9b70738 --- /dev/null +++ b/lib/adjust_app_store_purchase.dart @@ -0,0 +1,31 @@ +// +// adjust_app_store_purchase.dart +// Adjust SDK +// +// Created by Ugljesa Erceg (@uerceg) on 5th September 2023. +// Copyright (c) 2020-Present Adjust GmbH. All rights reserved. +// + +class AdjustAppStorePurchase { + String? receipt; + String? productId; + String? transactionId; + + AdjustAppStorePurchase(this.receipt, this.productId, this.transactionId); + + Map get toMap { + Map purchaseMap = new Map(); + + if (receipt != null) { + purchaseMap['receipt'] = receipt; + } + if (productId != null) { + purchaseMap['productId'] = productId; + } + if (transactionId != null) { + purchaseMap['transactionId'] = transactionId; + } + + return purchaseMap; + } +} diff --git a/test/app/ios/Runner.xcodeproj/project.pbxproj b/test/app/ios/Runner.xcodeproj/project.pbxproj index 0ece039..de546c7 100644 --- a/test/app/ios/Runner.xcodeproj/project.pbxproj +++ b/test/app/ios/Runner.xcodeproj/project.pbxproj @@ -237,6 +237,7 @@ files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( diff --git a/test/app/lib/command_executor.dart b/test/app/lib/command_executor.dart index 15b74c9..d20b0a3 100644 --- a/test/app/lib/command_executor.dart +++ b/test/app/lib/command_executor.dart @@ -11,6 +11,7 @@ import 'dart:io' show Platform; import 'package:adjust_sdk/adjust.dart'; import 'package:adjust_sdk/adjust_ad_revenue.dart'; import 'package:adjust_sdk/adjust_app_store_subscription.dart'; +import 'package:adjust_sdk/adjust_app_store_purchase.dart'; import 'package:adjust_sdk/adjust_attribution.dart'; import 'package:adjust_sdk/adjust_config.dart'; import 'package:adjust_sdk/adjust_event.dart'; @@ -871,7 +872,20 @@ class CommandExecutor { void _verifyPurchase() { if (Platform.isIOS) { + String? receipt = _command.getFirstParameterValue('receipt'); + String? productId = _command.getFirstParameterValue('productId'); + String? transactionId = _command.getFirstParameterValue('transactionId'); + AdjustAppStorePurchase purchase = + new AdjustAppStorePurchase(receipt, productId, transactionId); + + Adjust.verifyAppStorePurchase(purchase).then((result) { + String? localBasePath = _basePath; + TestLib.addInfoToSend('verification_status', result?.verificationStatus); + TestLib.addInfoToSend('code', result?.code.toString()); + TestLib.addInfoToSend('message', result?.message); + TestLib.sendInfoToServer(localBasePath); + }); } else if (Platform.isAndroid) { String? productId = _command.getFirstParameterValue('productId'); String? purchaseToken = _command.getFirstParameterValue('purchaseToken'); From d595ff35e5a173d39d1b2c4ced97a0fe631bd7f6 Mon Sep 17 00:00:00 2001 From: uerceg Date: Tue, 5 Sep 2023 10:04:16 +0200 Subject: [PATCH 12/16] feat: add ability to track only verified ios revenue --- ios/Classes/AdjustSdk.m | 14 ++++++++++++++ lib/adjust_event.dart | 4 ++++ test/app/lib/command_executor.dart | 6 ++++++ 3 files changed, 24 insertions(+) diff --git a/ios/Classes/AdjustSdk.m b/ios/Classes/AdjustSdk.m index 7f52781..c4fd1f1 100644 --- a/ios/Classes/AdjustSdk.m +++ b/ios/Classes/AdjustSdk.m @@ -323,6 +323,8 @@ - (void)trackEvent:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSString *revenue = call.arguments[@"revenue"]; NSString *currency = call.arguments[@"currency"]; NSString *callbackId = call.arguments[@"callbackId"]; + NSString *receipt = call.arguments[@"receipt"]; + NSString *productId = call.arguments[@"productId"]; NSString *transactionId = call.arguments[@"transactionId"]; NSString *strCallbackParametersJson = call.arguments[@"callbackParameters"]; NSString *strPartnerParametersJson = call.arguments[@"partnerParameters"]; @@ -336,6 +338,18 @@ - (void)trackEvent:(FlutterMethodCall *)call withResult:(FlutterResult)result { [adjustEvent setRevenue:revenueValue currency:currency]; } + // Receipt. + if ([self isFieldValid:receipt]) { + NSData *receiptValue; + receiptValue = [receipt dataUsingEncoding:NSUTF8StringEncoding]; + [adjustEvent setReceipt:receiptValue]; + } + + // Product ID. + if ([self isFieldValid:productId]) { + [adjustEvent setProductId:productId]; + } + // Transaction ID. if ([self isFieldValid:transactionId]) { [adjustEvent setTransactionId:transactionId]; diff --git a/lib/adjust_event.dart b/lib/adjust_event.dart index 5b5f2e2..ab77ec5 100644 --- a/lib/adjust_event.dart +++ b/lib/adjust_event.dart @@ -11,6 +11,7 @@ import 'dart:convert'; class AdjustEvent { String _eventToken; String? _currency; + String? receipt; String? transactionId; String? productId; String? purchaseToken; @@ -49,6 +50,9 @@ class AdjustEvent { if (transactionId != null) { eventMap['transactionId'] = transactionId; } + if (receipt != null) { + eventMap['receipt'] = receipt; + } if (productId != null) { eventMap['productId'] = productId; } diff --git a/test/app/lib/command_executor.dart b/test/app/lib/command_executor.dart index d20b0a3..511b88b 100644 --- a/test/app/lib/command_executor.dart +++ b/test/app/lib/command_executor.dart @@ -557,9 +557,15 @@ class CommandExecutor { if (_command.containsParameter('orderId')) { adjustEvent!.transactionId = _command.getFirstParameterValue('orderId'); } + if (_command.containsParameter('receipt')) { + adjustEvent!.receipt = _command.getFirstParameterValue('receipt'); + } if (_command.containsParameter('productId')) { adjustEvent!.productId = _command.getFirstParameterValue('productId'); } + if (_command.containsParameter('transactionId')) { + adjustEvent!.transactionId = _command.getFirstParameterValue('transactionId'); + } if (_command.containsParameter('purchaseToken')) { adjustEvent!.purchaseToken = _command.getFirstParameterValue('purchaseToken'); } From f87383d68a8545c613807a6d1606df3ab8db4d96 Mon Sep 17 00:00:00 2001 From: uerceg Date: Wed, 6 Sep 2023 14:51:35 +0200 Subject: [PATCH 13/16] build: update native dependencies --- ios/adjust_sdk.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/adjust_sdk.podspec b/ios/adjust_sdk.podspec index 8311077..6c9c0b2 100644 --- a/ios/adjust_sdk.podspec +++ b/ios/adjust_sdk.podspec @@ -14,5 +14,5 @@ Pod::Spec.new do |s| s.ios.deployment_target = '8.0' s.dependency 'Flutter' - s.dependency 'Adjust', '4.34.1' + s.dependency 'Adjust', '4.34.2' end From c9122577d8e5c43d0fc45e255387424b1f6e6167 Mon Sep 17 00:00:00 2001 From: uerceg Date: Wed, 6 Sep 2023 15:02:21 +0200 Subject: [PATCH 14/16] chore: update example app project settings --- example/ios/Runner.xcodeproj/project.pbxproj | 6 +++++- .../Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index b60c77f..5c3a88d 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -175,7 +175,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1430; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -224,6 +224,7 @@ files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( @@ -385,6 +386,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -524,6 +526,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -555,6 +558,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index f3d88ac..4ba725f 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ Date: Wed, 6 Sep 2023 15:02:37 +0200 Subject: [PATCH 15/16] feat: add att dialog delay feature --- ios/Classes/AdjustSdk.m | 6 ++++++ lib/adjust_config.dart | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/ios/Classes/AdjustSdk.m b/ios/Classes/AdjustSdk.m index c4fd1f1..013ed37 100644 --- a/ios/Classes/AdjustSdk.m +++ b/ios/Classes/AdjustSdk.m @@ -151,6 +151,7 @@ - (void)start:(FlutterMethodCall *)call withResult:(FlutterResult)result { NSString *info3 = call.arguments[@"info3"]; NSString *info4 = call.arguments[@"info4"]; NSString *delayStart = call.arguments[@"delayStart"]; + NSString *attConsentWaitingInterval = call.arguments[@"attConsentWaitingInterval"]; NSString *isDeviceKnown = call.arguments[@"isDeviceKnown"]; NSString *eventBufferingEnabled = call.arguments[@"eventBufferingEnabled"]; NSString *sendInBackground = call.arguments[@"sendInBackground"]; @@ -276,6 +277,11 @@ - (void)start:(FlutterMethodCall *)call withResult:(FlutterResult)result { if ([self isFieldValid:delayStart]) { [adjustConfig setDelayStart:[delayStart doubleValue]]; } + + // ATT consent delay. + if ([self isFieldValid:attConsentWaitingInterval]) { + [adjustConfig setAttConsentWaitingInterval:[attConsentWaitingInterval intValue]]; + } // App secret. if ([self isFieldValid:secretId] diff --git a/lib/adjust_config.dart b/lib/adjust_config.dart index 8987e4e..863da5b 100644 --- a/lib/adjust_config.dart +++ b/lib/adjust_config.dart @@ -67,6 +67,7 @@ class AdjustConfig { num? _secretId; bool? _skAdNetworkHandling; + num? attConsentWaitingInterval; double? delayStart; bool? isDeviceKnown; bool? sendInBackground; @@ -279,6 +280,9 @@ class AdjustConfig { if (delayStart != null) { configMap['delayStart'] = delayStart.toString(); } + if (attConsentWaitingInterval != null) { + configMap['attConsentWaitingInterval'] = attConsentWaitingInterval.toString(); + } if (attributionCallback != null) { configMap['attributionCallback'] = _attributionCallbackName; } From ad38c52d7cd8ebdc5d73c46be4b33a3beeb4100e Mon Sep 17 00:00:00 2001 From: uerceg Date: Wed, 6 Sep 2023 18:13:18 +0200 Subject: [PATCH 16/16] docs: update CHANGELOG --- CHANGELOG.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eb6cb0..0f5aacb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +### Version 4.34.0 (6th September 2023) +#### Added +- Added support for Android apps using Gradle 8.0 or later. +- Added ability to delay SDK start on iOS platform in order to wait for an answer to the ATT dialog. You can set the number of seconds to wait (capped internally to 120) by setting the `attConsentWaitingInterval` method of the `AdjustConfig` instance. +- Added support for purchase verification. In case you are using this feature, you can now use it by calling `verifyAppStorePurchase` (for iOS) and `verifyPlayStorePurchase` (for Android) methods of the `Adjust` instance. + +#### Native SDKs +- [iOS@v4.34.2][ios_sdk_v4.34.2] +- [Android@v4.34.0][android_sdk_v4.34.0] + +--- + ### Version 4.33.1 (16th February 2023) #### Fixed - Skipped invocation of SKAN 4.0 style callback in case SKAN 4.0 API was not invoked (https://github.com/adjust/flutter_sdk/issues/104). @@ -324,6 +336,7 @@ [ios_sdk_v4.32.1]: https://github.com/adjust/ios_sdk/tree/v4.32.1 [ios_sdk_v4.33.2]: https://github.com/adjust/ios_sdk/tree/v4.33.2 [ios_sdk_v4.33.4]: https://github.com/adjust/ios_sdk/tree/v4.33.4 +[ios_sdk_v4.34.2]: https://github.com/adjust/ios_sdk/tree/v4.34.2 [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 @@ -339,4 +352,5 @@ [android_sdk_v4.31.0]: https://github.com/adjust/android_sdk/tree/v4.31.0 [android_sdk_v4.32.0]: https://github.com/adjust/android_sdk/tree/v4.32.0 [android_sdk_v4.33.2]: https://github.com/adjust/android_sdk/tree/v4.33.2 -[android_sdk_v4.33.3]: https://github.com/adjust/android_sdk/tree/v4.33.3 \ No newline at end of file +[android_sdk_v4.33.3]: https://github.com/adjust/android_sdk/tree/v4.33.3 +[android_sdk_v4.34.0]: https://github.com/adjust/android_sdk/tree/v4.34.0 \ No newline at end of file