Skip to content

Commit fa12535

Browse files
authored
Merge pull request #579 from adjust/v4340
Version 4.34.0
2 parents 8c377a8 + 821b611 commit fa12535

File tree

40 files changed

+842
-39
lines changed

40 files changed

+842
-39
lines changed

Adjust/build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ ext {
99
coreMinSdkVersion = 9
1010
coreCompileSdkVersion = 33
1111
coreTargetSdkVersion = 33
12-
coreVersionName = '4.33.5'
12+
coreVersionName = '4.34.0'
1313
defaultVersionCode = 1
1414
webbridgeMinSdkVersion = 17
1515
samsungReferrerMinSdkVersion = 18
@@ -20,14 +20,14 @@ ext {
2020
}
2121

2222
buildscript {
23-
ext.kotlin_version = '1.6.10'
23+
ext.kotlin_version = '1.7.10'
2424

2525
repositories {
2626
mavenCentral()
2727
google()
2828
}
2929
dependencies {
30-
classpath 'com.android.tools.build:gradle:7.2.2'
30+
classpath 'com.android.tools.build:gradle:7.3.1'
3131

3232
// NOTE: Do not place your application dependencies here; they belong
3333
// in the individual module build.gradle files.

Adjust/example-app-java/src/main/java/com/adjust/examples/MainActivity.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import androidx.appcompat.app.AppCompatActivity;
88

9+
import android.util.Log;
910
import android.view.Menu;
1011
import android.view.MenuItem;
1112
import android.view.View;
@@ -14,7 +15,9 @@
1415

1516
import com.adjust.sdk.Adjust;
1617
import com.adjust.sdk.AdjustEvent;
17-
import com.adjust.sdk.AdjustPlayStoreSubscription;
18+
import com.adjust.sdk.AdjustPurchase;
19+
import com.adjust.sdk.AdjustPurchaseVerificationResult;
20+
import com.adjust.sdk.OnPurchaseVerificationFinishedListener;
1821

1922
public class MainActivity extends AppCompatActivity {
2023
private static final String EVENT_TOKEN_SIMPLE = "g3mfiw";
@@ -72,9 +75,6 @@ public boolean onOptionsItemSelected(MenuItem item) {
7275
public void onTrackSimpleEventClick(View v) {
7376
AdjustEvent event = new AdjustEvent(EVENT_TOKEN_SIMPLE);
7477

75-
// Assign custom identifier to event which will be reported in success/failure callbacks.
76-
event.setCallbackId("PrettyRandomIdentifier");
77-
7878
Adjust.trackEvent(event);
7979
}
8080

Adjust/gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip

Adjust/sdk-core/src/main/java/com/adjust/sdk/ActivityHandler.java

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ public class ActivityHandler implements IActivityHandler {
7575
private AdjustAttribution attribution;
7676
private IAttributionHandler attributionHandler;
7777
private ISdkClickHandler sdkClickHandler;
78+
private IPurchaseVerificationHandler purchaseVerificationHandler;
7879
private SessionParameters sessionParameters;
7980
private InstallReferrer installReferrer;
8081
private InstallReferrerHuawei installReferrerHuawei;
@@ -102,6 +103,9 @@ public void teardown() {
102103
if (sdkClickHandler != null) {
103104
sdkClickHandler.teardown();
104105
}
106+
if (purchaseVerificationHandler != null) {
107+
purchaseVerificationHandler.teardown();
108+
}
105109
if (sessionParameters != null) {
106110
if (sessionParameters.callbackParameters != null) {
107111
sessionParameters.callbackParameters.clear();
@@ -126,6 +130,7 @@ public void teardown() {
126130
adjustConfig = null;
127131
attributionHandler = null;
128132
sdkClickHandler = null;
133+
purchaseVerificationHandler = null;
129134
sessionParameters = null;
130135
}
131136

@@ -383,6 +388,10 @@ public void finishedTrackingActivity(ResponseData responseData) {
383388
launchEventResponseTasks((EventResponseData)responseData);
384389
return;
385390
}
391+
// check if it's a purchase verification response
392+
if (responseData instanceof PurchaseVerificationResponseData) {
393+
launchPurchaseVerificationResponseTasks((PurchaseVerificationResponseData)responseData);
394+
}
386395
}
387396

388397
@Override
@@ -538,6 +547,16 @@ public void run() {
538547
});
539548
}
540549

550+
@Override
551+
public void launchPurchaseVerificationResponseTasks(final PurchaseVerificationResponseData purchaseVerificationResponseData) {
552+
executor.submit(new Runnable() {
553+
@Override
554+
public void run() {
555+
launchPurchaseVerificationResponseTasksI(purchaseVerificationResponseData);
556+
}
557+
});
558+
}
559+
541560
@Override
542561
public void sendFirstPackages () {
543562
executor.submit(new Runnable() {
@@ -744,6 +763,16 @@ public AdjustAttribution getAttribution() {
744763
return attribution;
745764
}
746765

766+
@Override
767+
public void verifyPurchase(final AdjustPurchase purchase, final OnPurchaseVerificationFinishedListener callback) {
768+
executor.submit(new Runnable() {
769+
@Override
770+
public void run() {
771+
verifyPurchaseI(purchase, callback);
772+
}
773+
});
774+
}
775+
747776
public InternalState getInternalState() {
748777
return internalState;
749778
}
@@ -911,6 +940,7 @@ public void run() {
911940
adjustConfig.basePath,
912941
adjustConfig.gdprPath,
913942
adjustConfig.subscriptionPath,
943+
adjustConfig.purchaseVerificationPath,
914944
deviceInfo.clientSdk);
915945
packageHandler = AdjustFactory.getPackageHandler(
916946
this,
@@ -924,6 +954,7 @@ public void run() {
924954
adjustConfig.basePath,
925955
adjustConfig.gdprPath,
926956
adjustConfig.subscriptionPath,
957+
adjustConfig.purchaseVerificationPath,
927958
deviceInfo.clientSdk);
928959

929960
attributionHandler = AdjustFactory.getAttributionHandler(
@@ -937,13 +968,28 @@ public void run() {
937968
adjustConfig.basePath,
938969
adjustConfig.gdprPath,
939970
adjustConfig.subscriptionPath,
971+
adjustConfig.purchaseVerificationPath,
940972
deviceInfo.clientSdk);
941973

942974
sdkClickHandler = AdjustFactory.getSdkClickHandler(
943975
this,
944976
toSendI(true),
945977
sdkClickHandlerActivitySender);
946978

979+
IActivityPackageSender purchaseVerificationHandlerActivitySender =
980+
new ActivityPackageSender(
981+
adjustConfig.urlStrategy,
982+
adjustConfig.basePath,
983+
adjustConfig.gdprPath,
984+
adjustConfig.subscriptionPath,
985+
adjustConfig.purchaseVerificationPath,
986+
deviceInfo.clientSdk);
987+
988+
purchaseVerificationHandler = AdjustFactory.getPurchaseVerificationHandler(
989+
this,
990+
toSendI(true),
991+
purchaseVerificationHandlerActivitySender);
992+
947993
if (isToUpdatePackagesI()) {
948994
updatePackagesI();
949995
}
@@ -1577,6 +1623,35 @@ public void run() {
15771623
handler.post(runnable);
15781624
}
15791625

1626+
private void launchPurchaseVerificationResponseTasksI(PurchaseVerificationResponseData purchaseVerificationResponseData) {
1627+
// use the same handler to ensure that all tasks are executed sequentially
1628+
Handler handler = new Handler(adjustConfig.context.getMainLooper());
1629+
JSONObject jsonResponse = purchaseVerificationResponseData.jsonResponse;
1630+
1631+
// check and parse response data
1632+
AdjustPurchaseVerificationResult verificationResult;
1633+
if (jsonResponse == null) {
1634+
verificationResult = new AdjustPurchaseVerificationResult(
1635+
"not_verified",
1636+
101,
1637+
purchaseVerificationResponseData.message);
1638+
} else {
1639+
verificationResult = new AdjustPurchaseVerificationResult(
1640+
UtilNetworking.extractJsonString(jsonResponse, "verification_status"),
1641+
UtilNetworking.extractJsonInt(jsonResponse, "code"),
1642+
UtilNetworking.extractJsonString(jsonResponse, "message"));
1643+
}
1644+
1645+
// trigger purchase verification callback with the verification result
1646+
Runnable runnable = new Runnable() {
1647+
@Override
1648+
public void run() {
1649+
purchaseVerificationResponseData.activityPackage.getPurchaseVerificationCallback().onVerificationFinished(verificationResult);
1650+
}
1651+
};
1652+
handler.post(runnable);
1653+
}
1654+
15801655
private void prepareDeeplinkI(final Uri deeplink, final Handler handler) {
15811656
if (deeplink == null) {
15821657
return;
@@ -1923,15 +1998,18 @@ private void pauseSendingI() {
19231998
// it's possible for the sdk click handler to be active while others are paused
19241999
if (!toSendI(true)) {
19252000
sdkClickHandler.pauseSending();
2001+
purchaseVerificationHandler.pauseSending();
19262002
} else {
19272003
sdkClickHandler.resumeSending();
2004+
purchaseVerificationHandler.resumeSending();
19282005
}
19292006
}
19302007

19312008
private void resumeSendingI() {
19322009
attributionHandler.resumeSending();
19332010
packageHandler.resumeSending();
19342011
sdkClickHandler.resumeSending();
2012+
purchaseVerificationHandler.resumeSending();
19352013
}
19362014

19372015
private boolean updateActivityStateI(long now) {
@@ -2403,6 +2481,73 @@ private void trackSubscriptionI(final AdjustPlayStoreSubscription subscription)
24032481
packageHandler.sendFirstPackage();
24042482
}
24052483

2484+
private void verifyPurchaseI(final AdjustPurchase purchase, final OnPurchaseVerificationFinishedListener callback) {
2485+
if (callback == null) {
2486+
logger.warn("Purchase verification aborted because verification callback is null");
2487+
return;
2488+
}
2489+
// from this moment on we know that we can ping client callback in case of error
2490+
if (adjustConfig.urlStrategy != null &&
2491+
(adjustConfig.urlStrategy.equals(AdjustConfig.DATA_RESIDENCY_EU) ||
2492+
adjustConfig.urlStrategy.equals(AdjustConfig.DATA_RESIDENCY_US) ||
2493+
adjustConfig.urlStrategy.equals(AdjustConfig.DATA_RESIDENCY_TR))) {
2494+
logger.warn("Purchase verification not available for data residency users right now");
2495+
return;
2496+
}
2497+
if (!checkActivityStateI(activityState)) {
2498+
AdjustPurchaseVerificationResult result = new AdjustPurchaseVerificationResult(
2499+
"not_verified",
2500+
102,
2501+
"Purchase verification aborted because SDK is still not initialized");
2502+
callback.onVerificationFinished(result);
2503+
logger.warn("Purchase verification aborted because SDK is still not initialized");
2504+
return;
2505+
}
2506+
if (!isEnabledI()) {
2507+
AdjustPurchaseVerificationResult result = new AdjustPurchaseVerificationResult(
2508+
"not_verified",
2509+
103,
2510+
"Purchase verification aborted because SDK is disabled");
2511+
callback.onVerificationFinished(result);
2512+
logger.warn("Purchase verification aborted because SDK is disabled");
2513+
return;
2514+
}
2515+
if (activityState.isGdprForgotten) {
2516+
AdjustPurchaseVerificationResult result = new AdjustPurchaseVerificationResult(
2517+
"not_verified",
2518+
104,
2519+
"Purchase verification aborted because user is GDPR forgotten");
2520+
callback.onVerificationFinished(result);
2521+
logger.warn("Purchase verification aborted because user is GDPR forgotten");
2522+
return;
2523+
}
2524+
if (purchase == null) {
2525+
logger.warn("Purchase verification aborted because purchase instance is null");
2526+
AdjustPurchaseVerificationResult verificationResult =
2527+
new AdjustPurchaseVerificationResult(
2528+
"not_verified",
2529+
105,
2530+
"Purchase verification aborted because purchase instance is null");
2531+
callback.onVerificationFinished(verificationResult);
2532+
return;
2533+
}
2534+
2535+
long now = System.currentTimeMillis();
2536+
PackageBuilder packageBuilder = new PackageBuilder(adjustConfig, deviceInfo, activityState, sessionParameters, now);
2537+
ActivityPackage verificationPackage = packageBuilder.buildVerificationPackage(purchase, callback);
2538+
if (verificationPackage == null) {
2539+
logger.warn("Purchase verification aborted because verification package is null");
2540+
AdjustPurchaseVerificationResult verificationResult =
2541+
new AdjustPurchaseVerificationResult(
2542+
"not_verified",
2543+
106,
2544+
"Purchase verification aborted because verification package is null");
2545+
callback.onVerificationFinished(verificationResult);
2546+
return;
2547+
}
2548+
purchaseVerificationHandler.sendPurchaseVerificationPackage(verificationPackage);
2549+
}
2550+
24062551
private void gotOptOutResponseI() {
24072552
activityState.isGdprForgotten = true;
24082553
writeActivityStateI();

Adjust/sdk-core/src/main/java/com/adjust/sdk/ActivityKind.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ public enum ActivityKind {
1414
DISABLE_THIRD_PARTY_SHARING,
1515
SUBSCRIPTION,
1616
THIRD_PARTY_SHARING,
17-
MEASUREMENT_CONSENT;
17+
MEASUREMENT_CONSENT,
18+
PURCHASE_VERIFICATION;
1819

1920
public static ActivityKind fromString(String string) {
2021
if ("session".equals(string)) {
@@ -39,6 +40,8 @@ public static ActivityKind fromString(String string) {
3940
return THIRD_PARTY_SHARING;
4041
} else if ("measurement_consent".equals(string)) {
4142
return MEASUREMENT_CONSENT;
43+
} else if ("purchase_verification".equals(string)) {
44+
return PURCHASE_VERIFICATION;
4245
} else {
4346
return UNKNOWN;
4447
}
@@ -69,6 +72,8 @@ public String toString() {
6972
return "third_party_sharing";
7073
case MEASUREMENT_CONSENT:
7174
return "measurement_consent";
75+
case PURCHASE_VERIFICATION:
76+
return "purchase_verification";
7277
default:
7378
return "unknown";
7479
}

Adjust/sdk-core/src/main/java/com/adjust/sdk/ActivityPackage.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ public class ActivityPackage implements Serializable {
4848
private Map<String, String> callbackParameters;
4949
private Map<String, String> partnerParameters;
5050

51+
// callbacks
52+
private OnPurchaseVerificationFinishedListener purchaseVerificationCallback;
53+
5154
private int retries;
5255
private long clickTimeInMilliseconds;
5356
private long clickTimeInSeconds;
@@ -165,6 +168,14 @@ public void setGooglePlayInstant(Boolean googlePlayInstant) {
165168
this.googlePlayInstant = googlePlayInstant;
166169
}
167170

171+
public OnPurchaseVerificationFinishedListener getPurchaseVerificationCallback() {
172+
return this.purchaseVerificationCallback;
173+
}
174+
175+
public void setPurchaseVerificationCallback(final OnPurchaseVerificationFinishedListener callback) {
176+
this.purchaseVerificationCallback = callback;
177+
}
178+
168179
public Map<String, String> getCallbackParameters() {
169180
return callbackParameters;
170181
}

Adjust/sdk-core/src/main/java/com/adjust/sdk/Adjust.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ private Adjust() {
3434
*/
3535
public static synchronized AdjustInstance getDefaultInstance() {
3636
@SuppressWarnings("unused")
37-
String VERSION = "!SDK-VERSION-STRING!:com.adjust.sdk:adjust-android:4.33.5";
37+
String VERSION = "!SDK-VERSION-STRING!:com.adjust.sdk:adjust-android:4.34.0";
3838

3939
if (defaultInstance == null) {
4040
defaultInstance = new AdjustInstance();
@@ -363,6 +363,17 @@ public static String getSdkVersion() {
363363
return adjustInstance.getSdkVersion();
364364
}
365365

366+
/**
367+
* Verify in app purchase from Google Play.
368+
*
369+
* @param purchase AdjustPurchase object to be tracked
370+
* @param callback Callback to obtain verification results
371+
*/
372+
public static void verifyPurchase(final AdjustPurchase purchase, OnPurchaseVerificationFinishedListener callback) {
373+
AdjustInstance adjustInstance = Adjust.getDefaultInstance();
374+
adjustInstance.verifyPurchase(purchase, callback);
375+
}
376+
366377
/**
367378
* Used for testing purposes only. Do NOT use this method.
368379
*

Adjust/sdk-core/src/main/java/com/adjust/sdk/AdjustConfig.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public class AdjustConfig {
1111
String basePath;
1212
String gdprPath;
1313
String subscriptionPath;
14+
String purchaseVerificationPath;
1415
Context context;
1516
String appToken;
1617
String environment;

0 commit comments

Comments
 (0)