从 1.2.0 版开始,Navigation 3 支持使用 DeepLinkRequest 和
DeepLinkMatcher 类深层链接到
应用中的目的地。
如需在应用中支持深层链接,请完成以下步骤:
- 在
AndroidManifest.xml中定义 intent 过滤器 ,以指定应用可以处理哪些 URI。 - 创建
DeepLinkMatcher实例,以将传入请求映射到您的 导航键。 - 在 activity 的
onCreate或onNewIntent方法中匹配传入请求 ,并相应地更新返回堆栈。
创建 DeepLinkRequest
DeepLinkRequest 表示传入的深层链接。它包含
DeepLinkUri和可选的RequestExtras,其中包含其他
信息,例如 intent 操作或 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 extra
如需存储与深层链接相关的其他信息,请使用
RequestExtras 类。为了使定义和实例化 extra 类型安全,
该库提供了 RequestExtrasKey 接口和
requestExtras DSL。
此外,该库还提供了两个 extra 键和关联的帮助程序:
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) 运算符组合 extra。
从 Intent 创建 DeepLinkRequest
在 Android 上,您可以直接从 Intent 创建 DeepLinkRequest。以这种方式构造时,DeepLinkRequest 的构建方式如下:
uri是从 intent 的data字段复制的。- 如果 MIME 类型和操作 extra 不为 null,则会从 相应的 intent 字段进行设置。
- 所有具有非 null 值的
intent.extras都会另存为SavedState中的DeepLinkRequest.IntentExtrasKey。 - 使用
extras参数提供的任何其他 extra 都会添加。
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 用于构建合成返回堆栈。该库还
支持自定义匹配器,以用于内置
匹配器未涵盖的用例。
如需了解详情,请参阅创建 DeepLinkMatcher。
添加 intent 过滤器
如需启用深层链接以启动 activity,您必须在应用的 AndroidManifest.xml 中定义匹配的
<intent-filter> 元素。如需了解更多
信息,请参阅为传入链接添加 intent 过滤器。
匹配传入请求
创建 您的 DeepLinkMatcher 实例后,您可以在 activity 中匹配
传入请求。
如需匹配传入请求,请完成以下步骤:
- 实例化
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) } } }