Android 安卓网络视图“;电话:";链接显示未找到的网页
我正在尝试让我的android webview应用程序打开手机的电话:链接。每次我打开一个电话连接,它的工作非常好,打开了电话。然而,一旦我完成了我的呼叫并返回到应用程序,就会出现一个页面,上面写着“未找到网页电话:0000000000”。然后我必须再次点击后退按钮才能进入我点击电话号码的页面 有没有一种方法可以让它打开电话链接,而不必在webview中查找页面,也不必在手机上打开页面 这是我在WebView中用来覆盖其对TEL和Mailto链接的处理的代码:Android 安卓网络视图“;电话:";链接显示未找到的网页,android,android-webview,Android,Android Webview,我正在尝试让我的android webview应用程序打开手机的电话:链接。每次我打开一个电话连接,它的工作非常好,打开了电话。然而,一旦我完成了我的呼叫并返回到应用程序,就会出现一个页面,上面写着“未找到网页电话:0000000000”。然后我必须再次点击后退按钮才能进入我点击电话号码的页面 有没有一种方法可以让它打开电话链接,而不必在webview中查找页面,也不必在手机上打开页面 这是我在WebView中用来覆盖其对TEL和Mailto链接的处理的代码: public bo
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;
}
任何帮助都将不胜感激。在过去的两个小时里,我一直在搜索古德,但没有给出任何答案。好吧,我想我解决了这个问题。我只需要按如下方式分离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:links,它不会给我以前在手机上打开地图时遇到的问题。而不是调用
加载url(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;
}
我发现,在我们试用过的所有手机上,查看tel:都能如期工作。由于拨号操作,无需对其进行特殊处理
我注意到YouTube视频和类似的东西在网络视图中不起作用,所以你可能也想检测它们
整个过程可能适用于所有类型的URI,因为它们也不是嵌入式浏览器。根据我的经验,Intent.ACTION\u VIEW
非常适合解析tel:
、sms:
、smsto:
、mms:
和mmsto:
链接
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;
}
这是一个五合一:
@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.shouldOverrideUrlLoading()中返回true,否则它将尝试向URL发送请求并获取错误,然后触发onReceiveError()
注意:-Android Nouget之后
shouldOverrideUrlAlloading
已被弃用
您需要将shouldOverrideUrlLoading
与shouldOverrideUrlLoading
一起使用,以获得更好的支持。另外,您可能需要检查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;
}
某些常量在
WebView
类中是静态的。您应该使用Intent.ACTION\u VIEW
而不是Intent.ACTION\u DIAL
或ACTION\u 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 answer但出现以下错误的用户:
找不到符号视图。startActivity(意图)代码>
您可以使用以下代码:
public boolean shouldOverrideUrlLoading(WebView视图,字符串url){
如果(url.startsWith(“电话:”){
Intent Intent=新的Intent(Intent.ACTION\u拨号,Uri.parse(url));
view.getContext().startActivity(intent);
view.reload();
返回true;
}
view.loadUrl(url);
返回true;
}
我刚刚将startActivity(intent)
更改为view.getContext().startActivity(intent)
,这对我很有效。查看和回答我得到了一个解决方案
在API 21中,它引发了一个异常:“android.util.AndroidRuntimeException:从活动上下文外部调用startActivity()需要标志_Activity_NEW_TASK标志。这真的是您想要的吗?”
此外,可能未发现活动,如所注意到的。所以,我处理了这些情况
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:")
}
}
尝试拨打ACTION_拨号获取电话:链接?等等,文档实际上说ACTION_视图很好:那没关系……愚蠢的问题:您是否正确设置了WebViewClient
?其他一切都正常吗?是的。。。除电话:链接外,其他所有功能正常。即使是这样,也只是当你不打电话回到应用程序时,它会出现在一个页面上,上面写着“找不到”。@EboMike:我认为你第一次是对的:--我不相信“注意查看操作如何做对特定URI来说最合理的事情”注意docs.Duh中的注释。我刚刚意识到您正在调用tel:link上的view.LoadUrl(url)。您不妨在startActivity()
之后添加一个return true
。添加到清单中。@jasonflaherty实际上CALL\u PHONE权限用于操作\u CALL而不是操作\u拨号。因此,即使没有权限,上述代码也可以正常工作;返回true将导致WebView覆盖URL并按其认为合适的方式处理它。请不要按原样复制上面的代码。从回调返回false,而不是调用view.loadUrl。调用loadUrl会引入一个微妙的错误,如果页面中有任何带有自定义方案URL的iframe(比如),它会将应用程序的主框架导航到该URL,很可能会破坏应用程序,这是一个副作用。您能解释一下您的解决方案吗?尤其是URL_服务器的测试(顺便说一句,它缺失了)可能不是每个人都清楚。URL_服务器是“”,而“return false;”意味着您站点中的页面将在应用程序中打开,而不会在android浏览器中打开。您可以使用URLUtil.isNetworkUrl(URL)进行http/https(和其他)检查伟大的建议,@xnagyg。我已经更新了我的代码片段。这比添加单独的URL方案更实用。完美。。。处理牛轧糖前和牛轧糖。谢谢你,谢谢!使用@Suppress(“弃用”)
代替@SuppressWarnings(“弃用”)
。你可以创造奇迹
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;
}
@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;
}
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:")
}
}