13

https://firebase.google.com/docs/dynamic-links/android/receive

states that

Calling getDynamicLink() retrieves the link and clears that data so it is only processed once by your app.

You normally call getDynamicLink() in the main activity as well as any activities launched by intent filters that match the link.

I copied the following code from the doc.

FirebaseDynamicLinks.getInstance()
        .getDynamicLink(getIntent())
        .addOnSuccessListener(this, new OnSuccessListener<PendingDynamicLinkData>() {
            @Override
            public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) {
                // Get deep link from result (may be null if no link is found)
                Uri deepLink = null;
                if (pendingDynamicLinkData != null) {
                    deepLink = pendingDynamicLinkData.getLink();
                }


                // Handle the deep link. For example, open the linked
                // content, or apply promotional credit to the user's
                // account.
                // ...

                // ...
            }
        })
        .addOnFailureListener(this, new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Log.w(TAG, "getDynamicLink:onFailure", e);
            }
        });

If I put the above code on MainActivity:onCreate

  • when app is not running in background, deep link works fine
  • when app is running in background, deep link is not recognized (the onSuccess callback doesn't get called)

If I put the above code on MainActivity:onStart

  • when app is running in background or not, deep link works fine
  • If user clicks deep link, main activity gets it and opens approapriate activity, (works fine) but when he tries to go back to the main activity, onSuccess callback fires again and he never be able to go to the main activity.
eugene
  • 39,839
  • 68
  • 255
  • 489
  • 1
    For the `onCreate()` case, you say `onSuccess()` does not get called. Is `onFailure()` called instead? In my use of `getDynamicLink()`, `onSuccess()` is always called, with the first call containing a `PendingDynamicLinkData` and subsequent calls containing null. – Bob Snyder Jan 06 '18 at 15:34
  • 1
    @BobSnyder no neither onSuccess nor onFailure doesn't get called. – eugene Jan 07 '18 at 08:09
  • 1
    I've got the same issue. I thought that getDynamicLink() clears data but it don't. And every call of this method return the same link every time. It can't be processed once so. – olivejp May 28 '18 at 05:04
  • 1
    @eugene I am facing the same issue, did you solve this issue? Step 1: Received the dynamic link in the app. Step 2: Navigated to the required page. Step 3: App went to the background. Step 4: Opened the app from the background, the app still navigates to the previous dynamic link page. I am using onStart() method – Durga Vundavalli Jul 26 '18 at 07:51
  • I answered this question here: https://stackoverflow.com/a/62985346/1432239 – maclir Jul 19 '20 at 20:32
  • This solution worked for me: https://stackoverflow.com/a/61788281/1839500 – Dick Lucas Sep 04 '20 at 04:05
  • When the App is in Background/Closed and notification contains notification data `onMessageReceived` is never called. Check this topic https://stackoverflow.com/a/37395785/4024146 + this answer about data part: https://stackoverflow.com/a/40083727/4024146 – mtrakal Apr 23 '21 at 12:04

3 Answers3

5

Duplicate the code written in MainActivity:onCreate method (entire Firebase Dynamic Links related code) inside MainActivity:onNewIntent method, this works irrespective of the app is running in the background or not.

Also MainActivity:onNewIntent method is not invoked if the app is not present in background hence no duplicate Firebase call happens.

Your MainActivity should look like this

@Override
protected void onCreate(Bundle savedInstanceState) {
    //...

    FirebaseDynamicLinks.getInstance()
            .getDynamicLink(getIntent())
            .addOnSuccessListener(this, new OnSuccessListener<PendingDynamicLinkData>() {
                @Override
                public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) {
                    // Get deep link from result (may be null if no link is found)
                    Uri deepLink = null;
                    if (pendingDynamicLinkData != null) {
                        deepLink = pendingDynamicLinkData.getLink();
                    }


                    // Handle the deep link. For example, open the linked
                    // content, or apply promotional credit to the user's
                    // account.
                    // ...


            })
            .addOnFailureListener(this, new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    Log.w(TAG, "getDynamicLink:onFailure", e);
                }
            });
}

@Override
protected void onNewIntent(Intent intent) {
    //...

    FirebaseDynamicLinks.getInstance()
            .getDynamicLink(intent)
            .addOnSuccessListener(this, new OnSuccessListener<PendingDynamicLinkData>() {
                @Override
                public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) {
                    // Get deep link from result (may be null if no link is found)
                    Uri deepLink = null;
                    if (pendingDynamicLinkData != null) {
                        deepLink = pendingDynamicLinkData.getLink();
                    }


                    // Handle the deep link. For example, open the linked
                    // content, or apply promotional credit to the user's
                    // account.
                    // ...


            })
            .addOnFailureListener(this, new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    Log.w(TAG, "getDynamicLink:onFailure", e);
                }
            });
}
Naveen Kumar
  • 51
  • 1
  • 5
0

I kept a dirty hack by taking a global url and comparing it next time with new url , It's not perfect but it's the best I came up with .

 var previousDeepLink:String?=null //take it as global and static


    FirebaseDynamicLinks.getInstance()
    .getDynamicLink(getIntent())
    .addOnSuccessListener(this, new OnSuccessListener<PendingDynamicLinkData>() {
        @Override
        public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) {
            // Get deep link from result (may be null if no link is found)
            Uri deepLink = null;
            if (pendingDynamicLinkData != null) {
                deepLink = pendingDynamicLinkData.getLink();
            }

                 if(previousDeepLink==deepLink?.toString()){
                        return@OnSuccessListener
                    }
                    previousDeepLink=deepLink?.toString()



            // Handle the deep link. For example, open the linked
            // content, or apply promotional credit to the user's
            // account.
            // ...

            // ...
        }
    })
    .addOnFailureListener(this, new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            Log.w(TAG, "getDynamicLink:onFailure", e);
        }
    });

                
Manohar
  • 22,116
  • 9
  • 108
  • 144
0

The answer is in the documents:

You must call getDynamicLink() in every activity that might be launched by the link, even though the link might be available from the intent using getIntent().getData(). Calling getDynamicLink() retrieves the link and clears that data so it is only processed once by your app.

You normally call getDynamicLink() in the main activity as well as any activities launched by intent filters that match the link.

John T
  • 814
  • 10
  • 17