一、错误记录
报错信息 :
网页无法打开 位于 baiduboxapp://speech/startVoiceSearch?¶ms={“voiceSource”:“home_naver_long”}&jumpTime 的网页无法加载, 因为 net::ERR_UNKNOW_URL_SCHEME ;
二、解决方案
出现该错误的原因是 WebView 尝试加载不支持的 URL 链接 , 目前 WebView 只能支持加载 http 或 https 协议的 URL 地址 ;
当前要加载的地址是 " baiduboxapp://speech/startVoiceSearch?¶ms={“voiceSource”:“home_naver_long”}&jumpTime " 这是百度应用的 URL 地址 ;
出现上述问题 , 通过重写 WebViewClient 的 shouldOverrideUrlLoading 函数 , 获取要加载的 URL 地址 , 如果发现了要加载不支持的 URL 协议地址 ,则启动对应的应用加载该地址 , 如 百度 / 淘宝 / 京东 等应用 ;
解决方案 : 为 WebView 设置 WebViewClient , 重写其中的 shouldOverrideUrlLoading 函数 , 如果 url 链接是 http:// 和 https:// 页面 直接加载 , 如果是其它页面 , 直接调用对应的 app 应用 ;
代码语言:javascript复制 // WebViewClient 是一个用于处理 WebView 页面加载事件的类
webview.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
Log.i("MainActivity", "访问地址 : $url")
// 4.0 之后必须添加该设置
// 只能加载 http:// 和 https:// 页面 , 不能加载其它协议链接
if (url.startsWith("http://") || url.startsWith("https://")) {
view.loadUrl(url)
return true
} else {
if (url.startsWith("weixin://") ||
url.startsWith("alipays://") ||
url.startsWith("tel://") ||
url.startsWith("baiduboxapp://") ) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
startActivity(intent)
return true
}
}
return false
}
// SSL 证书校验出现异常
override fun onReceivedSslError(
view: WebView,
handler: SslErrorHandler,
error: SslError) {
when (error.primaryError) {
SslError.SSL_INVALID, SslError.SSL_UNTRUSTED -> {
handler.proceed()
}
else -> handler.cancel()
}
}
}
三、开发通过自定义的 URL 协议启动的应用
在 AndroidManifest.xml 清单文件中注册一个自定义的 URL 协议处理器 , 下面注册的协议名称是 myapp ;
代码语言:javascript复制<activity android:name=".MyActivity">
<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="myapp" />
</intent-filter>
</activity>
在应用中就可以使用 myapp:// 开头的 URL 来启动上述 MyActivity ;
在 WebView 中如果遇到了此类 URL 链接 , 使用 WebViewClient 的 shouldOverrideUrlLoading 方法来拦截不支持的 URL 协议,不直接加载这些链接 , 而是直接启动 ;
通用处理方案如下 , 一般是启动该 url 对应的应用 ;
代码语言:javascript复制WebView webView = findViewById(R.id.webView);
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("myapp://")) {
// 处理 myapp 协议的 URL
return true;
}
// 其他协议的 URL 使用默认行为
return super.shouldOverrideUrlLoading(view, url);
}
});