Android WebView“电话:”链接显示找不到网页

发布于 2024-10-06 09:08:39 字数 701 浏览 4 评论 0原文

我正在尝试让我的 android webview 应用程序打开电话:链接到手机。每次我打开电话链接时,它都会很好用并打开电话。然而,一旦我完成通话并返回到应用程序,它就会出现在一个页面上,上面写着“找不到网页电话:0000000000”。然后我必须再次点击后退按钮才能到达我点击电话号码的页面。

有没有办法让它打开 TEL 链接,而无需尝试在 webview 中查找页面以及在手机上打开它?

这是我在 WebView 中使用的代码,用于覆盖其对 TEL 和 Mailto 链接的处理:

        public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.startsWith("mailto:") || url.startsWith("tel:")) { 
                Intent intent = new Intent(Intent.ACTION_VIEW,
                        Uri.parse(url)); 
                startActivity(intent); 
                } 
        view.loadUrl(url);
        return true;
        }

任何帮助将不胜感激。我花了过去两个小时搜索古德尔,但未能给出任何答案。

I am trying to get my android webview app to open tel: links to the phone. Every time I open up a telephone link it works great and opens up the phone. However once I am done with my call and go back to the app it is at a page that says "Web Page Not Found tel:0000000000". Then I have to hit the back button once more to get to the page that I clicked the telephone number on.

Is there a way to get it to open the TEL link without trying to find the page in webview as well as opening it up on the phone?

This is code I am using in WebView to override its handling of the TEL and Mailto links:

        public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.startsWith("mailto:") || url.startsWith("tel:")) { 
                Intent intent = new Intent(Intent.ACTION_VIEW,
                        Uri.parse(url)); 
                startActivity(intent); 
                } 
        view.loadUrl(url);
        return true;
        }

Any help would be appreciated. I have spent the last 2 hours scouring goodle and have failed to produce any answers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

摇划花蜜的午后 2024-10-13 09:08:39

好的,我解决了我认为的问题。我只需要将 URL 覆盖分开,如下所示:

public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if (url.startsWith("tel:")) { 
        Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url)); 
        startActivity(intent);
        view.reload();
        return true;
    }

    view.loadUrl(url);
    return true;
}

现在我的常规链接和电话链接一样有效。如果需要的话,我还可以在其中添加 geo: 链接,并且它不会给我带来之前在手机上打开地图时遇到的问题。

OK so I solved the issue I think. I just needed to separate the URL overrides as follows:

public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if (url.startsWith("tel:")) { 
        Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url)); 
        startActivity(intent);
        view.reload();
        return true;
    }

    view.loadUrl(url);
    return true;
}

Now my regular links work as well as the tel links. I can also add in there for geo: links if I need to and it will not give me the issue that I was having before to open up maps on the phone.

只是在用心讲痛 2024-10-13 09:08:39

不要调用 loadUrl(url),只需为不应覆盖的 URL 返回 false:

public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if( URLUtil.isNetworkUrl(url) ) {
        return false;
    }

    // Otherwise allow the OS to handle it
    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
    startActivity( intent ); 
    return true;
}

我发现 VIEWing tel: 在我们尝试过的所有手机上都能按预期工作。由于 DIAL 操作,无需对其进行特殊处理。

我注意到 YouTube 视频等在 WebView 中不起作用,因此您可能也想检测这些内容。

整个过程可能可以通过 在 PackageManager 中查询处理您的 URI 的活动,但这些活动也不是嵌入式浏览器。这可能有点矫枉过正,并且会被其他已安装的浏览器混淆。

Rather than call loadUrl(url), just return false for the URLs that should not be overridden:

public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if( URLUtil.isNetworkUrl(url) ) {
        return false;
    }

    // Otherwise allow the OS to handle it
    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
    startActivity( intent ); 
    return true;
}

I've found VIEWing tel: works as expected on all phones we've tried it with. No need to special-case it because of the DIAL action.

I've noticed YouTube videos and the like don't work in WebViews, so you may want to detect those as well.

The whole process could probably be generalized for all sorts of URIs by querying the PackageManager for Activities that handle your URI that are also not the embedded browser. That might be overkill and get confused by other installed browsers.

空心空情空意 2024-10-13 09:08:39

根据文档并根据我的经验,Intent.ACTION_VIEW 非常适合解析 tel:sms:smsto: 、 < code>mms: 和 mmsto: 链接。

这是 5 合 1:

@Override
    public boolean shouldOverrideUrlLoading(WebView webview, String url)
    {
     if (url.startsWith("tel:") || url.startsWith("sms:") || url.startsWith("smsto:") || url.startsWith("mms:") || url.startsWith("mmsto:"))
       { 
         Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse(url)); 
         startActivity(intent); 
         return true;
       }
    return false;
   }

According to the documentation and based on my experience, Intent.ACTION_VIEW is perfectly fine to parse tel: , sms: , smsto: , mms: and mmsto: links.

Here's a 5 in 1:

@Override
    public boolean shouldOverrideUrlLoading(WebView webview, String url)
    {
     if (url.startsWith("tel:") || url.startsWith("sms:") || url.startsWith("smsto:") || url.startsWith("mms:") || url.startsWith("mmsto:"))
       { 
         Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse(url)); 
         startActivity(intent); 
         return true;
       }
    return false;
   }
始终不够爱げ你 2024-10-13 09:08:39

注意:- Android Nouget shouldOverrideUrlLoading 已弃用后,

您需要将 shouldOverrideUrlLoadingshouldOverrideUrlLoading 一起使用以获得更好的支持。另外,您可能想检查 url 是否有 mailto:tel:,它们在 HTML5 中分别用于触发邮件客户端和电话拨号。

完整的解决方案现在看起来像这样

    @SuppressWarnings("deprecation")
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.startsWith("mailto:")) {  
            //Handle mail Urls
            startActivity(new Intent(Intent.ACTION_SENDTO, Uri.parse(url)));
        } else if (url.startsWith("tel:")) {
            //Handle telephony Urls
            startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(url)));
        } else {
            view.loadUrl(url);
        }
        return true;
    }

    @TargetApi(Build.VERSION_CODES.N)
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
        final Uri uri = request.getUrl();
        if (uri.toString().startsWith("mailto:")) {
            //Handle mail Urls
            startActivity(new Intent(Intent.ACTION_SENDTO, uri));
        } else if (uri.toString().startsWith("tel:")) {
            //Handle telephony Urls
            startActivity(new Intent(Intent.ACTION_DIAL, uri));
        } else {
            //Handle Web Urls
            view.loadUrl(uri.toString());
        }
        return true;
    }

Note :- After Android Nouget shouldOverrideUrlLoading is Deprecated

You need to use shouldOverrideUrlLoading along with shouldOverrideUrlLoading for better support. Also you might want to check if url have mailto: or tel:, which are used in HTML5 to trigger mail client and phone dial respectively.

A complete solution will look like this now

    @SuppressWarnings("deprecation")
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.startsWith("mailto:")) {  
            //Handle mail Urls
            startActivity(new Intent(Intent.ACTION_SENDTO, Uri.parse(url)));
        } else if (url.startsWith("tel:")) {
            //Handle telephony Urls
            startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(url)));
        } else {
            view.loadUrl(url);
        }
        return true;
    }

    @TargetApi(Build.VERSION_CODES.N)
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
        final Uri uri = request.getUrl();
        if (uri.toString().startsWith("mailto:")) {
            //Handle mail Urls
            startActivity(new Intent(Intent.ACTION_SENDTO, uri));
        } else if (uri.toString().startsWith("tel:")) {
            //Handle telephony Urls
            startActivity(new Intent(Intent.ACTION_DIAL, uri));
        } else {
            //Handle Web Urls
            view.loadUrl(uri.toString());
        }
        return true;
    }
风渺 2024-10-13 09:08:39
public class MainActivity extends Activity {

private static final String HTML ="<!DOCTYPE html><html><body><a 
href='tel:867-5309'>Click here to call!</a></body></html>";
private static final String TEL_PREFIX = "tel:";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    WebView wv = (WebView) findViewById(R.id.webview);
    wv.setWebViewClient(new CustomWebViewClient());
    wv.loadData(HTML, "text/html", "utf-8");
}

private class CustomWebViewClient extends WebViewClient {

    @Override
    public boolean shouldOverrideUrlLoading(WebView wv, String url) {
        if(url.startsWith(TEL_PREFIX)) {
            Intent intent = new Intent(Intent.ACTION_DIAL);
            intent.setData(Uri.parse(url));
            startActivity(intent);
            return true;
        }
        return false;
    }
}

}

这是我找到的修复方法。你必须使用这个方法。

wv.setWebViewClient(new CustomWebViewClient());
public class MainActivity extends Activity {

private static final String HTML ="<!DOCTYPE html><html><body><a 
href='tel:867-5309'>Click here to call!</a></body></html>";
private static final String TEL_PREFIX = "tel:";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    WebView wv = (WebView) findViewById(R.id.webview);
    wv.setWebViewClient(new CustomWebViewClient());
    wv.loadData(HTML, "text/html", "utf-8");
}

private class CustomWebViewClient extends WebViewClient {

    @Override
    public boolean shouldOverrideUrlLoading(WebView wv, String url) {
        if(url.startsWith(TEL_PREFIX)) {
            Intent intent = new Intent(Intent.ACTION_DIAL);
            intent.setData(Uri.parse(url));
            startActivity(intent);
            return true;
        }
        return false;
    }
}

}

This was the fix i found. You have to use this method.

wv.setWebViewClient(new CustomWebViewClient());
明明#如月 2024-10-13 09:08:39

如果没有分配给 WebView 的 WebViewClient,默认情况下 WebView 会要求 Activity Manager 为 URL 选择正确的处理程序。如果提供了WebViewClient,您应该自己处理不同的URL,并在WebViewClient.shouldOverrideUrlLoading()中返回true,否则它将尝试向该URL发送请求并收到错误,然后触发onReceiveError()。

检查文档: WebViewClient.shouldOverrideUrlLoading

     @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.startsWith("tel:")) { 
            // ...TODO: launch a Dial app or send SMS or add to contact, etc...
            return true;
        }
        else if (url.startsWith("mailto:")) {
            // ...TODO: send email to someone or add to contact, etc...
            return true;
        }
        else {
            // ...TODO: Handle URL here
            boolean handled = yourHandleUrlMethod(url);
            return handled;
        }
    }

If there is no WebViewClient assigned to WebView, by default WebView will ask Activity Manager to choose the proper handler for the URL. If a WebViewClient is provided, you should handle different URLs yourself and returns true in WebViewClient.shouldOverrideUrlLoading(), otherwise it will try to send request to the URL and get an error, then triggers onReceiveError().

Check document: WebViewClient.shouldOverrideUrlLoading

     @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.startsWith("tel:")) { 
            // ...TODO: launch a Dial app or send SMS or add to contact, etc...
            return true;
        }
        else if (url.startsWith("mailto:")) {
            // ...TODO: send email to someone or add to contact, etc...
            return true;
        }
        else {
            // ...TODO: Handle URL here
            boolean handled = yourHandleUrlMethod(url);
            return handled;
        }
    }
红尘作伴 2024-10-13 09:08:39

WebView 类中的一些常量是静态的。您应该使用 Intent.ACTION_VIEW 而不是 Intent.ACTION_DIALACTION_SENDTO

@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    String url = request.getUrl().toString();
    if (url.startsWith(WebView.SCHEME_TEL)
            || url.startsWith(SCHEME_SMS)
            || url.startsWith(WebView.SCHEME_MAILTO)
            || url.startsWith(WebView.SCHEME_GEO)) {
        
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse(url));
        startActivity(intent); // view.context.startActivity(intent);
    }
    return true;
}

Some constants are static in WebView class. You should use Intent.ACTION_VIEW instead of Intent.ACTION_DIAL or ACTION_SENDTO:

@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    String url = request.getUrl().toString();
    if (url.startsWith(WebView.SCHEME_TEL)
            || url.startsWith(SCHEME_SMS)
            || url.startsWith(WebView.SCHEME_MAILTO)
            || url.startsWith(WebView.SCHEME_GEO)) {
        
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse(url));
        startActivity(intent); // view.context.startActivity(intent);
    }
    return true;
}
烟燃烟灭 2024-10-13 09:08:39
public boolean shouldOverrideUrlLoading(WebView view, String url)
       {Uri query_string=Uri.parse(url);
        String query_scheme=query_string.getScheme();
        String query_host=query_string.getHost();
        if ((query_scheme.equalsIgnoreCase("https") || query_scheme.equalsIgnoreCase("http"))
            && query_host!=null && query_host.equalsIgnoreCase(Uri.parse(URL_SERVER).getHost())
            && query_string.getQueryParameter("new_window")==null
           )
           {return false;//handle the load by webview
           }
        try
           {Intent intent=new Intent(Intent.ACTION_VIEW, query_string);
            String[] body=url.split("\\?body=");
            if (query_scheme.equalsIgnoreCase("sms") && body.length>1)
               {intent=new Intent(Intent.ACTION_VIEW, Uri.parse(body[0]));
                intent.putExtra("sms_body", URLDecoder.decode(body[1]));
               }
            view.getContext().startActivity(intent);//handle the load by os
           }
        catch (Exception e) {}
        return true;
       }
public boolean shouldOverrideUrlLoading(WebView view, String url)
       {Uri query_string=Uri.parse(url);
        String query_scheme=query_string.getScheme();
        String query_host=query_string.getHost();
        if ((query_scheme.equalsIgnoreCase("https") || query_scheme.equalsIgnoreCase("http"))
            && query_host!=null && query_host.equalsIgnoreCase(Uri.parse(URL_SERVER).getHost())
            && query_string.getQueryParameter("new_window")==null
           )
           {return false;//handle the load by webview
           }
        try
           {Intent intent=new Intent(Intent.ACTION_VIEW, query_string);
            String[] body=url.split("\\?body=");
            if (query_scheme.equalsIgnoreCase("sms") && body.length>1)
               {intent=new Intent(Intent.ACTION_VIEW, Uri.parse(body[0]));
                intent.putExtra("sms_body", URLDecoder.decode(body[1]));
               }
            view.getContext().startActivity(intent);//handle the load by os
           }
        catch (Exception e) {}
        return true;
       }
无远思近则忧 2024-10-13 09:08:39

对于那些尝试使用 @jeff Thomas 答案但遇到以下错误的人:

cannot find symbol view.startActivity(intent);

您可以使用此代码:

public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if (url.startsWith("tel:")) { 
        Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url)); 
        view.getContext().startActivity(intent);
        view.reload();
        return true;
    }

    view.loadUrl(url);
    return true;
}

我刚刚更改了 startActivity(intent) code> 到 view.getContext().startActivity(intent) 这对我有用。

For those who tried to use @jeff Thomas answer but got below error:

cannot find symbol view.startActivity(intent);

You can use this code:

public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if (url.startsWith("tel:")) { 
        Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url)); 
        view.getContext().startActivity(intent);
        view.reload();
        return true;
    }

    view.loadUrl(url);
    return true;
}

I just changed startActivity(intent) to view.getContext().startActivity(intent) and thats worked for me.

溇涏 2024-10-13 09:08:39
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    WebView wv = (WebView) findViewById(R.id.webview);
    wv.setWebViewClient(new CustomWebViewClient());
    wv.loadData(HTML, "text/html", "utf-8");
}

private class CustomWebViewClient extends WebViewClient {
    @SuppressWarnings("deprecated")
    @Override
    public boolean shouldOverrideUrlLoading(WebView wv, String url) {
        if(url.startsWith(TEL_PREFIX)) {
            Intent intent = new Intent(Intent.ACTION_DIAL);
            intent.setData(Uri.parse(url));
            startActivity(intent);
            return true;
        }
        return false;
    }
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    WebView wv = (WebView) findViewById(R.id.webview);
    wv.setWebViewClient(new CustomWebViewClient());
    wv.loadData(HTML, "text/html", "utf-8");
}

private class CustomWebViewClient extends WebViewClient {
    @SuppressWarnings("deprecated")
    @Override
    public boolean shouldOverrideUrlLoading(WebView wv, String url) {
        if(url.startsWith(TEL_PREFIX)) {
            Intent intent = new Intent(Intent.ACTION_DIAL);
            intent.setData(Uri.parse(url));
            startActivity(intent);
            return true;
        }
        return false;
    }
嘿咻 2024-10-13 09:08:39

看看 Hitesh Sahukam C 回答我有一个解决方案。

在 API 21 中,它引发了一个异常:“android.util.AndroidRuntimeException:从 Activity 上下文外部调用 startActivity() 需要 FLAG_ACTIVITY_NEW_TASK 标志。这真的是您想要的吗?”。

此外,可能找不到活动,正如 diyism 所注意到的那样。所以,我处理了这些情况。

class MyWebViewClient : WebViewClient() {

    @Suppress("DEPRECATION")
    override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
        if (view != null && url != null) {
            return resolveUri(view.context, Uri.parse(url))
        }
        return super.shouldOverrideUrlLoading(view, url)
    }

    @TargetApi(Build.VERSION_CODES.N)
    override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
        val uri = request?.url
        if (view != null && uri != null) {
            return resolveUri(view.context, uri)
        }
        return super.shouldOverrideUrlLoading(view, request)
    }

    private fun resolveUri(context: Context, uri: Uri): Boolean {
        val url = uri.toString()
        URL_SCHEMES.forEach {
            if (url.startsWith(it)) {
                val intent = Intent(Intent.ACTION_VIEW).apply {
                    data = uri
                    addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                }
                try {
                    context.startActivity(intent)
                } catch (e: ActivityNotFoundException) {
                }
                return true
            }
        }
        return false
    }

    companion object {
        private val URL_SCHEMES = arrayOf(WebView.SCHEME_TEL,
            WebView.SCHEME_MAILTO, WebView.SCHEME_GEO, "sms:", "smsto:", "mms:", "mmsto:")
    }
}

Looking at Hitesh Sahu and kam C answers I got a solution.

In API 21 it raised an exception: "android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?".

Also an activity may not be found, as noticed by diyism. So, I handled these situations.

class MyWebViewClient : WebViewClient() {

    @Suppress("DEPRECATION")
    override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
        if (view != null && url != null) {
            return resolveUri(view.context, Uri.parse(url))
        }
        return super.shouldOverrideUrlLoading(view, url)
    }

    @TargetApi(Build.VERSION_CODES.N)
    override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
        val uri = request?.url
        if (view != null && uri != null) {
            return resolveUri(view.context, uri)
        }
        return super.shouldOverrideUrlLoading(view, request)
    }

    private fun resolveUri(context: Context, uri: Uri): Boolean {
        val url = uri.toString()
        URL_SCHEMES.forEach {
            if (url.startsWith(it)) {
                val intent = Intent(Intent.ACTION_VIEW).apply {
                    data = uri
                    addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                }
                try {
                    context.startActivity(intent)
                } catch (e: ActivityNotFoundException) {
                }
                return true
            }
        }
        return false
    }

    companion object {
        private val URL_SCHEMES = arrayOf(WebView.SCHEME_TEL,
            WebView.SCHEME_MAILTO, WebView.SCHEME_GEO, "sms:", "smsto:", "mms:", "mmsto:")
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文