Android 在 WebView 中打开 Intent://协议 [英] Android open intent:// protocol in WebView

查看:56
本文介绍了Android 在 WebView 中打开 Intent://协议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我将 url 加载到 WebView 并尝试打开链接时,其中一些显示错误页面,例如:

When i load url into WebView and try to open links, some of them shows an error page like:

net::ERR_UNKNOWN_URL_SCHEME intent://maps.yandex.ru?utm_medium=tab...

net::ERR_UNKNOWN_URL_SCHEME intent://maps.yandex.ru?utm_medium=tab...

我怎样才能打开这个链接,或者至少检查是否安装了合适的应用程序并运行它?

How can i open this links, or at least check whether appropriate app installed and run it?

我尝试通过实现自定义 WebViewClient 来覆盖 url 加载:

I've tried to override url loading by implementing custom WebViewClient:

@Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (!url.startsWith("http")) {
            getActivity().startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse(url)));
            return true;
        }
        return false;
    }

但在这种情况下,应用会因 ActivityNotFoundException 而崩溃.

but app crashes with ActivityNotFoundException in this case.

02-24 20:58:51.886 31255-31255/ru.uxapps.voicesearch W/System.err: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=intent://maps.yandex.ru?utm_medium=tab-maps&text=магазин&utm_source=serp&yandexuid=2258091361456330110 }
02-24 20:58:51.886 31255-31255/ru.uxapps.voicesearch W/System.err:     at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1798)
02-24 20:58:51.886 31255-31255/ru.uxapps.voicesearch W/System.err:     at android.app.Instrumentation.execStartActivity(Instrumentation.java:1512)
02-24 20:58:51.886 31255-31255/ru.uxapps.voicesearch W/System.err:     at android.app.Activity.startActivityForResult(Activity.java:3930)
02-24 20:58:51.886 31255-31255/ru.uxapps.voicesearch W/System.err:     at android.app.Activity.startActivityForResult(Activity.java:3890)
02-24 20:58:51.886 31255-31255/ru.uxapps.voicesearch W/System.err:     at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:784)
02-24 20:58:51.886 31255-31255/ru.uxapps.voicesearch W/System.err:     at android.app.Activity.startActivity(Activity.java:4213)
02-24 20:58:51.886 31255-31255/ru.uxapps.voicesearch W/System.err:     at android.app.Activity.startActivity(Activity.java:4181)
02-24 20:58:51.886 31255-31255/ru.uxapps.voicesearch W/System.err:     at ru.uxapps.voicesearch.FWeb$CustomWebViewClient.shouldOverrideUrlLoading(FWeb.java:70)
02-24 20:58:51.886 31255-31255/ru.uxapps.voicesearch W/System.err:     at com.android.webview.chromium.WebViewContentsClientAdapter.shouldOverrideUrlLoading(WebViewContentsClientAdapter.java:325)
02-24 20:58:51.886 31255-31255/ru.uxapps.voicesearch W/System.err:     at org.chromium.android_webview.AwContentsClientBridge.shouldOverrideUrlLoading(AwContentsClientBridge.java:266)
02-24 20:58:51.886 31255-31255/ru.uxapps.voicesearch W/System.err:     at org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
02-24 20:58:51.886 31255-31255/ru.uxapps.voicesearch W/System.err:     at org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:37)
02-24 20:58:51.886 31255-31255/ru.uxapps.voicesearch W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
02-24 20:58:51.886 31255-31255/ru.uxapps.voicesearch W/System.err:     at android.os.Looper.loop(Looper.java:148)
02-24 20:58:51.886 31255-31255/ru.uxapps.voicesearch W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5417)
02-24 20:58:51.887 31255-31255/ru.uxapps.voicesearch W/System.err:     at java.lang.reflect.Method.invoke(Native Method)

即使安装了所需的应用程序,应用程序也会崩溃.但是如果在 Chrome 中打开这个链接,它会显示 maps.yandex.ru 站点,或者如果安装了应用程序.

App crashes even if required app is installed. But if open this link in Chrome, it shows maps.yandex.ru site, or opens app if installed.

是否有适用于所有 intent://链接的通用解决方案?感谢您的建议.

Is there a common solution, which will work for all intent:// links? Thanks for your suggestions.

推荐答案

我找到了解决方案.这个问题本文档 帮助我了解情况.

I found a solution. This question and this documentation helps me to understand situation.

因此,我编写了一个遵循以下逻辑的链接处理程序:

As a result, i've written a link handler which follow this logic:

  1. 在同一个 WebView 中打开 http 和 https
  2. 尝试处理已知方案(电话:等)
  3. 如果找不到已知活动,则解析意图:方案并尝试运行适当的应用
  4. 如果未安装所需的应用程序,则尝试将提供的后备 url 加载到当前 WebView 中
  5. 如果没有提供后备网址,则重定向到市场并要求安装所需的应用

代码是:

mWebView.setWebViewClient(new CustomWebViewClient());

//...

private class CustomWebViewClient extends WebViewClient {

    @Override
    public boolean shouldOverrideUrlLoading(WebView webView, String url) {
        if (url.startsWith("http")) return false;//open web links as usual
        //try to find browse activity to handle uri
        Uri parsedUri = Uri.parse(url);
        PackageManager packageManager = getActivity().getPackageManager();
        Intent browseIntent = new Intent(Intent.ACTION_VIEW).setData(parsedUri);
        if (browseIntent.resolveActivity(packageManager) != null) {
            getActivity().startActivity(browseIntent);
            return true;
        }
        //if not activity found, try to parse intent://
        if (url.startsWith("intent:")) {
            try {
                Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
                if (intent.resolveActivity(getActivity().getPackageManager()) != null) {
                    getActivity().startActivity(intent);
                    return true;
                }
                //try to find fallback url
                String fallbackUrl = intent.getStringExtra("browser_fallback_url");
                if (fallbackUrl != null) {
                    webView.loadUrl(fallbackUrl);
                    return true;
                }
                //invite to install
                Intent marketIntent = new Intent(Intent.ACTION_VIEW).setData(
                        Uri.parse("market://details?id=" + intent.getPackage()));
                if (marketIntent.resolveActivity(packageManager) != null) {
                    getActivity().startActivity(marketIntent);
                    return true;
                }
            } catch (URISyntaxException e) {
                //not an intent uri
            }
        }
        return true;//do nothing in other cases
    }

}

也许它需要一些清理,但它可能会有所帮助.如果您知道更简单的方法,请告诉我,我仍在寻找最佳解决方案.

Maybe it needs some cleanup, but it can be helpful. Please tell me if you know an easier way of doing this, i still looking for the best solution.

这篇关于Android 在 WebView 中打开 Intent://协议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆