From 1e26e4b59a41a32aed66e8a8efd3986993236ada Mon Sep 17 00:00:00 2001 From: bklastaitis-branch Date: Wed, 13 Nov 2019 19:23:14 -0800 Subject: [PATCH 1/9] self initialize if not yet initialized from on resume to not drop ball when app is launched into and non-launcher activity from the recent apps tray --- .../io/branch/referral/BranchActivityLifecycleObserver.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Branch-SDK/src/main/java/io/branch/referral/BranchActivityLifecycleObserver.java b/Branch-SDK/src/main/java/io/branch/referral/BranchActivityLifecycleObserver.java index d488a6c12..431dec189 100644 --- a/Branch-SDK/src/main/java/io/branch/referral/BranchActivityLifecycleObserver.java +++ b/Branch-SDK/src/main/java/io/branch/referral/BranchActivityLifecycleObserver.java @@ -69,6 +69,12 @@ public void onActivityResumed(@NonNull Activity activity) { branch.getInitState() != Branch.SESSION_STATE.INITIALISED; branch.onIntentReady(activity, grabIntentParams); } + + if (branch.getInitState() == Branch.SESSION_STATE.UNINITIALISED) { + // this is the only place where we self-initialize in case user opens the app from 'recent apps tray' + // and the entry Activity is not the launcher Activity where user placed initSession themselves. + branch.initSession(activity); + } } @Override From 4c039f8f34ff8b3b57c11be29821955d9647130b Mon Sep 17 00:00:00 2001 From: bklastaitis-branch Date: Thu, 14 Nov 2019 15:43:55 -0800 Subject: [PATCH 2/9] added initialization test plan --- Branch-SDK-TestBed/InitializationTestPlan.md | 64 ++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 Branch-SDK-TestBed/InitializationTestPlan.md diff --git a/Branch-SDK-TestBed/InitializationTestPlan.md b/Branch-SDK-TestBed/InitializationTestPlan.md new file mode 100644 index 000000000..03499d056 --- /dev/null +++ b/Branch-SDK-TestBed/InitializationTestPlan.md @@ -0,0 +1,64 @@ +# Test plan for different initialization scenarios + +This is a test plan enlisting possible initialization scenarios. As CSMs +find bugs arising from unforeseen initialization scenarios, this list should be updated. + + +### Assumptions: +* User followed [Android documentation](https://docs.branch.io/apps/android/), +so `initSession` is only called in the `RoutingActivity` (aka `LaunchActivity`). +* Application can have multiple activities (all non-routing activities +will be called `RoutedActivity`) +* Latest Branch SDK version is being used + + +## Scenarios + +##### Application in background + +Test by opening the app via: +* launcher icon +* recent apps tray (not available in cold start) +* push notification + +Cold start: entry point = `RoutingActivity.onCreate` +* Repro: Close app and remove it from the recent apps list +(not 100% guarantee that this will work because manufacturers determine +if application is killed when removed from recents list). Alternatively, +call `adb shell pm clear my.app.package.id` from the command line (this +will also clear cache and stored data). Open app. + + +Warm start: entry point = `RoutingActivity.onCreate` +* Repro: Close app via the back button. Open app. + +Hot start: entry point is either `RoutingActivity.onStart` or `RoutedActivity.onStart` +depending which activity the user was last on. However, if app is opened +via a push notification, the entry point is guaranteed to be `RoutingActivity.onStart`. +* Repro: Close app via the home button. Open app. + + +##### Application in foreground + +Test by opening the app via: +* push notification + +Burning hot start: entry point = either `RoutingActivity.onNewIntent` +or `RoutingActivity.onStart` depending if user is currently on `RoutingActivity` +or `RoutedActivity` respectively. There is one exception, if the user is on +`RoutedActivity` but `RoutingActivity` is still partially visible, then the +entry point will be `RoutingActivity.onNewIntent`. + +There are four possible scenarios the users can find themselves in, +`reInitSession` is either called or not and the user may may currently be +in either `RoutingActivity` or `RoutedActivity`. Note that documentation +gives instructions to use `reInitSession`, however it's a new instruction, +so it may be overlooked by existing users: +* `reInitSession` is not used + * User is in `RoutingActivity` = Branch initialization is expected to FAIL + * User is in `RoutedActivity` = Branch initialization is expected work _unless_ + `RoutingActivity` is still partially visible (e.g. `RoutedActivity` is + semi-transparent or is not using the full screen) +* `reInitSession` is used + * User is in `RoutedActivity` = Branch initialization is expected work + * User is in `RoutingActivity` = Branch initialization is expected work \ No newline at end of file From c5eb22050466fd5e72e8b11d844c32d189e0d836 Mon Sep 17 00:00:00 2001 From: bklastaitis-branch Date: Thu, 14 Nov 2019 17:05:37 -0800 Subject: [PATCH 3/9] add more expected failure scenarios --- Branch-SDK-TestBed/InitializationTestPlan.md | 85 +++++++++++++------- 1 file changed, 56 insertions(+), 29 deletions(-) diff --git a/Branch-SDK-TestBed/InitializationTestPlan.md b/Branch-SDK-TestBed/InitializationTestPlan.md index 03499d056..343e131ef 100644 --- a/Branch-SDK-TestBed/InitializationTestPlan.md +++ b/Branch-SDK-TestBed/InitializationTestPlan.md @@ -1,64 +1,91 @@ -# Test plan for different initialization scenarios +# Test plan for different (re)initialization scenarios This is a test plan enlisting possible initialization scenarios. As CSMs -find bugs arising from unforeseen initialization scenarios, this list should be updated. +find bugs arising from unforeseen initialization scenarios, this list should +be updated. Unless noted, initialization is expected to work in all scenarios. -### Assumptions: -* User followed [Android documentation](https://docs.branch.io/apps/android/), -so `initSession` is only called in the `RoutingActivity` (aka `LaunchActivity`). +## Assumptions set #1: +* User followed [Android documentation](https://docs.branch.io/apps/android/) * Application can have multiple activities (all non-routing activities -will be called `RoutedActivity`) +are called `RoutedActivity`) * Latest Branch SDK version is being used +* `initSession` is only called in the `RoutingActivity.onStart`. -## Scenarios - -##### Application in background - +##### 1. Application in background +``` Test by opening the app via: * launcher icon * recent apps tray (not available in cold start) * push notification - -Cold start: entry point = `RoutingActivity.onCreate` +``` +##### Cold start: * Repro: Close app and remove it from the recent apps list (not 100% guarantee that this will work because manufacturers determine if application is killed when removed from recents list). Alternatively, call `adb shell pm clear my.app.package.id` from the command line (this will also clear cache and stored data). Open app. +* Initialization entry point = `RoutingActivity.onCreate` -Warm start: entry point = `RoutingActivity.onCreate` +##### Warm start: * Repro: Close app via the back button. Open app. +* Initialization entry point = `RoutingActivity.onCreate` -Hot start: entry point is either `RoutingActivity.onStart` or `RoutedActivity.onStart` -depending which activity the user was last on. However, if app is opened -via a push notification, the entry point is guaranteed to be `RoutingActivity.onStart`. +##### Hot start: * Repro: Close app via the home button. Open app. +* Initialization entry point is either `RoutingActivity.onStart` or +`BranchActivityLifecycleObserver.onResume` depending which activity the +user was last on. However, if app is opened via a push notification, the +Initialization entry point is guaranteed to be `RoutingActivity.onStart`. -##### Application in foreground - +##### 2. Application in foreground +``` Test by opening the app via: * push notification - -Burning hot start: entry point = either `RoutingActivity.onNewIntent` +``` +##### Burning hot start: +* Repro: have the app open +* Initialization entry point = either `RoutingActivity.onNewIntent` or `RoutingActivity.onStart` depending if user is currently on `RoutingActivity` or `RoutedActivity` respectively. There is one exception, if the user is on `RoutedActivity` but `RoutingActivity` is still partially visible, then the entry point will be `RoutingActivity.onNewIntent`. There are four possible scenarios the users can find themselves in, -`reInitSession` is either called or not and the user may may currently be -in either `RoutingActivity` or `RoutedActivity`. Note that documentation -gives instructions to use `reInitSession`, however it's a new instruction, -so it may be overlooked by existing users: -* `reInitSession` is not used - * User is in `RoutingActivity` = Branch initialization is expected to FAIL +`reInitSession` is either called or not and the user is currently in +`RoutingActivity` or in `RoutedActivity`. Note that documentation gives +instructions to use `reInitSession`, however it's a new instruction, so +it may be overlooked by existing users. When the latter happens, we may +expect an initialization failure: +* `reInitSession` is not used (i.e. not following documentation) + * User is in `RoutingActivity` = Branch initialization is guaranteed to FAIL * User is in `RoutedActivity` = Branch initialization is expected work _unless_ `RoutingActivity` is still partially visible (e.g. `RoutedActivity` is semi-transparent or is not using the full screen) -* `reInitSession` is used - * User is in `RoutedActivity` = Branch initialization is expected work - * User is in `RoutingActivity` = Branch initialization is expected work \ No newline at end of file + + +## Assumptions set #2: +* User followed [Android documentation](https://docs.branch.io/apps/android/) +* Application can have multiple activities +* Latest Branch SDK version is being used +* `initSession` is called in both `RoutingActivity` and `RoutedActivity` + +##### 1. Application in foreground +``` +Test by opening the app via push notification launching `RoutedActivity`: +* when `RoutedActivity` is currently in foreground +* when `RoutedActivity` is in backstack (e.g. has been launched before +but user is currently on another `RoutedActivity`) +* when `RoutedActivity` is NOT in backstack (e.g. this particular +`RoutedActivity` has NOT been launched before) +``` + +##### Burning hot start: +* Repro: have the app open + +Again, there are expected failures when `reInitSession` is NOT used in `RoutedActivity` +* user is currently in `RoutedActivity` = guaranteed initialization failure +* `RoutedActivity` is in backstack BUT partially visible \ No newline at end of file From 70b7c55aa7b01632b054034d469f4f8b3f5f86ca Mon Sep 17 00:00:00 2001 From: bklastaitis-branch Date: Thu, 14 Nov 2019 17:41:49 -0800 Subject: [PATCH 4/9] some cleanup --- Branch-SDK-TestBed/InitializationTestPlan.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Branch-SDK-TestBed/InitializationTestPlan.md b/Branch-SDK-TestBed/InitializationTestPlan.md index 343e131ef..026af86c7 100644 --- a/Branch-SDK-TestBed/InitializationTestPlan.md +++ b/Branch-SDK-TestBed/InitializationTestPlan.md @@ -10,7 +10,10 @@ be updated. Unless noted, initialization is expected to work in all scenarios. * Application can have multiple activities (all non-routing activities are called `RoutedActivity`) * Latest Branch SDK version is being used -* `initSession` is only called in the `RoutingActivity.onStart`. + + +## Scenario #1: +* `initSession` is only called in `RoutingActivity.onStart`. ##### 1. Application in background @@ -36,9 +39,10 @@ will also clear cache and stored data). Open app. ##### Hot start: * Repro: Close app via the home button. Open app. * Initialization entry point is either `RoutingActivity.onStart` or -`BranchActivityLifecycleObserver.onResume` depending which activity the -user was last on. However, if app is opened via a push notification, the -Initialization entry point is guaranteed to be `RoutingActivity.onStart`. +`BranchActivityLifecycleObserver.onResume` depending on whether `RoutingActivity` +or `RoutedActivity` was in foreground last. However, if app is opened via +a push notification, the Initialization entry point is guaranteed to be +`RoutingActivity.onStart`. ##### 2. Application in foreground @@ -67,10 +71,7 @@ expect an initialization failure: semi-transparent or is not using the full screen) -## Assumptions set #2: -* User followed [Android documentation](https://docs.branch.io/apps/android/) -* Application can have multiple activities -* Latest Branch SDK version is being used +## Scenario #2: * `initSession` is called in both `RoutingActivity` and `RoutedActivity` ##### 1. Application in foreground From 6044482fa4965a61ab9139f1eceade8fed1eeac5 Mon Sep 17 00:00:00 2001 From: bklastaitis-branch Date: Thu, 14 Nov 2019 19:21:03 -0800 Subject: [PATCH 5/9] tiny cleanup --- Branch-SDK-TestBed/InitializationTestPlan.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Branch-SDK-TestBed/InitializationTestPlan.md b/Branch-SDK-TestBed/InitializationTestPlan.md index 026af86c7..20cd66ad8 100644 --- a/Branch-SDK-TestBed/InitializationTestPlan.md +++ b/Branch-SDK-TestBed/InitializationTestPlan.md @@ -5,7 +5,7 @@ find bugs arising from unforeseen initialization scenarios, this list should be updated. Unless noted, initialization is expected to work in all scenarios. -## Assumptions set #1: +## Assumptions: * User followed [Android documentation](https://docs.branch.io/apps/android/) * Application can have multiple activities (all non-routing activities are called `RoutedActivity`) From dd16d79f6493d80ba34efb66edc99988ae82d556 Mon Sep 17 00:00:00 2001 From: bklastaitis-branch Date: Fri, 15 Nov 2019 18:09:35 -0800 Subject: [PATCH 6/9] change name of activities --- Branch-SDK-TestBed/InitializationTestPlan.md | 56 ++++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/Branch-SDK-TestBed/InitializationTestPlan.md b/Branch-SDK-TestBed/InitializationTestPlan.md index 20cd66ad8..40e5dd83c 100644 --- a/Branch-SDK-TestBed/InitializationTestPlan.md +++ b/Branch-SDK-TestBed/InitializationTestPlan.md @@ -7,13 +7,13 @@ be updated. Unless noted, initialization is expected to work in all scenarios. ## Assumptions: * User followed [Android documentation](https://docs.branch.io/apps/android/) -* Application can have multiple activities (all non-routing activities -are called `RoutedActivity`) +* Application can have multiple activities (launcher activity is called +`SplashActivity` and all others are `NextActivity`) * Latest Branch SDK version is being used ## Scenario #1: -* `initSession` is only called in `RoutingActivity.onStart`. +* `initSession` is only called in `SplashActivity.onStart`. ##### 1. Application in background @@ -29,20 +29,20 @@ Test by opening the app via: if application is killed when removed from recents list). Alternatively, call `adb shell pm clear my.app.package.id` from the command line (this will also clear cache and stored data). Open app. -* Initialization entry point = `RoutingActivity.onCreate` +* Initialization entry point = `SplashActivity.onCreate` ##### Warm start: * Repro: Close app via the back button. Open app. -* Initialization entry point = `RoutingActivity.onCreate` +* Initialization entry point = `SplashActivity.onCreate` ##### Hot start: * Repro: Close app via the home button. Open app. -* Initialization entry point is either `RoutingActivity.onStart` or -`BranchActivityLifecycleObserver.onResume` depending on whether `RoutingActivity` -or `RoutedActivity` was in foreground last. However, if app is opened via +* Initialization entry point is either `SplashActivity.onStart` or +`BranchActivityLifecycleObserver.onResume` depending on whether `SplashActivity` +or `NextActivity` was in foreground last. However, if app is opened via a push notification, the Initialization entry point is guaranteed to be -`RoutingActivity.onStart`. +`SplashActivity.onStart`. ##### 2. Application in foreground @@ -52,41 +52,41 @@ Test by opening the app via: ``` ##### Burning hot start: * Repro: have the app open -* Initialization entry point = either `RoutingActivity.onNewIntent` -or `RoutingActivity.onStart` depending if user is currently on `RoutingActivity` -or `RoutedActivity` respectively. There is one exception, if the user is on -`RoutedActivity` but `RoutingActivity` is still partially visible, then the -entry point will be `RoutingActivity.onNewIntent`. +* Initialization entry point = either `SplashActivity.onNewIntent` +or `SplashActivity.onStart` depending if user is currently on `SplashActivity` +or `NextActivity` respectively. There is one exception, if the user is on +`NextActivity` but `SplashActivity` is still partially visible, then the +entry point will be `SplashActivity.onNewIntent`. There are four possible scenarios the users can find themselves in, `reInitSession` is either called or not and the user is currently in -`RoutingActivity` or in `RoutedActivity`. Note that documentation gives +`SplashActivity` or in `NextActivity`. Note that documentation gives instructions to use `reInitSession`, however it's a new instruction, so it may be overlooked by existing users. When the latter happens, we may expect an initialization failure: * `reInitSession` is not used (i.e. not following documentation) - * User is in `RoutingActivity` = Branch initialization is guaranteed to FAIL - * User is in `RoutedActivity` = Branch initialization is expected work _unless_ - `RoutingActivity` is still partially visible (e.g. `RoutedActivity` is + * User is in `SplashActivity` = Branch initialization is guaranteed to FAIL + * User is in `NextActivity` = Branch initialization is expected work _unless_ + `SplashActivity` is still partially visible (e.g. `NextActivity` is semi-transparent or is not using the full screen) ## Scenario #2: -* `initSession` is called in both `RoutingActivity` and `RoutedActivity` +* `initSession` is called in both `SplashActivity` and `NextActivity` ##### 1. Application in foreground ``` -Test by opening the app via push notification launching `RoutedActivity`: -* when `RoutedActivity` is currently in foreground -* when `RoutedActivity` is in backstack (e.g. has been launched before -but user is currently on another `RoutedActivity`) -* when `RoutedActivity` is NOT in backstack (e.g. this particular -`RoutedActivity` has NOT been launched before) +Test by opening the app via push notification launching `NextActivity`: +* when `NextActivity` is currently in foreground +* when `NextActivity` is in backstack (e.g. has been launched before +but user is currently on another `NextActivity`) +* when `NextActivity` is NOT in backstack (e.g. this particular +`NextActivity` has NOT been launched before) ``` ##### Burning hot start: * Repro: have the app open -Again, there are expected failures when `reInitSession` is NOT used in `RoutedActivity` -* user is currently in `RoutedActivity` = guaranteed initialization failure -* `RoutedActivity` is in backstack BUT partially visible \ No newline at end of file +Again, there are expected failures when `reInitSession` is NOT used in `NextActivity` +* user is currently in `NextActivity` = guaranteed initialization failure +* `NextActivity` is in backstack BUT partially visible \ No newline at end of file From ecc470de01603040d1d4096c58dd4577bc431ba6 Mon Sep 17 00:00:00 2001 From: bklastaitis-branch Date: Mon, 18 Nov 2019 18:02:52 -0800 Subject: [PATCH 7/9] changed the release date --- ChangeLog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 391a477de..278d92bc7 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,6 +1,6 @@ # Branch Android SDK change log - v4.2.0 - * _*Master Release*_ - November 13, 2019 + * _*Master Release*_ - November 19, 2019 * Remove initialization race conditions. * Do not auto-initialize sessions, make calling initSession a mandatory step required of Branch SDK users (officially this was already implied). * Overload reInitSession with different callbacks and start advertising it to users as the official way to handle session reinitialization in cases where activity is in foreground and is being reopened. From 637c22dab786ea19042b9b3a5341bf38ccf74e07 Mon Sep 17 00:00:00 2001 From: bklastaitis-branch Date: Tue, 19 Nov 2019 11:24:14 -0800 Subject: [PATCH 8/9] fixed formatting of titles so it follows incremental order --- Branch-SDK-TestBed/InitializationTestPlan.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Branch-SDK-TestBed/InitializationTestPlan.md b/Branch-SDK-TestBed/InitializationTestPlan.md index 40e5dd83c..7a556e429 100644 --- a/Branch-SDK-TestBed/InitializationTestPlan.md +++ b/Branch-SDK-TestBed/InitializationTestPlan.md @@ -16,14 +16,14 @@ be updated. Unless noted, initialization is expected to work in all scenarios. * `initSession` is only called in `SplashActivity.onStart`. -##### 1. Application in background +### 1. Application in background ``` Test by opening the app via: * launcher icon * recent apps tray (not available in cold start) * push notification ``` -##### Cold start: +### Cold start: * Repro: Close app and remove it from the recent apps list (not 100% guarantee that this will work because manufacturers determine if application is killed when removed from recents list). Alternatively, @@ -32,11 +32,11 @@ will also clear cache and stored data). Open app. * Initialization entry point = `SplashActivity.onCreate` -##### Warm start: +### Warm start: * Repro: Close app via the back button. Open app. * Initialization entry point = `SplashActivity.onCreate` -##### Hot start: +### Hot start: * Repro: Close app via the home button. Open app. * Initialization entry point is either `SplashActivity.onStart` or `BranchActivityLifecycleObserver.onResume` depending on whether `SplashActivity` @@ -45,12 +45,12 @@ a push notification, the Initialization entry point is guaranteed to be `SplashActivity.onStart`. -##### 2. Application in foreground +### 2. Application in foreground ``` Test by opening the app via: * push notification ``` -##### Burning hot start: +### Burning hot start: * Repro: have the app open * Initialization entry point = either `SplashActivity.onNewIntent` or `SplashActivity.onStart` depending if user is currently on `SplashActivity` @@ -74,7 +74,7 @@ expect an initialization failure: ## Scenario #2: * `initSession` is called in both `SplashActivity` and `NextActivity` -##### 1. Application in foreground +### 1. Application in foreground ``` Test by opening the app via push notification launching `NextActivity`: * when `NextActivity` is currently in foreground @@ -84,7 +84,7 @@ but user is currently on another `NextActivity`) `NextActivity` has NOT been launched before) ``` -##### Burning hot start: +### Burning hot start: * Repro: have the app open Again, there are expected failures when `reInitSession` is NOT used in `NextActivity` From 49c41c8235b36eecf3ea25858bb05878f25f1ade Mon Sep 17 00:00:00 2001 From: bklastaitis-branch Date: Tue, 19 Nov 2019 11:30:22 -0800 Subject: [PATCH 9/9] further fixed title ordering --- Branch-SDK-TestBed/InitializationTestPlan.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Branch-SDK-TestBed/InitializationTestPlan.md b/Branch-SDK-TestBed/InitializationTestPlan.md index 7a556e429..4bcb0425b 100644 --- a/Branch-SDK-TestBed/InitializationTestPlan.md +++ b/Branch-SDK-TestBed/InitializationTestPlan.md @@ -23,7 +23,7 @@ Test by opening the app via: * recent apps tray (not available in cold start) * push notification ``` -### Cold start: +#### Cold start: * Repro: Close app and remove it from the recent apps list (not 100% guarantee that this will work because manufacturers determine if application is killed when removed from recents list). Alternatively, @@ -32,11 +32,11 @@ will also clear cache and stored data). Open app. * Initialization entry point = `SplashActivity.onCreate` -### Warm start: +#### Warm start: * Repro: Close app via the back button. Open app. * Initialization entry point = `SplashActivity.onCreate` -### Hot start: +#### Hot start: * Repro: Close app via the home button. Open app. * Initialization entry point is either `SplashActivity.onStart` or `BranchActivityLifecycleObserver.onResume` depending on whether `SplashActivity` @@ -50,7 +50,7 @@ a push notification, the Initialization entry point is guaranteed to be Test by opening the app via: * push notification ``` -### Burning hot start: +#### Burning hot start: * Repro: have the app open * Initialization entry point = either `SplashActivity.onNewIntent` or `SplashActivity.onStart` depending if user is currently on `SplashActivity` @@ -84,7 +84,7 @@ but user is currently on another `NextActivity`) `NextActivity` has NOT been launched before) ``` -### Burning hot start: +#### Burning hot start: * Repro: have the app open Again, there are expected failures when `reInitSession` is NOT used in `NextActivity`