Skip to content

Commit 813cbac

Browse files
Merge branch 'master' into SDK-2459
2 parents 910e7b3 + 50d5b5a commit 813cbac

24 files changed

+435
-133
lines changed

.envrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
use flake

.github/workflows/sync-readme-changelog.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
--data "$payload"
4040

4141
- name: Announce New Release in Slack
42-
uses: slackapi/slack-github-action@v1.25.0
42+
uses: slackapi/slack-github-action@v1.27.0
4343
with:
4444
channel-id: "C063MQJMKJN" #sdk-releases
4545
payload: |

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,5 @@ Branch-SDK-TestBed/gradlew
2626
Branch-SDK-TestBed/gradlew.bat
2727

2828
Branch-SDK-TestBed/gradle/wrapper/gradle-wrapper.properties
29+
30+
.direnv

Branch-SDK/build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ dependencies {
6262
}
6363

6464
val VERSION_NAME: String by project
65+
val ANDROID_BUILD_TOOLS_VERSION: String by project
6566
val ANDROID_BUILD_SDK_VERSION_COMPILE: String by project
6667
val ANDROID_BUILD_SDK_VERSION_MINIMUM: String by project
6768
val VERSION_CODE: String by project
@@ -72,7 +73,7 @@ fun isReleaseBuild(): Boolean {
7273

7374
android {
7475
compileSdk = ANDROID_BUILD_SDK_VERSION_COMPILE.toInt()
75-
76+
buildToolsVersion = ANDROID_BUILD_TOOLS_VERSION
7677
defaultConfig {
7778
minSdk = ANDROID_BUILD_SDK_VERSION_MINIMUM.toInt()
7879
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Branch-SDK/proguard-consumer.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@
55
-dontwarn com.samsung.android.sdk.sinstallreferrer.**
66

77
-dontwarn com.google.android.gms.**
8+
9+
-dontwarn com.android.billingclient.**

Branch-SDK/src/androidTest/java/io/branch/referral/ServerRequestTests.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
package io.branch.referral;
22

3+
import static io.branch.referral.Defines.Jsonkey.Branch_Sdk_Request_Uuid;
4+
5+
import android.util.Log;
6+
37
import androidx.test.ext.junit.runners.AndroidJUnit4;
48

59
import org.json.JSONArray;
10+
import org.json.JSONException;
611
import org.json.JSONObject;
712
import org.junit.After;
813
import org.junit.Assert;
@@ -11,10 +16,13 @@
1116
import org.junit.runner.RunWith;
1217

1318
import java.util.Calendar;
19+
import java.util.UUID;
1420
import java.util.concurrent.CountDownLatch;
1521
import java.util.concurrent.TimeUnit;
1622

1723
import io.branch.indexing.BranchUniversalObject;
24+
import io.branch.referral.util.BRANCH_STANDARD_EVENT;
25+
import io.branch.referral.util.BranchEvent;
1826
import io.branch.referral.util.ContentMetadata;
1927
import io.branch.referral.util.LinkProperties;
2028

@@ -111,6 +119,32 @@ public void onLinkCreate(String url, BranchError error) {
111119
});
112120
}
113121

122+
@Test
123+
public void testServerRequestUuid() {
124+
new BranchEvent(BRANCH_STANDARD_EVENT.PURCHASE).logEvent(getTestContext());
125+
final ServerRequestQueue queue = ServerRequestQueue.getInstance(getTestContext());
126+
Assert.assertEquals(1, queue.getSize());
127+
128+
ServerRequest eventRequest = queue.peekAt(0);
129+
130+
// Slightly hacky, we are creating a UUID and appending a formatted date string which will always be length 11 `-yyyyMMddHH`.
131+
String uuid = eventRequest.uuid.substring(0, eventRequest.uuid.length()-11);
132+
// Validate that a UUID is correctly generated
133+
Assert.assertNotNull(UUID.fromString(uuid));
134+
}
135+
136+
@Test
137+
public void testServerRequestTimestamp() {
138+
new BranchEvent(BRANCH_STANDARD_EVENT.PURCHASE).logEvent(getTestContext());
139+
final ServerRequestQueue queue = ServerRequestQueue.getInstance(getTestContext());
140+
Assert.assertEquals(1, queue.getSize());
141+
142+
ServerRequest eventRequest = queue.peekAt(0);
143+
144+
// The default value is 0. Once constructed, the epoch time is set
145+
Assert.assertTrue(eventRequest.creation_ts > 0);
146+
}
147+
114148
private void setTimeouts(int timeout, int connectTimeout){
115149
branch.setNetworkTimeout(timeout);
116150
branch.setNetworkConnectTimeout(connectTimeout);

Branch-SDK/src/main/java/io/branch/referral/Branch.java

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,7 +1442,7 @@ private void initializeSession(ServerRequestInitSession initRequest, int delay)
14421442
if (forceBranchSession && intent != null) {
14431443
intent.removeExtra(Defines.IntentKeys.ForceNewBranchSession.getKey()); // SDK-881, avoid double initialization
14441444
}
1445-
registerAppInit(initRequest, false, forceBranchSession);
1445+
registerAppInit(initRequest, forceBranchSession);
14461446
} else if (initRequest.callback_ != null) {
14471447
// Else, let the user know session initialization failed because it's already initialized.
14481448
initRequest.callback_.onInitFinished(null, new BranchError("Warning.", BranchError.ERR_BRANCH_ALREADY_INITIALIZED));
@@ -1453,7 +1453,7 @@ private void initializeSession(ServerRequestInitSession initRequest, int delay)
14531453
* Registers app init with params filtered from the intent. Unless ignoreIntent = true, this
14541454
* will wait on the wait locks to complete any pending operations
14551455
*/
1456-
void registerAppInit(@NonNull ServerRequestInitSession request, boolean ignoreWaitLocks, boolean forceBranchSession) {
1456+
void registerAppInit(@NonNull ServerRequestInitSession request, boolean forceBranchSession) {
14571457
BranchLogger.v("registerAppInit " + request);
14581458
setInitState(SESSION_STATE.INITIALISING);
14591459

@@ -1475,36 +1475,37 @@ void registerAppInit(@NonNull ServerRequestInitSession request, boolean ignoreWa
14751475
}
14761476
BranchLogger.v("Finished ordering init calls");
14771477
requestQueue_.printQueue();
1478-
initTasks(request, ignoreWaitLocks);
1478+
initTasks(request);
14791479

14801480
requestQueue_.processNextQueueItem("registerAppInit");
14811481
}
14821482

1483-
private void initTasks(ServerRequest request, boolean ignoreWaitLocks) {
1484-
BranchLogger.v("initTasks " + request + " ignoreWaitLocks " + ignoreWaitLocks);
1485-
if (!ignoreWaitLocks) {
1486-
// Single top activities can be launched from stack and there may be a new intent provided with onNewIntent() call.
1487-
// In this case need to wait till onResume to get the latest intent. Bypass this if bypassWaitingForIntent_ is true.
1488-
if (intentState_ != INTENT_STATE.READY && isWaitingForIntent()) {
1489-
BranchLogger.v("Adding INTENT_PENDING_WAIT_LOCK");
1490-
request.addProcessWaitLock(ServerRequest.PROCESS_WAIT_LOCK.INTENT_PENDING_WAIT_LOCK);
1491-
}
1492-
1493-
request.addProcessWaitLock(ServerRequest.PROCESS_WAIT_LOCK.GAID_FETCH_WAIT_LOCK);
1494-
1495-
if (request instanceof ServerRequestRegisterInstall) {
1496-
request.addProcessWaitLock(ServerRequest.PROCESS_WAIT_LOCK.INSTALL_REFERRER_FETCH_WAIT_LOCK);
1497-
1498-
deviceInfo_.getSystemObserver().fetchInstallReferrer(context_, new SystemObserver.InstallReferrerFetchEvents(){
1499-
@Override
1500-
public void onInstallReferrersFinished() {
1501-
request.removeProcessWaitLock(ServerRequest.PROCESS_WAIT_LOCK.INSTALL_REFERRER_FETCH_WAIT_LOCK);
1502-
requestQueue_.processNextQueueItem("onInstallReferrersFinished");
1503-
}
1504-
});
1505-
}
1483+
private void initTasks(ServerRequest request) {
1484+
BranchLogger.v("initTasks " + request);
1485+
// Single top activities can be launched from stack and there may be a new intent provided with onNewIntent() call.
1486+
// In this case need to wait till onResume to get the latest intent. Bypass this if bypassWaitingForIntent_ is true.
1487+
if (intentState_ != INTENT_STATE.READY && isWaitingForIntent()) {
1488+
request.addProcessWaitLock(ServerRequest.PROCESS_WAIT_LOCK.INTENT_PENDING_WAIT_LOCK);
1489+
BranchLogger.v("Added INTENT_PENDING_WAIT_LOCK");
1490+
}
1491+
1492+
if (request instanceof ServerRequestRegisterInstall) {
1493+
request.addProcessWaitLock(ServerRequest.PROCESS_WAIT_LOCK.INSTALL_REFERRER_FETCH_WAIT_LOCK);
1494+
BranchLogger.v("Added INSTALL_REFERRER_FETCH_WAIT_LOCK");
1495+
1496+
deviceInfo_.getSystemObserver().fetchInstallReferrer(context_, new SystemObserver.InstallReferrerFetchEvents() {
1497+
@Override
1498+
public void onInstallReferrersFinished() {
1499+
request.removeProcessWaitLock(ServerRequest.PROCESS_WAIT_LOCK.INSTALL_REFERRER_FETCH_WAIT_LOCK);
1500+
BranchLogger.v("INSTALL_REFERRER_FETCH_WAIT_LOCK removed");
1501+
requestQueue_.processNextQueueItem("onInstallReferrersFinished");
1502+
}
1503+
});
15061504
}
15071505

1506+
request.addProcessWaitLock(ServerRequest.PROCESS_WAIT_LOCK.GAID_FETCH_WAIT_LOCK);
1507+
BranchLogger.v("Added GAID_FETCH_WAIT_LOCK");
1508+
15081509
deviceInfo_.getSystemObserver().fetchAdId(context_, new SystemObserver.AdsParamsFetchEvents() {
15091510
@Override
15101511
public void onAdsParamsFetchFinished() {

Branch-SDK/src/main/java/io/branch/referral/BranchAsyncTask.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public final AsyncTask<Params, Progress, Result> executeTask(Params... params) {
2020
try {
2121
return executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
2222
} catch (Exception t) {
23-
BranchLogger.w("Caught Exception " + t.getMessage());
23+
BranchLogger.w("Caught Exception in AsyncTask: " + t.getMessage());
2424
return execute(params);
2525
}
2626
}

Branch-SDK/src/main/java/io/branch/referral/Defines.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,9 @@ public enum Jsonkey {
225225
DMA_Ad_User_Data("dma_ad_user_data"),
226226
Is_Meta_Click_Through("is_meta_ct"),
227227

228-
Consumer_Protection_Attribution_Level("cpp_level");
228+
Consumer_Protection_Attribution_Level("cpp_level"),
229+
Branch_Sdk_Request_Creation_Time_Stamp("branch_sdk_request_timestamp"),
230+
Branch_Sdk_Request_Uuid("branch_sdk_request_unique_id");
229231

230232
private final String key;
231233

Branch-SDK/src/main/java/io/branch/referral/ServerRequest.java

Lines changed: 67 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,18 @@
1313
import org.json.JSONException;
1414
import org.json.JSONObject;
1515

16+
import java.text.SimpleDateFormat;
1617
import java.util.Arrays;
1718
import java.util.ConcurrentModificationException;
1819
import java.util.HashSet;
1920
import java.util.Iterator;
21+
import java.util.Locale;
2022
import java.util.Set;
23+
import java.util.TimeZone;
2124
import java.util.concurrent.ConcurrentHashMap;
2225

26+
import java.util.UUID;
27+
2328
/**
2429
* Abstract class defining the structure of a Branch Server request.
2530
*/
@@ -34,6 +39,8 @@ public abstract class ServerRequest {
3439

3540
private static final String POST_KEY = "REQ_POST";
3641
private static final String POST_PATH_KEY = "REQ_POST_PATH";
42+
protected long creation_ts = 0;
43+
protected String uuid;
3744

3845
private JSONObject params_;
3946
final Defines.RequestPath requestPath_;
@@ -67,11 +74,7 @@ public enum BRANCH_API_VERSION {
6774
* @param requestPath Path to server for this request.
6875
*/
6976
public ServerRequest(Context context, Defines.RequestPath requestPath) {
70-
context_ = context;
71-
requestPath_ = requestPath;
72-
prefHelper_ = PrefHelper.getInstance(context);
73-
params_ = new JSONObject();
74-
locks_ = new HashSet<>();
77+
this(requestPath, new JSONObject(), context);
7578
}
7679

7780
/**
@@ -83,13 +86,40 @@ public ServerRequest(Context context, Defines.RequestPath requestPath) {
8386
* @param context Application context.
8487
*/
8588
protected ServerRequest(Defines.RequestPath requestPath, JSONObject post, Context context) {
89+
BranchLogger.v("ServerRequest constructor");
8690
context_ = context;
8791
requestPath_ = requestPath;
8892
params_ = post;
8993
prefHelper_ = PrefHelper.getInstance(context);
9094
locks_ = new HashSet<>();
95+
96+
creation_ts = System.currentTimeMillis();
97+
String creation_ts_date_formatted = formatUnixEpochToDateFormat(creation_ts);
98+
uuid = getRequestUuid(creation_ts_date_formatted);
9199
}
92-
100+
101+
/**
102+
* Returns Unix epoch time converted to readable date format: year-month-dayOfMonth-hour with - prefix
103+
* Force Locale US character representation
104+
* @param creationTs
105+
* @return
106+
*/
107+
private String formatUnixEpochToDateFormat(long creationTs) {
108+
SimpleDateFormat sdf = new SimpleDateFormat("-yyyyMMddHH", Locale.US);
109+
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
110+
111+
return sdf.format(creationTs);
112+
}
113+
114+
/**
115+
* Appends formatted time stamp to randomly generated UUID
116+
* @param creationTsDateFormatted
117+
* @return
118+
*/
119+
private String getRequestUuid(String creationTsDateFormatted) {
120+
return UUID.randomUUID().toString() + creationTsDateFormatted;
121+
}
122+
93123
/**
94124
* <p>Should be implemented by the child class.Specifies any error associated with request.
95125
* If there are errors request will not be executed.</p>
@@ -139,16 +169,7 @@ protected ServerRequest(Defines.RequestPath requestPath, JSONObject post, Contex
139169
public boolean shouldRetryOnFail() {
140170
return false;
141171
}
142-
143-
/**
144-
* Specifies whether this request should be persisted to memory in order to re send in the next session
145-
*
146-
* @return {@code true} by default. Should be override for request that need not to be persisted
147-
*/
148-
boolean isPersistable() {
149-
return true;
150-
}
151-
172+
152173
/**
153174
* Specifies whether this request should add the limit app tracking value
154175
*
@@ -241,6 +262,7 @@ public String getRequestUrl() {
241262
* as key-value pairs.
242263
*/
243264
protected void setPost(JSONObject post) throws JSONException {
265+
BranchLogger.v("setPost " + post);
244266
params_ = post;
245267

246268
if (getBranchRemoteAPIVersion() == BRANCH_API_VERSION.V1) {
@@ -364,7 +386,8 @@ public JSONObject toJSON() {
364386
}
365387
return json;
366388
}
367-
389+
390+
// TODO: Replace with in-memory only ServerRequest objects.
368391
/**
369392
* <p>Converts a {@link JSONObject} object containing keys stored as key-value pairs into
370393
* a {@link ServerRequest}.</p>
@@ -404,13 +427,14 @@ public static ServerRequest fromJSON(JSONObject json, Context context) {
404427
} catch (JSONException e) {
405428
BranchLogger.w("Caught JSONException " + e.getMessage());
406429
}
407-
430+
408431
if (!TextUtils.isEmpty(requestPath)) {
409432
return getExtendedServerRequest(requestPath, post, context, initiatedByClient);
410433
}
411434
return null;
412435
}
413-
436+
437+
// TODO: Replace with in-memory only ServerRequest objects.
414438
/**
415439
* <p>Factory method for creating the specific server requests objects. Creates requests according
416440
* to the request path.</p>
@@ -422,18 +446,17 @@ public static ServerRequest fromJSON(JSONObject json, Context context) {
422446
*/
423447
private static ServerRequest getExtendedServerRequest(String requestPath, JSONObject post, Context context, boolean initiatedByClient) {
424448
ServerRequest extendedReq = null;
425-
449+
426450
if (requestPath.equalsIgnoreCase(Defines.RequestPath.GetURL.getPath())) {
427451
extendedReq = new ServerRequestCreateUrl(Defines.RequestPath.GetURL, post, context);
428452
} else if (requestPath.equalsIgnoreCase(Defines.RequestPath.RegisterInstall.getPath())) {
429453
extendedReq = new ServerRequestRegisterInstall(Defines.RequestPath.RegisterInstall, post, context, initiatedByClient);
430454
} else if (requestPath.equalsIgnoreCase(Defines.RequestPath.RegisterOpen.getPath())) {
431455
extendedReq = new ServerRequestRegisterOpen(Defines.RequestPath.RegisterOpen, post, context, initiatedByClient);
432456
}
433-
434457
return extendedReq;
435458
}
436-
459+
437460
/**
438461
* Updates the google ads parameters. This should be called only from a background thread since it involves GADS method invocation using reflection
439462
* Ensure that when there is a valid GAID/AID, remove the SSAID if it's being used
@@ -639,17 +662,37 @@ private void removePreinstallData(JSONObject params) {
639662
}
640663

641664
void doFinalUpdateOnMainThread() {
665+
BranchLogger.v("doFinalUpdateOnMainThread");
642666
updateRequestMetadata();
643667
if (shouldUpdateLimitFacebookTracking()) {
644668
updateLimitFacebookTracking();
645669
}
646670
if (shouldAddDMAParams()) {
647671
addDMAParams();
648672
}
649-
addConsumerProtectionAttributionLevel();
673+
674+
addConsumerProtectionAttributionLevel();
675+
676+
// Always add these fields
677+
addClientRequestParameters();
650678
}
651-
679+
680+
/**
681+
* Put request time stamp and uuid at top level of POST body
682+
*/
683+
private void addClientRequestParameters() {
684+
if(prefHelper_ != null){
685+
try {
686+
params_.put(Defines.Jsonkey.Branch_Sdk_Request_Creation_Time_Stamp.getKey(), this.creation_ts);
687+
params_.put(Defines.Jsonkey.Branch_Sdk_Request_Uuid.getKey(), this.uuid);
688+
} catch (JSONException e) {
689+
throw new RuntimeException(e);
690+
}
691+
}
692+
}
693+
652694
void doFinalUpdateOnBackgroundThread() {
695+
BranchLogger.v("doFinalUpdateOnBackgroundThread");
653696
if (this instanceof ServerRequestInitSession) {
654697
((ServerRequestInitSession) this).updateLinkReferrerParams();
655698
if (prioritizeLinkAttribution(this.params_)) {

0 commit comments

Comments
 (0)