建立指向特定目的地的深層連結

在 Android 中,深層連結是可讓您直接連往應用程式的特定目的地的連結。

瀏覽元件可讓您建立兩種不同的深層連結:明顯隱含

建立明確深層連結

明確深層連結是深層連結的一種執行個體,會使用 PendingIntent 將使用者帶往應用程式中的特定位置。舉例來說,您可以在通知或應用程式小工具中顯示明確深層連結。

當使用者透過明確深層連結開啟應用程式時,系統會清除工作返回堆疊,並替換為深層連結的目的地。在建立巢狀結構圖時,每個巢狀結構層級的起始目的地也會新增至堆疊中(即階層中每個 <navigation> 元素的開始目的地)。也就是說,當使用者按下深層連結目的地中的「Back」按鈕時,就會返回導覽堆疊的上一個位置,就如同從進入點進入應用程式時一樣。

您可以使用 NavDeepLinkBuilder 類別建構 PendingIntent,如下方範例所示。請注意,如果提供的內容並非 Activity,建構函式則會使用 PackageManager.getLaunchIntentForPackage() (如果有) 做為預設的啟動活動。

Kotlin

val pendingIntent = NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.android)
    .setArguments(args)
    .createPendingIntent()

Java

PendingIntent pendingIntent = new NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.android)
    .setArguments(args)
    .createPendingIntent();

根據預設,NavDeepLinkBuilder 會將明確深層連結作為預設啟動 Activity,其已在應用程式資訊清單中宣告。如果 NavHost 處於其他的活動中,則必須在建立深層連結建構工具時指定其元件名稱:

Kotlin

val pendingIntent = NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.android)
    .setArguments(args)
    .setComponentName(DestinationActivity::class.java)
    .createPendingIntent()

Java

PendingIntent pendingIntent = new NavDeepLinkBuilder(context)
        .setGraph(R.navigation.nav_graph)
        .setDestination(R.id.android)
        .setArguments(args)
        .setComponentName(DestinationActivity.class)
        .createPendingIntent();

如果已有 ComponentName,可以直接將其傳送至建構工具:

Kotlin

val componentName = ...

val pendingIntent = NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.android)
    .setArguments(args)
    .setComponentName(componentName)
    .createPendingIntent()

Java

ComponentName componentName = ...;

PendingIntent pendingIntent = new NavDeepLinkBuilder(context)
        .setGraph(R.navigation.nav_graph)
        .setDestination(R.id.android)
        .setArguments(args)
        .setComponentName(componentName)
        .createPendingIntent();

如果已有 NavController,也可以使用 NavController.createDeepLink() 建立深層連結。

建立隱含深層連結

隱含深層連結是指應用程式中特定的目的地。在叫用深層連結時 (例如當使用者點選連結時),Android 就可以將應用程式開啟至對應的目的地。

深層連結可依 URI、意圖動作及 MIME 類型進行比對符合。可以為單一的深層連結指定多個比對類型,但請注意,系統會優先比對 URI 引數,接著是操作,然後是 MIME 類型。

以下是含有 URI、操作及 MIME 類型的深層連結範例:

<fragment android:id="@+id/a"
          android:name="com.example.myapplication.FragmentA"
          tools:layout="@layout/a">
        <deepLink app:uri="www.example.com"
                app:action="android.intent.action.MY_ACTION"
                app:mimeType="type/subtype"/>
</fragment>

您也可以使用導覽編輯器建立前往目的地的隱含深層連結,如下所示:

  1. 在導覽編輯器的「Design」分頁中,選取深層連結的目的地。
  2. 在「Attributes」面板的「Deep Links」部分中按一下「+」
  3. 在隨即出現的「Add Deep Link」對話方塊中,輸入深層連結的相關資訊。

    請注意以下事項:

    • 系統會將無配置的 URI 視為 http 或 https。例如,www.google.com 可符合 http://www.google.comhttps://www.google.com兩者。
    • {placeholder_name} 格式的路徑參數預留位置符合一個或多個字元。例如,http://www.example.com/users/{id} 符合 http://www.example.com/users/4。瀏覽元件會嘗試比對預留位置名稱與定義的引數(針對深層連結目的地所定義),從而將預留位置的值剖析為適當的類型。如果不具有定義相同名稱的引數,引數值會使用預設的 String 類型。可以使用 .* 萬用字元來比對 0 個以上的字元。
    • 可以使用查詢參數預留位置來取代路徑參數,也可以搭配路徑參數使用。例如,http://www.example.com/users/{id}?myarg={myarg} 符合 http://www.example.com/users/4?myarg=28
    • 使用預設值或空值定義的查詢變數參數預留位置則不需進行比對。舉例來說,http://www.example.com/users/{id}?arg1={arg1}&arg2={arg2}http://www.example.com/users/4?arg2=28http://www.example.com/users/4?arg1=7 相符。但具有路徑參數則否。舉例來說,http://www.example.com/users?arg1=7&arg2=28 並不符合上述模式,因為未提供必要路徑參數。
    • 多餘的查詢參數不會影響深層連結 URI 比對。舉例來說,即使 URI 模式中並未定義 extraneousParamhttp://www.example.com/users/{id} 也能與 http://www.example.com/users/4?extraneousParam=7 相符。
  4. (選用) 勾選「Auto Verify」,要求 Google 驗證您是 URI 的擁有者。詳情請參閱「驗證 Android 應用程式連結」。

  5. 按一下「Add」。連結圖示 會顯示在所選目的地上方,表示該目的地設有深層連結。

  6. 按一下「Code」分頁標籤,切換至 XML 檢視畫面。具有巢狀結構的 <deepLink> 元素已新增至目的地:

    <deepLink app:uri="https://www.google.com" />
    

如要啟用隱含深層連結,還必須在應用程式的 manifest.xml 檔案中新增內容。將單一 <nav-graph> 元素新增至指向現有瀏覽圖的活動,如以下範例所示:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication">

    <application ... >

        <activity name=".MainActivity" ...>
            ...

            <nav-graph android:value="@navigation/nav_graph" />

            ...

        </activity>
    </application>
</manifest>

建構專案時,Navigation 元件會將 <nav-graph> 元素替換成產生的 <intent-filter> 元素,以符合導覽圖中的所有深層連結。

觸發隱含深層連結時,返回堆疊的狀態取決於是否使用 Intent.FLAG_ACTIVITY_NEW_TASK 旗標啟動隱式 Intent

  • 如果設定了旗標,系統會清除工作返回堆疊,並以深層連結目的地取代。與明確深層連結一樣,在為圖表建立巢狀結構時,每個巢狀結構層級的起始目的地 (即階層中每個 <navigation> 元素的起始目的地) 也會新增至堆疊中。也就是說,當使用者按下深層連結目的地中的「Back」按鈕時,就會瀏覽回返回堆疊,就像從進入點進入應用程式一樣。
  • 如未設定旗標,此時仍會保留在上個應用程式的工作堆疊中,其中觸發了隱含深層連結,在此情況下,「Back」按鈕會將使用者帶回到上一個應用程式,而「Up」按鈕則會在導覽圖的階層父項目的地上啟動應用程式的工作。

處理深層連結

使用瀏覽時,強烈建議您一律使用 standard 的預設 launchMode。使用 standard 啟動模式時,瀏覽會呼叫 handleDeepLink() 以處理 Intent 內的任何明確或隱含深層連結,以自動處理深層連結。不過,如果在使用替代的 launchMode (例如 singleTop) 時重新使用了 Activity,系統並不會自動執行這項操作。在此情況下,必須在 onNewIntent() 中手動呼叫 handleDeepLink(),如下例所示:

Kotlin

override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    navController.handleDeepLink(intent)
}

Java

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    navController.handleDeepLink(intent);
}

其他資源

如要進一步瞭解導覽功能,請參閱下列資源。

範例

程式碼研究室

影片