Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Navigation components : Deeplink using uri depending buildType

Tags:

Any way to read a constant depending buildType ${deepLinkHost}?

debug -> deepLinkUri = http://link.debug/
staging -> deepLinkUri = http://link.staging/
release ->  deepLinkUri=  http://link/
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/navigation_home"
    app:startDestination="@id/fragment_home">

    <fragment
        android:id="@+id/fragment_home"
        android:name="..."
        tools:layout="@layout/fragment_home">
        <argument
            android:name="token"
            android:defaultValue="@null"
            app:argType="string"
            app:nullable="true" />
        <deepLink app:uri="${deepLinkUri}/?code={token}" />
</fragment>

This was manage before with manifestPlaceholders.deepLinkHost on build.gradle and deeplinks by activity in the AndroidManifest, but once google uses 1 Activity to N Fragments, how can we manage it with navigation components?

like image 520
rafaelasguerra Avatar asked Sep 08 '19 11:09

rafaelasguerra


People also ask

What is deep link in navigation component?

In Android, a deep link is a link that takes you directly to a specific destination within an app. The Navigation component lets you create two different types of deep links: explicit and implicit.

How do I create a deep URL?

Click Add Navigation Icon, then select Add a Web URL. Give it a name. Click Show URL options, then select "Deeplink app URL." Add your deeplink URL to the textbox labelled "Deeplink app URL" and a backup link to the textbox labelled "URL."

How does deeplink work on Android?

A Deep Link is a URL link that is generated, when anyone clicks on that link our app will be open with a specific activity or a screen. Using this URL we can send a message to our app with parameters. In WhatsApp, we can generate a deep link to send a message to a phone number with some message in it.


1 Answers

It looks like it's not currently supported out of the box, but there is a pretty simple workaround. Normally registering a deep link requires two steps:

  1. Add deepLink to the navigation graph. Since we can't specify any substitution or a @string resource as the uri, let's just define the host name as a variable: <deepLink app:uri="http://{deepLinkHost}/?code={token}" />. This link will match any host and pass deepLinkHost as a parameter.
  2. Register an intent-filter in the AndroidManifest.xml, so our activity actually reacts on the deep link. The recommended approach for the latest android studio is to add <nav-graph android:value="@navigation/nav_graph" /> to the manifest, so it generates necessary intent-filter automatically. It will, however, register our activity to accept links with any host, which is probably not what we want. So instead of doing this, let's go with the standard approach. Basically here we define the intent-filter manually instead of auto-generating it from navigation graph. So we can use manifest substitutions just as we would normally do.

Example

  • debug -> http://link.debug/identification?code=123
  • staging -> http://link.staging/identification?code=123
  • release -> http://link/identification?code=123

and

  • debug -> http://link.debug/banner?id=123
  • staging -> http://link.staging/banner?id=123
  • release -> http://link/banner?id=123

build.gradle

buildTypes {

        debug {
            manifestPlaceholders.deepLinkUri = "http://link.debug"
        }

        staging {
           manifestPlaceholders.deepLinkUri = "http://link.staging"
        }

        release {
           manifestPlaceholders.deepLinkUri = "http://link"
        }
    }

AndroidManifest.xml

 <activity
     android:name=".HomeActivity">
     <intent-filter>
       <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
     </intent-filter>
     <intent-filter>
        <action android:name="android.intent.action.VIEW" />
         <category android:name="android.intent.category.DEFAULT" />
         <category android:name="android.intent.category.BROWSABLE" />
    
         <data
            android:host="${deepLinkUri}"
            android:scheme="https" />
    </intent-filter>   
 </activity>

navigation_main.xml

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/navigation_home"
    app:startDestination="@id/fragment_home">

    <fragment
        android:id="@+id/fragment_home"
        android:name="..."
        tools:layout="@layout/fragment_home">
        <argument
            android:name="deepLinkUri"
            android:defaultValue="@null"
            app:argType="string"
            app:nullable="true" />
        <argument
            android:name="token"
            android:defaultValue="@null"
            app:argType="string"
            app:nullable="true" />
        <deepLink app:uri="{deepLinkUri}/identification?code={token}" />
</fragment>

    <fragment
        android:id="@+id/fragment_marketing"
        android:name="..."
        tools:layout="@layout/fragment_marketing">
        <argument
            android:name="deepLinkUri"
            android:defaultValue="@null"
            app:argType="string"
            app:nullable="true" />
        <argument
            android:name="id"
            app:argType="integer"
            app:nullable="true" />
        <deepLink app:uri="{deepLinkUri}/banner?id={id}" />
</fragment>

22.05.2020 Update: Starting with the gradle plugin version 3.6 the deep link uri cannot contain parameters in scheme and host parts, it will result in Improper use of wildcards and/or placeholders in deeplink URI host error.

Fortunately one can use a wildcard, so to make the approach work again just change the deepLink definition in your nav graph file:

<deepLink app:uri="{deepLinkUri}/banner?id={id}" /> to <deepLink app:uri=".*/banner?id={id}" />

like image 91
esentsov Avatar answered Oct 16 '22 16:10

esentsov