Skip to content

Commit

Permalink
Merge pull request #834 from BranchMetrics/Staging
Browse files Browse the repository at this point in the history
Staging to master (releasing 5.0.1)
  • Loading branch information
bklastaitis-branch committed Apr 7, 2020
2 parents 2175cad + 02bdd42 commit b06e01c
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 22 deletions.
Expand Up @@ -39,15 +39,15 @@ public void testHardwareIdSimulatedInstall() {
SystemObserver.UniqueId uniqueId1 = DeviceInfo.getInstance().getHardwareID();

// Enable simulated installs
Branch.enableSimulateInstalls();
Branch.disableDeviceIDFetch(true);
SystemObserver.UniqueId uniqueSimulatedId1 = DeviceInfo.getInstance().getHardwareID();
SystemObserver.UniqueId uniqueSimulatedId2 = DeviceInfo.getInstance().getHardwareID();

// Per design, two requests for simulated IDs must be different.
Assert.assertNotEquals(uniqueSimulatedId1, uniqueSimulatedId2);

// A "Real" hardware Id should always be identical, even after switching simulation mode on and off.
Branch.disableSimulateInstalls();
Branch.disableDeviceIDFetch(false);
SystemObserver.UniqueId uniqueId2 = DeviceInfo.getInstance().getHardwareID();
Assert.assertEquals(uniqueId1, uniqueId2);
}
Expand Down
Expand Up @@ -2,6 +2,8 @@

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;

import org.json.JSONException;
import org.json.JSONObject;
Expand All @@ -22,8 +24,9 @@ abstract class ServerRequestInitSession extends ServerRequest {
private final ContentDiscoveryManifest contentDiscoveryManifest_;

private static final int STATE_FRESH_INSTALL = 0;
private static final int STATE_UPDATE = 2;
private static final int STATE_NO_CHANGE = 1;
private static final int STATE_UPDATE = 2;
private static final int STATE_TUNE_MIGRATION = 5;


ServerRequestInitSession(Context context, String requestPath) {
Expand Down Expand Up @@ -202,48 +205,53 @@ public void onPreExecute() {
}

/*
* Method to update the install or update state along with the timestamps.
* PRS NOTE
* Method to determine the install/update/no_change state along with the timestamps. Note that the
* back end has its own logic to interpret these (that logic includes 'reinstall' state).
* https://branch.atlassian.net/wiki/spaces/EN/pages/798786098/Open+Install+Reinstall+Logic+from+API+Open
*
* The Original install time will have a the very first install time only if the app allows preference back up.
* Apps that need to distinguish between a fresh install and re-install need to allow backing up of preferences.
* Previous install time stamp always carry the last last known update time. the value will be zero for any fresh install and will be the last update time with successive opens.
* Previous install time will have a value less than last update time ever since the app is updated.
*
* ------------------------------------------------------------
* | update_state_install | lut <= fit, fit = oit, put = 0 |
* --------------------------- --------------------------------
* | update_state_reinstall | oit < fit, put = 0 |
* --------------------------- --------------------------------
* | update_state_update | lut > fit, put < lut |
* --------------------------- --------------------------------
* | update_state_no_update | lut == put |
* --------------------------- --------------------------------
* @param post Post body for init request which need to be updated
* @throws JSONException when there is any exception on adding time stamps or update state
*/
private void updateInstallStateAndTimestamps(JSONObject post) throws JSONException {
// Default, just a regular open
int installOrUpdateState = STATE_NO_CHANGE;

String currAppVersion = DeviceInfo.getInstance().getAppVersion();
long updateBufferTime = (24 * 60 * 60 * 1000); // Update buffer time is a day.

long updateBufferTime = (24 * 60 * 60 * 1000); // Update buffer time is a day.
long firstInstallTime = DeviceInfo.getInstance().getFirstInstallTime();
long lastUpdateTime = DeviceInfo.getInstance().getLastUpdateTime();

if (PrefHelper.NO_STRING_VALUE.equals(prefHelper_.getAppVersion())) {
// Default, just register an install
// if no app version is in storage, this must be the first time Branch is here, register an install
installOrUpdateState = STATE_FRESH_INSTALL;
// if no app version is in storage, this must be the first time Branch is here. 24 hour buffer for updating as an update state

// However, if package info tells us that last update time is not the same as first install time
// then, from the users perspective, this is an `update` version of the app that happens to have
// Branch in it for the first time, so we record the session as 'update'.
if ((lastUpdateTime - firstInstallTime) >= updateBufferTime) {
installOrUpdateState = STATE_UPDATE;
}

// Finally, we check if this is the first session after a TUNE-> Branch migration, in which
// case server expects a special value.
if (isTuneMigration()) {
installOrUpdateState = STATE_TUNE_MIGRATION;
}

} else if (!prefHelper_.getAppVersion().equals(currAppVersion)) {
// if the current app version doesn't match the stored, it's an update
// if the current app version doesn't match the stored version, then it's an update
installOrUpdateState = STATE_UPDATE;
}

post.put(Defines.Jsonkey.Update.getKey(), installOrUpdateState);
post.put(Defines.Jsonkey.FirstInstallTime.getKey(), firstInstallTime);
post.put(Defines.Jsonkey.LastUpdateTime.getKey(), lastUpdateTime);

// only available when backing up of prefs is allowed (default on Android but users can override with allowBackup=false in manifest)
long originalInstallTime = prefHelper_.getLong(PrefHelper.KEY_ORIGINAL_INSTALL_TIME);
if (originalInstallTime == 0) {
originalInstallTime = firstInstallTime;
Expand All @@ -259,6 +267,14 @@ private void updateInstallStateAndTimestamps(JSONObject post) throws JSONExcepti
post.put(Defines.Jsonkey.PreviousUpdateTime.getKey(), prefHelper_.getLong(PrefHelper.KEY_PREVIOUS_UPDATE_TIME));
}

private boolean isTuneMigration() {
// getApplicationContext() matters here
SharedPreferences tunePrefs = context_.getApplicationContext().getSharedPreferences(
"com.mobileapptracking", Context.MODE_PRIVATE);
final String tuneID = tunePrefs.getString("mat_id", null);
return !TextUtils.isEmpty(tuneID);
}

@Override
protected boolean prepareExecuteWithoutTracking() {
JSONObject post = getPost();
Expand Down
9 changes: 9 additions & 0 deletions ChangeLog.md
@@ -1,4 +1,13 @@
# Branch Android SDK change log
- v5.0.1
* _*Master Release*_ - March 8, 2020
* Report GAID when test key is used
* Detect TUNE migrations, report them via the `update` field in open/install payload
* Deprecate enableSimulateInstalls
* Deprecate enableDebugMode
* Modify enableTestMode
* Support for air-preload campaigns via Play Install Referrer API

- v5.0.0
* _*Master Release*_ - March 17, 2020
* Bump up major version to signify switch to session builder from initSession (old functionality is maintained)
Expand Down
4 changes: 2 additions & 2 deletions gradle.properties
@@ -1,5 +1,5 @@
VERSION_NAME=5.0.0
VERSION_CODE=050000
VERSION_NAME=5.0.1
VERSION_CODE=050001
GROUP=io.branch.sdk.android

POM_DESCRIPTION=Use the Branch SDK (branch.io) to create and power the links that point back to your apps for all of these things and more. Branch makes it incredibly simple to create powerful deep links that can pass data across app install and open while handling all edge cases (using on desktop vs. mobile vs. already having the app installed, etc). Best of all, it is really simple to start using the links for your own app: only 2 lines of code to register the deep link router and one more line of code to create the links with custom data.
Expand Down

0 comments on commit b06e01c

Please sign in to comment.