Deep Link 与导航
场景
需要实现从浏览器 / 推送通知 / 短信等外部渠道直接跳转到 App 指定页面。
方案
1. 三种 Deep Link 类型
| 类型 | 格式 | 特点 |
|---|---|---|
| URI Scheme | myapp://product/123 | 简单但不安全,任何 App 都能注册 |
| App Links | https://example.com/product/123 | 需域名验证,Android 6.0+ |
| Intent URI | intent://...#Intent;...;end | Chrome 专用 |
2. App Links 配置
<!-- AndroidManifest.xml -->
<activity android:name=".DeepLinkActivity"
android:exported="true">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https"
android:host="example.com"
android:pathPrefix="/product" />
</intent-filter>
</activity>
// 在 https://example.com/.well-known/assetlinks.json 放置验证文件
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.app",
"sha256_cert_fingerprints": ["AA:BB:CC:..."]
}
}]
3. Navigation Deep Link
// Jetpack Navigation 支持声明式 Deep Link
@Composable
fun AppNavHost() {
NavHost(navController, startDestination = "home") {
composable(
route = "product/{id}",
deepLinks = listOf(
navDeepLink { uriPattern = "https://example.com/product/{id}" }
)
) { backStackEntry ->
val id = backStackEntry.arguments?.getString("id")
ProductScreen(id)
}
}
}
4. 常见问题
| 问题 | 解决 |
|---|---|
| 冷启动 Deep Link 延迟 | onCreate 中解析 Intent,启动后直接导航 |
| App 未安装 | 使用 Deferred Deep Link(通过归因平台) |
| 参数丢失 | intent.data 为 null 时的兜底处理 |
| 导航栈异常 | 正确设置 launchMode 或 FLAG_ACTIVITY_CLEAR_TOP |
面试答题要点
- App Links 优于 URI Scheme(安全、直接打开不弹选择器)
- 需要域名验证(
assetlinks.json) - Navigation 支持声明式 Deep Link
- 考虑 App 未安装的 Deferred Deep Link 场景