從 1.2.0 版開始,Navigation 3 支援使用 DeepLinkRequest 和 DeepLinkMatcher 類別,深層連結至應用程式中的目的地。
如要在應用程式中支援深層連結,請完成下列步驟:
- 在
AndroidManifest.xml中定義意圖篩選器,指定應用程式可處理的 URI。 - 建立
DeepLinkMatcher執行個體,將連入要求對應至導覽鍵。 - 在活動的
onCreate或onNewIntent方法中比對傳入的要求,並據此更新返回堆疊。
建立 DeepLinkRequest
DeepLinkRequest 代表傳入的深層連結。其中包含 DeepLinkUri 和選用的 RequestExtras,以及其他資訊,例如意圖動作或 MIME 類型。
// Create a request with a String URI val request = DeepLinkRequest(uri = "https://www.example.com/home") // Create a request from a DeepLinkUri val deepLinkUri = DeepLinkUri("https://www.example.com/home") val requestFromUri = DeepLinkRequest(uri = deepLinkUri) // Create a request with a URI and action val requestWithAction = DeepLinkRequest( uri = "https://www.example.com/home", extras = DeepLinkRequest.actionExtra("android.intent.action.VIEW") ) // Create a request with URI, action and mimeType val requestWithMimeType = DeepLinkRequest( uri = "https://www.example.com/image", extras = requestExtras { put(DeepLinkRequest.ActionExtrasKey, "android.intent.action.VIEW") put(DeepLinkRequest.Companion.MimeTypeExtrasKey, "image/png") } )
提供 DeepLinkRequest 額外內容
如要儲存與深層連結相關的其他資訊,請使用 RequestExtras 類別。為確保定義和例項化額外資訊時的型別安全,程式庫提供 RequestExtrasKey 介面和 requestExtras DSL。
此外,程式庫還提供兩個額外鍵和相關輔助程式:
MimeTypeExtrasKey:用於儲存 MIME 類型String。ActionExtrasKey(僅限 Android):用於儲存Intent的動作String。
val extras: RequestExtras = requestExtras { put(DeepLinkRequest.Companion.MimeTypeExtrasKey, "application/json") put(DeepLinkRequest.ActionExtrasKey, Intent.ACTION_VIEW) } // Access typed values using the get operator val mimeType: String? = extras[DeepLinkRequest.Companion.MimeTypeExtrasKey] val action: String? = extras[DeepLinkRequest.ActionExtrasKey] // Create extras using helper functions and combine them val mimeTypeExtras: RequestExtras = DeepLinkRequest.mimeTypeExtra("application/json") val combinedExtras: RequestExtras = extras + DeepLinkRequest.actionExtra(Intent.ACTION_VIEW)
如要定義自己的自訂 extra,請使用型別泛型實作 RequestExtrasKey 介面:
// Define a custom typed key: object CampaignIdExtrasKey : RequestExtrasKey<String> val customExtras: RequestExtras = requestExtras { put(CampaignIdExtrasKey, "123") } val campaignId: String? = customExtras[CampaignIdExtrasKey]
您也可以使用 emptyRequestExtras() 建構空白執行個體,或使用 + (plus) 和 - (minus) 運算子合併額外資訊。
從 Intent 建立 DeepLinkRequest
在 Android 裝置上,你可以直接從 Intent 建立 DeepLinkRequest。以這種方式建構時,DeepLinkRequest 的建構方式如下:
uri是從意圖的data欄位複製而來。- 如果不是空值,系統會從對應的意圖欄位設定 MIME 類型和動作 extras。
- 所有具有非空值的
intent.extras都會儲存為DeepLinkRequest.IntentExtrasKey中的SavedState。 - 系統會新增使用
extras參數提供的任何額外項目。
object CampaignIdExtrasKey : RequestExtrasKey<String> val intent = Intent(Intent.ACTION_VIEW).apply { data = Uri.parse("https://www.example.com/item/42") type = "application/json" putExtra("user_id", "123") } val request = DeepLinkRequest( intent = intent, extras = requestExtras { put(CampaignIdExtrasKey, "spring_promo") } ) // The resulting DeepLinkRequest contains: val uri = request.uri // "https://www.example.com/item/42" val action = request.extras[DeepLinkRequest.ActionExtrasKey] // "android.intent.action.VIEW" val mimeType = request.extras[DeepLinkRequest.Companion.MimeTypeExtrasKey] // "application/json" val intentExtras: SavedState? = request.extras[DeepLinkRequest.IntentExtrasKey] val userId: String? = intentExtras?.read { getStringOrNull("user_id") } // "123" val campaignId: String? = request.extras[CampaignIdExtrasKey] // "spring_promo"
建立 DeepLinkMatcher 執行個體
DeepLinkMatcher 會將傳入的 DeepLinkRequest 執行個體對應至可新增至應用程式返回堆疊的導覽鍵。Navigation 3 提供三種內建比對器:UriDeepLinkMatcher 用於根據模式比對 URI、StaticKeyDeepLinkMatcher 用於基本連結,以及 BackStackMatcher 用於建構合成返回堆疊。此外,程式庫也支援自訂比對器,適用於內建比對器未涵蓋的用途。
詳情請參閱「建立 DeepLinkMatchers」。
新增意圖篩選器
如要啟用深層連結來啟動活動,您必須在應用程式的 AndroidManifest.xml 中定義相符的 <intent-filter> 元素。詳情請參閱「新增連入連結的意圖篩選器」。
比對傳入要求
建立 DeepLinkMatcher 執行個體後,您可以在活動中比對傳入的要求。
如要比對傳入的要求,請完成下列步驟:
- 例項化
DeepLinkMatcher例項。 - 彙整所有
DeepLinkMatcher執行個體,無論是明確彙整或使用多重繫結。 - 從傳入的
Intent建立DeepLinkRequest。 - 比對所有比對器中的要求,找出最相符的項目。
- 從比對結果建立返回堆疊。
// 1. Instantiate your DeepLinkMatcher instances. val homeMatcher = StaticKeyDeepLinkMatcher(HomeKey, listOf(DeepLinkMatcher.actionFilter(Intent.ACTION_VIEW))) val userProfileMatcher = UriDeepLinkMatcher( DeepLinkUri("www.example.com/users/{id}"), serializer<UserProfileKey>() ).withBackStack { matchResult -> listOf(HomeKey, matchResult.key) } val telMatcher = TelDeepLinkMatcher() // 2. Collate all of your DeepLinkMatcher instances. // Note: Collating matchers with different generic types requires wildcards, // erasing the specific generic types. val deepLinkMatchers: List<DeepLinkMatcher<*, *>> = listOf( homeMatcher, userProfileMatcher, telMatcher ) class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... // 3. Create a DeepLinkRequest from the incoming Intent val request = DeepLinkRequest(intent = intent) // 4. Match the request against all matchers and find the best match. // Because DeepLinkMatcher.MatchResult implements Comparable, you can // use maxOrNull() to find the best match. val matchResult = deepLinkMatchers .mapNotNull { it.match(request) } // List<DeepLinkMatcher.MatchResult<*>> .maxOrNull() // DeepLinkMatcher.MatchResult<*>? // 5. Create the back stack from the match result (or fall back to a default). val backStack: List<NavKey> = when (matchResult) { // If no match is found, use the default back stack (e.g., HomeKey) null -> listOf(HomeKey) // If a BackStackMatchResult is found, use the back stack from the result is BackStackMatchResult<*, *> -> { // Because star-projected matchers erase the key type, cast the back stack to List<NavKey>. @Suppress("UNCHECKED_CAST") matchResult.backStack as List<NavKey> } // Otherwise, use the key from the match result to make a single-item back stack else -> listOf(matchResult.key as NavKey) } } }