firebase-android-sdk icon indicating copy to clipboard operation
firebase-android-sdk copied to clipboard

The getDynamicLink requires an intent or the intent data, depending on how the app was launched

Open JCarlosR opened this issue 2 years ago • 5 comments

Step 1: Are you in the right place?

Yes. Based on the documentation, we should use the following code to parse dynamic links:

Firebase.dynamicLinks
    .getDynamicLink(intent)
    .addOnSuccessListener(this) { pendingDynamicLinkData ->
        // ...
    }

Step 2: Describe your environment

  • Android Studio version
Android Studio Bumblebee | 2021.1.1 Patch 1
Build #AI-211.7628.21.2111.8139111, built on February 1, 2022
Runtime version: 11.0.11+9-b60-7590822 amd64
  • Firebase Component: Dynamic Links
  • Component version:
implementation 'com.google.firebase:firebase-dynamic-links-ktx:21.0.0'

Step 3: Describe the problem

Steps to reproduce:

  • Use the code snippet above to capture dynamic links.
    • Make sure report logs to a server (since LogCat is not available for builds published on Internal Testing).
  • Publish the app on the Internal Testing channel and make sure to have the app uninstalled.
  • Open a dynamic link.
  • It will open the Play Store app.
  • After installing the app, you will notice that the Dynamic Link is not captured by the getDynamicLink method when passing the intent as an argument. But it does work when using intent.data.

Relevant Code:

When I open a dynamic link and the app is uninstalled but then installed from the store, I can get the link and utm params properly, using:

Firebase.dynamicLinks
    .getDynamicLink(intent)
    .addOnSuccessListener(this) { /* ... */ }

However it will not work when opening the dynamic link while the app is installed. For this case, I have to use instead:

intent.data?.let { it ->
    Firebase.dynamicLinks
        .getDynamicLink(it)
        .addOnSuccessListener(this) { /* ... */ }
}

My question is... why is it necessary to register the listeners in both ways in order to parse both scenarios?

From this comment in the getDynamicLink method, I understand than the method itself is responsible for parsing from the intent.data when the information is not available on intent:

  /** 
   * [...]
   * When a dynamic link is clicked by the user, in most cases it is captured when clicked and
   * stored until accessed by {@link #getDynamicLink(Intent)} and returned as the {@link
   * PendingDynamicLinkData} of the {@link Task}. If the dynamic link was not captured, as is the
   * case when App Links launches the app, then the dynamic link is provided in the {@link
   * Intent#getData()}. The intent data is then processed to retrieve the dynamic link data. 
   */

I would like to process the dynamic links from one place.

JCarlosR avatar Feb 24 '22 15:02 JCarlosR

I found a few problems with this issue:

  • I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.
  • This issue does not seem to follow the issue template. Make sure you provide all the required information.

google-oss-bot avatar Feb 24 '22 15:02 google-oss-bot

Hi @JCarlosR, sorry for the late reply. I'm unable to reproduce this issue. I tried to create a clean project with the following relevant code:

fun handleLinks(){
        Firebase.dynamicLinks
            .getDynamicLink(intent)
            .addOnSuccessListener(this) { pendingDynamicLinkData ->
                var deepLink: Uri? = null

                if (pendingDynamicLinkData != null)
                    deepLink = pendingDynamicLinkData.link

                Toast.makeText(this, "handleLink: $deepLink", Toast.LENGTH_LONG).show()
            }
            .addOnFailureListener(this) { e ->Toast.makeText(this, "getDynamicLink onFailure: $e", Toast.LENGTH_LONG).show()}
    }

But in both scenario where the app is installed or uninstalled, I'm able to see the deep link value after the app opens. Am I missing something? Could you provide more details on your code implementation? Or if possible could you provide an MCVE for us to investigate this further? Thanks!

argzdev avatar Mar 07 '22 15:03 argzdev

Thanks for your response @argzdev.

In both scenarios I can get the deep link value, but the utm parameters are missing when I use the code you posted and the app is already installed.

If the app is installed I only get the utm parameters when using intent.data instead of intent.

Please check if you get the utm parameters in both scenarios parsing intent. If you still cannot reprocuce I will prepare a sample project and deep link.

JCarlosR avatar Mar 09 '22 22:03 JCarlosR

Hi @JCarlosR, sorry for the delayed response. I've updated my code where I'm able to retrieve the utm parameters.

Steps:

  1. create a dynamic link - "https://xxxx.xxxx.xxxx/xxxx
  2. this dynamic link have a Deep Link URL - e.g. "https://www.youtube.com/results?search_query=kotlin+await"
  3. Upon opening the app, I am able to retrieve "kotlin+await" from the utm param of "search_query"

Relevant code:

Firebase.dynamicLinks
            .getDynamicLink(intent)
            .addOnSuccessListener(this) { pendingDynamicLinkData ->
                var deepLink: Uri? = null

                if (pendingDynamicLinkData != null)
                    deepLink = pendingDynamicLinkData.link

                val search_query = deepLink?.getQueryParameter("search_query")

                Toast.makeText(this, "search_query: $search_query", Toast.LENGTH_LONG).show()
            }

I used the getQueryParameter command to retrieve any specific utm param that I need. Is this what you needed? or am I missing anything? If this is not what you wanted, could you provide me a minimal repro of the issue? Thanks!

argzdev avatar Apr 19 '22 10:04 argzdev

@argzdev I create the dynamic link without query parameters and then define the UTM params this way:

test_utm

To access the values I use something like this:

private fun parseDynamicLinkData(dynamicLinkData: PendingDynamicLinkData?) {
    val contentLink = dynamicLinkData?.link.toString()
    val utmBundle = dynamicLinkData?.utmParameters ?: Bundle()

    // ...
    // utmBundle["utm_medium"]
    // utmBundle["utm_source"]
    // utmBundle["utm_campaign"]
}

I created a method because I use the same for both callbacks (parsing intent and intent.data). Please see my first message in this page.

JCarlosR avatar Apr 19 '22 16:04 JCarlosR

Hi @JCarlosR, sorry for the radio silence here. I was able to reproduce this same behavior. I'll notify our engineers and see what we can do here. While waiting for a response, FWIW just sharing this code snippet as a workaround:

intent.data?.let { it ->
    getDynamicLinkDetails(it)
} ?: run {
    getDynamicLinkDetails()
}

argzdev avatar Jan 16 '23 15:01 argzdev

Hi folks, we'd like to inform you that the Firebase Dynamic Links service will be shutdown on August 25, 2025. In the meantime, only critical or security issues will be fixed in the SDK.

More at https://firebase.google.com/support/dynamic-links-faq

argzdev avatar Sep 15 '23 15:09 argzdev