From 0544528f341588168294af0157dd49bf04240e25 Mon Sep 17 00:00:00 2001 From: charliecruzan-stripe <97612659+charliecruzan-stripe@users.noreply.github.com> Date: Tue, 16 Jan 2024 10:48:17 -0800 Subject: [PATCH] Create android-chrome-tab-closes-on-background.md --- ...android-chrome-tab-closes-on-background.md | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 docs/android-chrome-tab-closes-on-background.md diff --git a/docs/android-chrome-tab-closes-on-background.md b/docs/android-chrome-tab-closes-on-background.md new file mode 100644 index 000000000..5acaf8d4d --- /dev/null +++ b/docs/android-chrome-tab-closes-on-background.md @@ -0,0 +1,81 @@ +## The problem + +You're likely running into the same problem from https://github.com/stripe/stripe-react-native/issues/355 where a Chrome custom tab (web browser) is launched from your app's Stripe flow, like to perform 3DSecure confirmation, and if the app is backgrounded, that web browser gets killed. + +## The solution + +If your Android `launchMode` is set to `singleTask` (check your `AndroidManifest.xml`), that's why this is occurring. Unfortunately, this is not addressable by the Stripe React Native library. + +Luckily, [@stianjensen shared a fix in the above Github issue](https://github.com/stripe/stripe-react-native/issues/355#issuecomment-1701323254). It is summarized here: + +1. Modify your `MainApplication`: + +```diff +public class MainApplication extends Application { ++ private ArrayList runningActivities = new ArrayList<>(); + ++ public void addActivityToStack (Class cls) { ++ if (!runningActivities.contains(cls)) runningActivities.add(cls); ++ } + ++ public void removeActivityFromStack (Class cls) { ++ if (runningActivities.contains(cls)) runningActivities.remove(cls); ++ } + ++ public boolean isActivityInBackStack (Class cls) { ++ return runningActivities.contains(cls); ++ } +} +``` + +2. create `LaunchActivity` + +```diff ++ public class LaunchActivity extends Activity { ++ @Override ++ protected void onCreate(Bundle savedInstanceState) { ++ super.onCreate(savedInstanceState); ++ BaseApplication application = (BaseApplication) getApplication(); ++ // check that MainActivity is not started yet ++ if (!application.isActivityInBackStack(MainActivity.class)) { ++ Intent intent = new Intent(this, MainActivity.class); ++ startActivity(intent); ++ } ++ finish(); ++ } ++ } +``` + +3. Modify `AndroidManifest.xml` and move `android.intent.action.MAIN` and `android.intent.category.LAUNCHER` from your `.MainActivity` to `.LaunchActivity` + +```diff ++ ++ ++ ++ ++ ++ + +... +- +- +- +- +... +``` + +4. Modify `MainActivity` to look _something_ like the following (you likely already have an `onCreate` method that you need to modify): + +``` + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(null); + ((BaseApplication) getApplication()).addActivityToStack(this.getClass()); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + ((BaseApplication) getApplication()).removeActivityFromStack(this.getClass()); + } +```