【问题标题】:How to handle intent:// on a webView URL?如何在 webView URL 上处理 intent://?
【发布时间】:2016-01-14 01:42:42
【问题描述】:

我目前正在开发一个带有webView 的安卓应用程序。在某些urls 上,我需要使用shouldOverrideUrlLoading 方法,这非常简单:

if(url.startsWith("something")){
//do something
return true;
}

我的问题:

一些URLS,例如在谷歌搜索,有以下URL方案:

intent://en.m.wikipedia.org/wiki/Test_cricket#Intent;scheme=http;package=org.wikipedia;S.browser_fallback_url=https%3A%2F%2Fwww.google.pt%2Fsearchurl%2Fr.html%23app%3Dorg.wikipedia%26pingbase%3Dhttps%3A%2F%2Fwww.google.pt%2F%26url%3Dhttps%3A%2F%2Fen.m.wikipedia.org%2Fwiki%2FTest_cricket;S.android.intent.extra.REFERRER_NAME=https%3A%2F%2Fwww.google.pt;launchFlags=0x8080000;end

我尝试过使用:

Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(browserIntent);

但我得到一个错误:

10-15 15:18:15.546: W/System.err(29086): android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=intent://en.m.wikipedia.org/wiki/Test_cricket }

我应该如何处理这种URL方案?


更新:

在@CommonsWare cmets 之后,我尝试在Intent 上使用parseUri()URL 创建一个Intent object,然后尝试startActivity(),类似于:

Intent myIntent = new Intent().parseUri(url, Intent.URI_INTENT_SCHEME);
startActivity(myIntent);

但我仍然得到:

android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=http://en.m.wikipedia.org/wiki/Test_cricket flg=0x8080000 pkg=org.wikipedia (has extras) }

我的说明可能有误,或者我根本无法按照@CommonsWare 的规定构造intent。有关如何构建Intent 的任何提示?

【问题讨论】:

  • 在调用startActivity()之前,要么捕获ActivityNotFoundException,要么使用PackageManagerresolveActivity()检测这种情况。在这种情况下,Uri 指向应用程序(维基百科),如果未安装该应用程序,Intent 将无法解析。您需要向用户显示某种错误消息,表明这一事实。
  • @CommonsWare 如果点击带有intent://... 的链接,某些浏览器(Firefox、Chrome、Opera)会成功打开应用程序,有没有办法将 uri 转发到默认浏览器并让它处理它?
  • 默认浏览器没有处理它——维基百科应用程序应该处理它。不过,现在我想起来了,ACTION_VIEW 可能不是正确的答案。在Intent 上使用parseUri() 从URL 创建一个Intent 对象,然后在该Intent 上尝试startActivity()
  • @CommonsWare,有道理,让我试一试。之后我会告诉你的。
  • @PedroLobito:尝试将 BROWSABLE 类别添加到您正在创建的意图对象中——这是浏览器实际所做的:myIntent.addCategory(Intent.CATEGORY_BROWSABLE); 看起来维基百科应用程序在其意图过滤器中指定了此类别:@ 987654321@

标签: android webview


【解决方案1】:

此意图 URL 的结构在此处描述 https://developer.chrome.com/multidevice/android/intents

所以我们可以像这样在内部 WebView 中处理它:

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if (url.startsWith("intent://")) {
        try {
            Context context = view.getContext();
            Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);

            if (intent != null) {
                view.stopLoading();

                PackageManager packageManager = context.getPackageManager();
                ResolveInfo info = packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
                if (info != null) {
                    context.startActivity(intent);
                } else {
                    String fallbackUrl = intent.getStringExtra("browser_fallback_url");
                    view.loadUrl(fallbackUrl);

                    // or call external broswer
//                    Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(fallbackUrl));
//                    context.startActivity(browserIntent);
                }

                return true;
            }
        } catch (URISyntaxException e) {
            if (GeneralData.DEBUG) {
                Log.e(TAG, "Can't resolve intent://", e);
            }
        }
    }

    return false;
}

【讨论】:

  • 完美!终于有办法了
  • 注意:view.stopLoading(); 不是必需的,因为 URL 在此函数返回之前不会开始加载,并通过返回 true 来消耗。
  • 这可用于在 Android WebView 中显示 Firebase 短链接(例如 Google Map Url)。由于来自 webview,intent 不会触发,网页也不会显示。跨度>
  • 不适用于 Api 30。检查此链接以修复 medium.com/androiddevelopers/…
【解决方案2】:

Comrade's answer 是可以使用的。


我设法解决这个问题的方法不是优雅,但它确实有效。

首先我们检查 url startsWithintent:// 是否包含 scheme=http,如果是,我们在 intent://@ 之后立即获取值987654326@传给Intent.ACTION_VIEW,如果没有,我们return false(忽略点击)。
我已经用谷歌移动搜索的几个结果测试了这个解决方案,例如 twitterfacebookgoogle mapswikipedia 并且完美无缺。

@Override
public boolean shouldOverrideUrlLoading( WebView view, String url) {
    if(url.startsWith("intent://") && url.contains("scheme=http")){
        url = Uri.decode(url);
        String bkpUrl = null;
        Pattern regexBkp = Pattern.compile("intent://(.*?)#");
        Matcher regexMatcherBkp = regexBkp.matcher(url);
        if (regexMatcherBkp.find()) {
            bkpUrl = regexMatcherBkp.group(1);
            Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://"+bkpUrl));
            startActivity(myIntent);
            return true;
        }else{
            return false;
        }
   }
return false;
}

如果您有更好的解决方案,我想听听。
感谢大家的支持,特别是CommonsWare

【讨论】:

    【解决方案3】:

    处理intent:// url的简单方法

    binding.webView.webViewClient = object : WebViewClient() {
                override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
                    
                    if (url.startsWith("intent://")) {
                        val intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME)
                        startActivity(intent)
                        return true
                    }
                    return super.shouldOverrideUrlLoading(view, url)
                }
                .
                .
                .
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-16
      • 2016-05-31
      • 1970-01-01
      相关资源
      最近更新 更多