Android WebView如何处理mailto、tel链接报err_unknown_url_scheme错误
报错原因
Android WebView 默认仅支持识别加载http://、https://开头的网页链接,当点击tel:(拨打电话)、mailto:(发送邮件)这类唤起系统功能的自定义协议链接时,WebView会尝试将其作为普通网页加载,就会抛出err_unknown_url_scheme的未知协议错误。
修复步骤
- 补充缺失的类导入:在文件头部导入处理系统跳转、URI解析需要的相关类
- 替换原有WebViewClient实现:把原来代码里默认的WebViewClient初始化逻辑替换为自定义实现,重写URL加载规则,对协议做分流:普通http/https链接交给WebView内部加载,系统功能类协议直接唤起对应系统应用处理
完整修改后的MainActivity.java代码如下:
package xxx.xxxxxxx.xxxxxxxxx; import androidx.appcompat.app.AppCompatActivity; import android.annotation.SuppressLint; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.webkit.WebResourceRequest; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import java.util.Objects; public class MainActivity extends AppCompatActivity { private WebView webView; @SuppressLint("SetJavaScriptEnabled") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); try { Objects.requireNonNull(this.getSupportActionBar()).hide(); } catch (NullPointerException ignored){} webView = findViewById(R.id.webview); // 替换为带自定义URL处理逻辑的WebViewClient webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { String url; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { url = request.getUrl().toString(); } else { url = view.getUrl(); } // http/https普通链接交由WebView内部加载 if (url.startsWith("http://") || url.startsWith("https://")) { view.loadUrl(url); return false; } // 系统协议链接唤起对应系统应用处理 try { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(intent); } catch (Exception ignored) { // 无对应处理应用时做兜底,避免应用崩溃 } return true; } }); webView.loadUrl("https://www.ezyadvs.com"); WebSettings webSettings =webView.getSettings(); webSettings.setJavaScriptEnabled(true); } @Override public void onBackPressed() { if(webView.canGoBack()) { webView.goBack(); }else{ super.onBackPressed(); } } }
注意事项
- 上述代码通过
Intent.ACTION_VIEW处理系统协议,拨打电话会默认跳转系统拨号盘、邮箱链接会唤起系统邮件应用,不需要额外申请敏感权限,兼容性更好。 - 现有逻辑会自动适配设备上已安装应用支持的所有自定义协议,包括后续新增的地图跳转
geo:、应用市场跳转market:等,不需要额外修改判断规则。 - 如果需要对特定协议做定制交互,可以在分流判断里新增对应分支单独处理。
内容的提问来源于stack exchange,提问作者AlaaEldin
相关产品推荐
相关产品推荐

