firebase / firebase-android-sdk

Firebase Android SDK
https://firebase.google.com
Apache License 2.0
2.28k stars 580 forks source link

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

Closed JCarlosR closed 1 year ago

JCarlosR commented 2 years ago

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

Step 3: Describe the problem

Steps to reproduce:

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.

google-oss-bot commented 2 years ago

I found a few problems with this issue:

argzdev commented 2 years ago

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!

JCarlosR commented 2 years ago

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.

argzdev commented 2 years ago

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!

JCarlosR commented 2 years ago

@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.

argzdev commented 1 year ago

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 commented 1 year ago

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