Android WebView唤起拨号盘报错net::ERR_UNKNOWN_URL_SCHEME求助
问题根源与解决方案
嘿,我一眼就看到了问题所在——你重复设置了两次WebViewClient,这直接导致你写的处理tel:等URL Scheme的逻辑被完全覆盖了!
为什么会报错?
你先写了一个WebViewClient,里面正确判断了tel:、mailto:等Scheme并调用系统应用处理,但紧接着你又设置了第二个WebViewClient:
webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } });
这个第二个WebViewClient会完全替换掉第一个,导致所有URL都被WebView自己尝试加载,而WebView不认识tel:这种非HTTP/HTTPS的Scheme,所以就抛出了net::ERR_UNKNOWN_URL_SCHEME错误。
修复方案:合并WebViewClient逻辑
把两个WebViewClient的功能合并到一个里面,同时还要考虑Android API版本的兼容性(API 24+有重载的shouldOverrideUrlLoading方法),另外加上异常处理防止没有对应应用的情况。
以下是修复后的完整代码:
import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.annotation.SuppressLint; import android.app.Activity; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.net.Uri; import android.view.Gravity; import android.view.View; import android.view.WindowManager; import android.webkit.WebChromeClient; import android.webkit.WebResourceRequest; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.ProgressBar; import android.widget.Toast; import androidx.annotation.RequiresApi; public class MainActivity extends Activity { private WebView webView; ProgressBar progressBar; Context context; String URL = "https://tajhalalmeats.com/"; private boolean doubleTap; @SuppressLint("SetJavaScriptEnabled") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); progressBar = findViewById(R.id.progressBar); webView = findViewById(R.id.webView); WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setDomStorageEnabled(true); webSettings.setAppCacheEnabled(true); webSettings.setSupportMultipleWindows(true); // 合并所有WebViewClient逻辑到一个实例中 webView.setWebViewClient(new WebViewClient(){ // 处理旧版本API(<24) @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { return handleUrlLoading(view, url); } // 处理API 24+版本 @RequiresApi(api = Build.VERSION_CODES.N) @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { String url = request.getUrl().toString(); return handleUrlLoading(view, url); } // 统一处理URL加载逻辑 private boolean handleUrlLoading(WebView view, String url) { if (url != null) { // 处理tel、mailto、whatsapp等非HTTP/HTTPS Scheme if (url.startsWith("tel:")) { try { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); view.getContext().startActivity(intent); return true; } catch (ActivityNotFoundException e) { Toast.makeText(MainActivity.this, "没有找到拨号应用", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } } else if (url.startsWith("mailto:")) { try { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); view.getContext().startActivity(intent); return true; } catch (ActivityNotFoundException e) { Toast.makeText(MainActivity.this, "没有找到邮件应用", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } } else if (url.startsWith("https://api.whatsapp") || url.startsWith("http://api.whatsapp")) { try { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); view.getContext().startActivity(intent); return true; } catch (ActivityNotFoundException e) { Toast.makeText(MainActivity.this, "没有找到WhatsApp应用", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } } // 其他HTTP/HTTPS链接由WebView加载 view.loadUrl(url); return true; } return false; } }); // WebChromeClient单独设置,不冲突 webView.setWebChromeClient(new WebChromeClient() { public void onProgressChanged(WebView view, int progress) { progressBar.setProgress(progress); progressBar.setVisibility(progress == 100 ? View.GONE : View.VISIBLE); } }); getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN|WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); webView.loadUrl(URL); } // 返回键逻辑保持不变 @Override public void onBackPressed() { if (webView.canGoBack()) { webView.goBack(); } else if (doubleTap) { super.onBackPressed(); } else { Toast toast = Toast.makeText(this, "Press again to exit", Toast.LENGTH_SHORT); toast.setGravity(Gravity.CENTER | Gravity.CENTER_HORIZONTAL, 0, 0); toast.show(); doubleTap = true; Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { doubleTap = false; } }, 2000); } } }
额外注意事项
- 权限问题:你添加的
CALL_PHONE权限其实用不到,因为我们用的是Intent.ACTION_VIEW来打开拨号盘,这个不需要危险权限;只有用Intent.ACTION_CALL直接拨打电话才需要CALL_PHONE权限,你可以根据需求调整。 - 异常处理:添加了
ActivityNotFoundException的捕获,避免用户设备没有对应应用时崩溃。 - API兼容性:同时实现了新旧版本的
shouldOverrideUrlLoading方法,确保在Android 7.0及以上版本也能正常工作。
内容的提问来源于stack exchange,提问作者taj
相关产品推荐
相关产品推荐

