导航组件:使用 uri 依赖于 buildType 的 Deeplink

rgu*_*rra 20 android deeplink androidx

有什么方法可以读取依赖于 buildType 的常量${deepLinkHost}

debug -> deepLinkUri = http://link.debug/
staging -> deepLinkUri = http://link.staging/
release ->  deepLinkUri=  http://link/
Run Code Online (Sandbox Code Playgroud)
<?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>
Run Code Online (Sandbox Code Playgroud)

这是之前通过 build.gradle 上的 manifestPlaceholders.deepLinkHost 和 AndroidManifest 中的活动深度链接来管理的,但是一旦 google 使用 1 Activity to N Fragments,我们如何使用导航组件来管理它?

ese*_*sov 17

看起来目前不支持开箱即用,但有一个非常简单的解决方法。通常注册一个深层链接需要两个步骤:

  1. 添加deepLink到导航图中。既然我们不能指定任何替换或@string资源的URI,让我们只定义主机名作为变量: <deepLink app:uri="http://{deepLinkHost}/?code={token}" />。此链接将匹配任何主机并deepLinkHost作为参数传递。
  2. 在 中注册一个意图过滤器AndroidManifest.xml,以便我们的活动实际上对深层链接做出反应。最新 android studio 的推荐方法是添加<nav-graph android:value="@navigation/nav_graph" />到清单中,因此它会自动生成必要的意图过滤器。然而,它会注册我们的活动以接受与任何主机的链接,这可能不是我们想要的。因此,与其这样做,不如采用标准方法。基本上在这里我们手动定义意图过滤器,而不是从导航图中自动生成它。所以我们可以像往常一样使用清单替换。

例子

构建.gradle

buildTypes {

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

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

        release {
           manifestPlaceholders.deepLinkUri = "http://link"
        }
    }
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

导航_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>
Run Code Online (Sandbox Code Playgroud)

22.05.2020 更新: 从 gradle 插件 3.6 版本开始,scheme 和 host 部分深度链接 uri 不能包含参数,会导致Improper use of wildcards and/or placeholders in deeplink URI host错误。

幸运的是,可以使用通配符,因此要使该方法再次起作用,只需更改deepLink导航图文件中的定义:

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

  • @esentsov `&lt;deepLink app:uri="${deepLinkUri}` 不适合我,直到我通过删除 `$` 更新为 `&lt;deepLink app:uri="{deepLinkUri}` (2认同)
  • 谢谢@li2,我在答案中修复了它 (2认同)