Android WebView“ tel:”链接显示没有找到网页

我试图让我的 android webview 应用程序打开电话: 链接到手机。每次我打开一个电话连接,它工程伟大,打开电话。然而,一旦我完成了我的电话,并返回到应用程序,它是在一个页面上说: “网页没有发现电话: 000000000”。然后我必须再次按下返回按钮才能到达我点击电话号码的页面。

有没有一种方法可以让它打开 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;
}

如果你能帮忙,我将不胜感激。我花了两个小时在谷歌上搜索但是没有找到任何答案。

77442 次浏览

好了,我想我解决了这个问题。我只需要像下面这样分离 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;
}

现在我的常规链接工作,以及电话联系。我也可以在那里添加地理: 链接,如果我需要,它不会给我的问题,我以前有打开手机上的地图。

不要调用 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 电话: 在所有我们试用过的手机上都能正常工作。不需要特殊情况下,因为它的 DAL 行动。

我注意到 YouTube 视频和类似的东西在网络视图中不起作用,所以你可能也想检测一下。

通过 为处理 URI 的活动查询 PackageManager可以将整个过程推广到所有类型的 URI,这些 URI 也不是嵌入式浏览器。这样做可能有些过火,并且会被其他已安装的浏览器搞混。

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

根据 文件和基于我的经验,Intent.ACTION_VIEW非常好解析 tel:sms:smsto:mms:mmsto:链接。

这是五分之一的几率:

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

如果没有分配给 WebView 的 WebViewClient,默认情况下,WebView 将要求活动管理器为 URL 选择合适的处理程序。如果提供了一个 WebViewClient,您应该自己处理不同的 URL,并在 WebViewClient.should dOverrideUrlLoading ()中返回 true,否则它将尝试向 URL 发送请求并得到一个错误,然后触发 onReceiveError ()。

检查文档: WebViewClient.should dOverrideUrlLoding

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

注意:-在 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;
}
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());
@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;
}

有些常量在 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;
}

对于那些试图使用@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)改成了 view.getContext().startActivity(intent)这对我很有用。

看着 Hitesh SahuKam C的答案,我得到了一个解决方案。

在 API 21中,它引发了一个异常: “ android.util。AndroidRuntimeException: 从活动上下文外部调用 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:")
}
}