You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
        }
    }
}

额外注意事项

  1. 权限问题:你添加的CALL_PHONE权限其实用不到,因为我们用的是Intent.ACTION_VIEW来打开拨号盘,这个不需要危险权限;只有用Intent.ACTION_CALL直接拨打电话才需要CALL_PHONE权限,你可以根据需求调整。
  2. 异常处理:添加了ActivityNotFoundException的捕获,避免用户设备没有对应应用时崩溃。
  3. API兼容性:同时实现了新旧版本的shouldOverrideUrlLoading方法,确保在Android 7.0及以上版本也能正常工作。

内容的提问来源于stack exchange,提问作者taj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 18:08:05