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

在 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 是否透過 Intent.FLAG_ACTIVITY_NEW_TASK 旗標啟動:

  • 如果設定了旗標,系統會清除工作返回堆疊,並以深層連結目的地取代。與明確深層連結一樣,在為圖表建立巢狀結構時,每個巢狀結構層級的起始目的地 (即階層中每個 <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);
}

其他資源

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

範例

程式碼研究室

影片