Android WebView无法触发Deep-linking,报ERR_UNKNORN_URL_SCHEME错误
WebView触发Deep Link出现ERR_UNKNOWN_URL_SCHEME的解决方法
我在Android应用的WebView中尝试触发Deep Link,网站通过执行window.location.href = app://ls.mydomain.it/?key=XXX跳转,但未触发ACTION_VIEW Intent,反而出现ERR_UNKNOWN_URL_SCHEME错误。
现有代码
Fragment中WebView加载逻辑
binding.webview.settings.javaScriptEnabled = true binding.webview.settings.loadWithOverviewMode = true binding.webview.webViewClient = object : WebViewClient() { override fun shouldOverrideUrlLoading(view: WebView?,request: WebResourceRequest?): Boolean { return false } } binding.webview.settings.domStorageEnabled = true binding.webview.loadUrl("https://ls.mydomain.it/?deviceId=${deviceId}")
Manifest中的Deep Link配置
<activity android:name=".ui.components.home.HomeActivity" android:exported="true" android:screenOrientation="portrait" android:theme="@style/Theme.App.Starting" android:windowSoftInputMode="adjustPan" android:launchMode="singleTask" tools:ignore="LockedOrientationActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="app" android:host="ls.mydomain.it" /> </intent-filter> </activity>
Activity中的Intent处理代码
override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) if (intent?.action == Intent.ACTION_VIEW) { val data: Uri? = intent.data newLicense(data) } }
问题原因
WebView默认仅支持处理http/https这类标准协议,对于自定义scheme(如app://)无法识别,会直接抛出ERR_UNKNOWN_URL_SCHEME错误,不会自动触发对应的Intent,需要手动拦截自定义scheme的URL并处理。
解决方案
修改WebViewClient的shouldOverrideUrlLoading方法,拦截自定义scheme的请求,手动构造并启动ACTION_VIEW Intent:
binding.webview.webViewClient = object : WebViewClient() { // 适配API 24+ override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean { request?.url?.let { uri -> handleCustomScheme(uri, view?.context)?.let { return true } } return false } // 兼容API 21及以下版本 override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { url?.let { val uri = Uri.parse(it) handleCustomScheme(uri, view?.context)?.let { return true } } return false } // 抽离自定义scheme处理逻辑 private fun handleCustomScheme(uri: Uri, context: Context?): Boolean { val scheme = uri.scheme if (scheme != null && scheme.equals("app", ignoreCase = true)) { try { val intent = Intent(Intent.ACTION_VIEW, uri) context?.startActivity(intent) return true } catch (e: ActivityNotFoundException) { // 无应用可处理该Intent时的逻辑,比如提示用户 e.printStackTrace() } } return false } }
补充说明
- 由于Activity设置了
launchMode="singleTask",Intent启动时会调用onNewIntent方法,你已实现的处理逻辑无需修改。 - 启动Intent时需确保Context有效,Fragment中使用
getActivity()时要注意生命周期,避免空指针。 - 捕获
ActivityNotFoundException是为了处理Manifest配置错误等导致无应用可处理Intent的情况,可在此处添加用户提示逻辑。
内容的提问来源于stack exchange,提问作者NiceToMytyuk
相关产品推荐
相关产品推荐

