Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android open intent:// protocol in 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...

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

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

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)

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.

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

like image 648
j2esu Avatar asked Feb 24 '16 17:02

j2esu


People also ask

How to open intent in android?

1.2. To start an activity, use the method startActivity(intent) . This method is defined on the Context object which Activity extends. The following code demonstrates how you can start another activity via an intent.

How to enable js in WebView android?

Enable JavaScript JavaScript is disabled in a WebView by default. You can enable it through the WebSettings attached to your WebView . You can retrieve WebSettings with getSettings() , then enable JavaScript with setJavaScriptEnabled() . WebView myWebView = (WebView) findViewById(R.

What is android intent action view?

An intent allows you to start an activity in another app by describing a simple action you'd like to perform (such as "view a map" or "take a picture") in an Intent object.


1 Answers

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. Open http and https in the same WebView
  2. Tries to handle known schemes (tel: etc.)
  3. If can't find a known activity, parses intent: scheme and tries to run appropriate app
  4. If required app not installed, tries to load provided fallback url into current WebView
  5. If no fallback url provided, redirects to market and ask to install required app

The code is:

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.

like image 187
j2esu Avatar answered Oct 03 '22 11:10

j2esu