From f32f3a03b1bb73cd579c54cfe675b3e5c6b949ae Mon Sep 17 00:00:00 2001 From: Sharon Cohen Date: Thu, 31 Dec 2020 18:18:12 +0200 Subject: [PATCH 1/5] fix - initial link when launched from history --- .../ReactNativeFirebaseDynamicLinksModule.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java b/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java index e625f42097..1b54d909a7 100644 --- a/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java +++ b/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java @@ -42,6 +42,7 @@ public class ReactNativeFirebaseDynamicLinksModule extends ReactNativeFirebaseMo private String initialLinkUrl = null; private boolean gotInitialLink = false; private int initialLinkMinimumVersion = 0; + private boolean launchedFromHistory = false; ReactNativeFirebaseDynamicLinksModule(ReactApplicationContext reactContext) { super(reactContext, TAG); @@ -107,7 +108,7 @@ public void buildShortLink(ReadableMap dynamicLinkMap, String shortLinkType, Pro @ReactMethod public void getInitialLink(Promise promise) { if (gotInitialLink) { - if (initialLinkUrl != null) { + if (initialLinkUrl != null && !launchedFromHistory) { promise.resolve(dynamicLinkToWritableMap(initialLinkUrl, initialLinkMinimumVersion)); } else { promise.resolve(null); @@ -122,6 +123,9 @@ public void getInitialLink(Promise promise) { return; } + Intent currentIntent = currentActivity.getIntent(); + launchedFromHistory = currentIntent != null && (currentIntent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0; + FirebaseDynamicLinks.getInstance().getDynamicLink(currentActivity.getIntent()) .addOnCompleteListener(task -> { if (task.isSuccessful()) { @@ -133,7 +137,7 @@ public void getInitialLink(Promise promise) { initialLinkMinimumVersion = pendingDynamicLinkData.getMinimumAppVersion(); } - if (initialLinkUrl != null) { + if (initialLinkUrl != null && !launchedFromHistory) { promise.resolve(dynamicLinkToWritableMap(initialLinkUrl, initialLinkMinimumVersion)); } else { promise.resolve(null); From ce6b52414247de867f673f0698d3af85974010a7 Mon Sep 17 00:00:00 2001 From: Sharon Cohen Date: Fri, 1 Jan 2021 23:31:44 +0200 Subject: [PATCH 2/5] fix - getInitialLink sometimes returns null --- ...ReactNativeFirebaseDynamicLinksModule.java | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java b/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java index 1b54d909a7..57a5629aff 100644 --- a/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java +++ b/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java @@ -40,9 +40,10 @@ public class ReactNativeFirebaseDynamicLinksModule extends ReactNativeFirebaseMo private static final String SHORT_LINK_TYPE_UNGUESSABLE = "UNGUESSABLE"; private String initialLinkUrl = null; - private boolean gotInitialLink = false; private int initialLinkMinimumVersion = 0; private boolean launchedFromHistory = false; + private boolean hostResumed = false; + private Promise initialPromise = null; ReactNativeFirebaseDynamicLinksModule(ReactApplicationContext reactContext) { super(reactContext, TAG); @@ -107,13 +108,8 @@ public void buildShortLink(ReadableMap dynamicLinkMap, String shortLinkType, Pro @ReactMethod public void getInitialLink(Promise promise) { - if (gotInitialLink) { - if (initialLinkUrl != null && !launchedFromHistory) { - promise.resolve(dynamicLinkToWritableMap(initialLinkUrl, initialLinkMinimumVersion)); - } else { - promise.resolve(null); - } - + if(!hostResumed) { + initialPromise = promise; return; } @@ -122,14 +118,12 @@ public void getInitialLink(Promise promise) { promise.resolve(null); return; } - Intent currentIntent = currentActivity.getIntent(); launchedFromHistory = currentIntent != null && (currentIntent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0; - FirebaseDynamicLinks.getInstance().getDynamicLink(currentActivity.getIntent()) + FirebaseDynamicLinks.getInstance().getDynamicLink(currentIntent) .addOnCompleteListener(task -> { if (task.isSuccessful()) { - gotInitialLink = true; PendingDynamicLinkData pendingDynamicLinkData = task.getResult(); if (pendingDynamicLinkData != null) { @@ -373,8 +367,9 @@ private void buildSocialParameters( @Override public void onHostDestroy() { initialLinkUrl = null; - gotInitialLink = false; initialLinkMinimumVersion = 0; + launchedFromHistory = false; + initialPromise = null; } @Override @@ -401,9 +396,15 @@ public void onActivityResult(Activity activity, int requestCode, int resultCode, @Override public void onHostResume() { + hostResumed = true; + if(initialPromise != null) { + getInitialLink(initialPromise); + initialPromise = null; + } } @Override public void onHostPause() { + hostResumed = false; } } From e23e900b6ba82a8fba00fb68911d5492e1168260 Mon Sep 17 00:00:00 2001 From: Sharon Cohen Date: Sat, 2 Jan 2021 00:12:29 +0200 Subject: [PATCH 3/5] add - line space --- .../dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java b/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java index 57a5629aff..13c216d808 100644 --- a/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java +++ b/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java @@ -118,6 +118,7 @@ public void getInitialLink(Promise promise) { promise.resolve(null); return; } + Intent currentIntent = currentActivity.getIntent(); launchedFromHistory = currentIntent != null && (currentIntent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0; From e484c95142d9de1a7021c5f395f2fa18fb593fda Mon Sep 17 00:00:00 2001 From: Sharon Cohen Date: Wed, 6 Jan 2021 23:10:43 +0200 Subject: [PATCH 4/5] fix - getInitial link guards and add comments --- ...ReactNativeFirebaseDynamicLinksModule.java | 47 ++++++++++++++++++- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java b/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java index 13c216d808..ef56b007eb 100644 --- a/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java +++ b/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java @@ -41,8 +41,25 @@ public class ReactNativeFirebaseDynamicLinksModule extends ReactNativeFirebaseMo private String initialLinkUrl = null; private int initialLinkMinimumVersion = 0; - private boolean launchedFromHistory = false; + + /** + * Ensures calls to getInitialLink only tries to retrieve the link from getDynamicLink once. + */ + private boolean gotInitialLink = false; + /** + * Used by getInitialLink to check if the activity has been resumed. + * "host" here refers to the host activity. + */ private boolean hostResumed = false; + /** + * Used by getInitialLink to check the current activity's intent flags to verify that the app + * hasn't been resumed from the Overview (history) screen. + */ + private boolean launchedFromHistory = false; + /** + * Holds the Promise that was passed to getInitialLink + * if getInitialLink was called before {@link com.facebook.react.common.LifecycleState#RESUMED} Lifecycle state. + */ private Promise initialPromise = null; ReactNativeFirebaseDynamicLinksModule(ReactApplicationContext reactContext) { @@ -108,23 +125,39 @@ public void buildShortLink(ReadableMap dynamicLinkMap, String shortLinkType, Pro @ReactMethod public void getInitialLink(Promise promise) { + // Check if getDynamicLink() has already completed successfully. + // This ensures the initial link is returned once, if found. + if (gotInitialLink) { + promise.resolve(null); + return; + } + + // Check for the case where getInitialLink + // runs before the LifeCycleState is RESUMED (e.g. BEFORE_CREATE or BEFORE_RESUME). if(!hostResumed) { + // Use initialPromise to store the Promise that was passed and + // run it when LifeCycleState changes to RESUMED in onHostResume. initialPromise = promise; return; } Activity currentActivity = getCurrentActivity(); + // Shouldn't happen anymore, left as a guard. if (currentActivity == null) { promise.resolve(null); return; } - + Intent currentIntent = currentActivity.getIntent(); + // Verify if the app was resumed from the Overview (history) screen. launchedFromHistory = currentIntent != null && (currentIntent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0; FirebaseDynamicLinks.getInstance().getDynamicLink(currentIntent) .addOnCompleteListener(task -> { if (task.isSuccessful()) { + // Flag that the getDynamicLink() completed successfully, + // preventing future calls to from receiving the link, as if the link had been cleared. + gotInitialLink = true; PendingDynamicLinkData pendingDynamicLinkData = task.getResult(); if (pendingDynamicLinkData != null) { @@ -132,6 +165,8 @@ public void getInitialLink(Promise promise) { initialLinkMinimumVersion = pendingDynamicLinkData.getMinimumAppVersion(); } + // Guard against the scenario where the app was launched using a dynamic link, + // then, the app was backgrounded using the Back button, and resumed from the Overview (screen). if (initialLinkUrl != null && !launchedFromHistory) { promise.resolve(dynamicLinkToWritableMap(initialLinkUrl, initialLinkMinimumVersion)); } else { @@ -368,9 +403,11 @@ private void buildSocialParameters( @Override public void onHostDestroy() { initialLinkUrl = null; + gotInitialLink = false; initialLinkMinimumVersion = 0; launchedFromHistory = false; initialPromise = null; + hostResumed = false; } @Override @@ -397,15 +434,21 @@ public void onActivityResult(Activity activity, int requestCode, int resultCode, @Override public void onHostResume() { + // Flag state is resumed. hostResumed = true; + // Check if getInitialLink was called before LifeCycleState was RESUMED + // and there's a pending Promise. if(initialPromise != null) { + // Call getInitialLink getInitialLink with the Promise that was passed in the original call. getInitialLink(initialPromise); + // Clear the Promise initialPromise = null; } } @Override public void onHostPause() { + // Flag state is not resumed. hostResumed = false; } } From 8ecff6eed4486bde0a401757d82ae835d4d76698 Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Mon, 25 Jan 2021 10:10:29 -0500 Subject: [PATCH 5/5] Apply suggestions from code review --- .../ReactNativeFirebaseDynamicLinksModule.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java b/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java index ef56b007eb..3f2dab3c3e 100644 --- a/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java +++ b/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java @@ -47,8 +47,8 @@ public class ReactNativeFirebaseDynamicLinksModule extends ReactNativeFirebaseMo */ private boolean gotInitialLink = false; /** - * Used by getInitialLink to check if the activity has been resumed. - * "host" here refers to the host activity. + * Used by getInitialLink to check if the activity has been resumed. + * "host" refers to the host activity, in terms of {@link LifeCycleEventListener#onHostResume()} */ private boolean hostResumed = false; /** @@ -134,7 +134,7 @@ public void getInitialLink(Promise promise) { // Check for the case where getInitialLink // runs before the LifeCycleState is RESUMED (e.g. BEFORE_CREATE or BEFORE_RESUME). - if(!hostResumed) { + if (!hostResumed) { // Use initialPromise to store the Promise that was passed and // run it when LifeCycleState changes to RESUMED in onHostResume. initialPromise = promise; @@ -150,7 +150,7 @@ public void getInitialLink(Promise promise) { Intent currentIntent = currentActivity.getIntent(); // Verify if the app was resumed from the Overview (history) screen. - launchedFromHistory = currentIntent != null && (currentIntent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0; + launchedFromHistory = (currentIntent != null) && ((currentIntent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0); FirebaseDynamicLinks.getInstance().getDynamicLink(currentIntent) .addOnCompleteListener(task -> { @@ -438,7 +438,7 @@ public void onHostResume() { hostResumed = true; // Check if getInitialLink was called before LifeCycleState was RESUMED // and there's a pending Promise. - if(initialPromise != null) { + if (initialPromise != null) { // Call getInitialLink getInitialLink with the Promise that was passed in the original call. getInitialLink(initialPromise); // Clear the Promise