Fatal Exception: android.content.ActivityNotFoundException: No Activity found to handle Intent

16.5k views Asked by At

I'm getting following error on some devices while opening url. I don't get any error on my devices but many devices are.

Fatal Exception: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=https://google.com/... }
   at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:2076)
   at android.app.Instrumentation.execStartActivity(Instrumentation.java:1720)
   at android.app.Activity.startActivityForResult(Activity.java:5258)
   at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:574)
   at android.app.Activity.startActivityForResult(Activity.java:5203)
   at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:560)
   at android.app.Activity.startActivity(Activity.java:5587)
   at android.app.Activity.startActivity(Activity.java:5555)

The code where error occurs is pretty straight-forward.

Uri uri = Uri.parse("https://google.com");

try {
     CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
     builder.setShowTitle(true);
     CustomTabsIntent customTabsIntent = builder.build();
     Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://"));

     ResolveInfo resolveInfo = getPackageManager().resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY);
     if (resolveInfo != null && resolveInfo.activityInfo.packageName.length() > 0) {
         customTabsIntent.intent.setPackage(resolveInfo.activityInfo.packageName);
     }

     customTabsIntent.launchUrl(this, uri);
} catch (ActivityNotFoundException e) {
          // Do nothing
}

In some devices (not old devices, mostly newest device), exception triggered but how can it be possible? This means devices has 0 browser? If so, my question is how can I open url even user disabled all browsers? Thanks in advance.

Note: Before I upgraded to custom-tabs in the live version, I used following code to open url but I always get the ActivityNotFoundException:

Intent browserIntent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(browserIntent);

It is the simplest code the open any url but without usage of try/catch causes crashes. It doesn't matter to use normal way or custom-tabs, it always causes ActivityNotFoundException. I'm looking a solution which opening url whatever happens. I'm not sure whether it is possible or not.

Note2: MinApi is Android 5.0 (Lollipop)

enter image description here

3

There are 3 answers

1
Aykut Uludağ On BEST ANSWER

I create a method which based on @andreban's answer. I believe it will open url %99.99 times.

public static void openURL(Context mContext, Uri uri) {
    CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
    builder.setShowTitle(true);
    CustomTabsIntent customTabsIntent = builder.build();
    Intent browserIntent = new Intent()
            .setAction(Intent.ACTION_VIEW)
            .addCategory(Intent.CATEGORY_BROWSABLE)
            .setType("text/plain")
            .setData(Uri.fromParts("http", "", null));

    List<ResolveInfo> possibleBrowsers;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
        possibleBrowsers = mContext.getPackageManager().queryIntentActivities(browserIntent, PackageManager.MATCH_DEFAULT_ONLY);
        if (possibleBrowsers.size() == 0) {
            possibleBrowsers = mContext.getPackageManager().queryIntentActivities(browserIntent, PackageManager.MATCH_ALL);
        }
    } else {
        possibleBrowsers = mContext.getPackageManager().queryIntentActivities(browserIntent, PackageManager.MATCH_DEFAULT_ONLY);
    }

    if (possibleBrowsers.size() > 0) {
        customTabsIntent.intent.setPackage(possibleBrowsers.get(0).activityInfo.packageName);
        customTabsIntent.launchUrl(mContext, uri);
    } else {
        Intent browserIntent2 = new Intent(Intent.ACTION_VIEW, uri);
        mContext.startActivity(browserIntent2);
    }
}
3
andreban On

A few notes on this issue:

Detecting non-browser apps as browsers

They query for browsers can detect non-browser applications, which will lead the an ActivityNotFoundException when launching the Custom Tab. See this issue for an example.

When querying for packages that can handle browser intents, I recommend using the below:


Intent browserIntent = new Intent()
        .setAction(Intent.ACTION_VIEW)
        .addCategory(Intent.CATEGORY_BROWSABLE)
        .setData(Uri.fromParts("http", "", null));

This is also how the Android framework itself detects browsers.

The following shouldn't be a problem as the the Custom Tab will still work, but the behaviour of PackageManager.MATCH_DEFAULT_ONLY changed on Android M and only the default browser is returned - I'm not sure what happens if a default browser is not set, but this may mean the returned list will be empty instead. This will mean users will get the disambiguation dialog when a default browser is not set. From Android M and above you may also want additionally query the package manager using PackageManager.MATCH_ALL if you want to get all browsers avoid the disambiguation dialog.

Check out this snippet in the android-browser-helper library for detecting Custom Tabs and Trusted Web Activity.

Preparing for Android 11

Android 11 introduced package visibility and applications must now declare which packages they are querying for. If your application is not implementing this, the list returned when querying the package manage will be empty, even with a browser installed.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    possibleProviders.addAll(pm.queryIntentActivities(queryBrowsersIntent,
                    PackageManager.MATCH_ALL));
}

Again, this shouldn't cause an ActivityNotFoundException as it would just cause the Custom Tab to launch without a package set.

Disabled browsers

Note: Before I upgraded to custom-tabs in the live version, I used following code to open url but I always get the ActivityNotFoundException:

Intent browserIntent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(browserIntent);

It is possible for users to disable all browser applications, but I wouldn't expect this to be common.

Another thing to be aware of is that Android TV and Android Auto devices don't have a browser installed. If your application is targeting those devices you won't be able to open these URLs. But this is only a problem if your app is targeting these platforms.

0
Hadym Varan On

I also create a method which based on @andreban's answer, but I had a problem with url because it contained a query parameter.

ActivityNotFoundException when:

val url = "https://somesite.com/page?num=4"
val uri = Uri.parse(url)

Custom Tabs opened when:

val uri = Uri.Builder()
        .scheme("https")
        .authority("somesite.com")
        .appendPath("page")
        .appendQueryParameter("num", 4)
        .build()

This discussion helped create a uri