📌 1. AndroidManifest.xml 中配置 Intent Filter 支持网页唤起
在目标 Activity 中必须声明 android.intent.action.VIEW 以及 DEFAULT 和 BROWSABLE 类别,方能被网页拉起:
<activity android:name=".DetailActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- 配置自定义 scheme 与 host -->
<data android:scheme="myapp"
android:host="page"
android:pathPrefix="/detail" />
</intent-filter>
</activity>
🛠️ 2. Android 原生 WebViewClient 拦截与跳转处理代码 (Kotlin)
默认 WebView 无法直接处理 intent:// 和自定义 Scheme(会触发 net::ERR_UNKNOWN_URL_SCHEME)。需重写 shouldOverrideUrlLoading:
webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
val url = request?.url?.toString() ?: return false
// 1. 如果是常规 http / https,直接走网页渲染
if (url.startsWith("http://") || url.startsWith("https://")) {
return false
}
// 2. 如果是 intent:// 协议 (Chrome Android Intent)
if (url.startsWith("intent://")) {
try {
val intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME)
if (intent != null) {
view?.context?.startActivity(intent)
return true
}
} catch (e: Exception) {
// 应用未安装,检查是否有 fallback 兜底地址
val fallbackUrl = intent?.getStringExtra("browser_fallback_url")
if (!fallbackUrl.isNullOrEmpty()) {
view?.loadUrl(fallbackUrl)
}
return true
}
}
// 3. 处理普通自定义 Scheme (如 alipays://, weixin://, tel:, sms:)
try {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
view?.context?.startActivity(intent)
return true
} catch (e: ActivityNotFoundException) {
Log.e("WebView", "未找到可处理该 Scheme 的应用: $url")
return true
}
}
}
⚠️ 3. 常见避坑与微信/系统限制说明
- Android 11+ 包可见性限制: 在 Android 11 (API 30) 及以上,App 调用
PackageManager.queryIntentActivities() 探测其他应用是否安装时,必须在 AndroidManifest.xml 的 <queries> 标签中显式声明包名或 Intent 意图。
- 微信等内置浏览器拦截: 微信对非微信白名单的 Scheme 实行严格拦截策略。解决方案:提示用户右上角在系统浏览器打开,或者接入腾讯开放平台应用宝微下载。
- 用户手势限制: 在移动端 Chrome 中,通过异步 Ajax 回调或未由点击事件直接触发的
location.href 跳转,会被 Chrome 判定为无用户手势授权而直接阻止唤起。推荐使用直接绑定的点击事件。