5

I have an Android app that does this:

    PackageManager pm = getApplicationContext().getPackageManager();
    Intent browserIntent = new Intent();
    browserIntent.setAction(Intent.ACTION_VIEW);
    browserIntent.addCategory(Intent.CATEGORY_BROWSABLE);
    browserIntent.setData(Uri.parse("http://www.google.com"));

    ResolveInfo resolveInfo = pm.resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY);
    try {
        String browserType = nutent.activityInfo.packageName;
    } catch (NullPointerException npe) {
        npe.printStackTrace();
    }

I have tested this on 4 different handsets and many different emulator configurations. All of them work fine. But I'm getting crash reports from deployed applications in the wild throwing an NPE since resolveInfo is sometimes null.

The immediate fix is to catch the NPE and deal with it before it crashes my app (as done above). But I've tried for days to reproduce this myself and cannot. On an emulator with a single default browser installed, it resolves to com.android.browser.BrowserActivity:

ResolveInfo{411ef228 com.android.browser.BrowserActivity p=0 o=0 m=0x208000}

Likewise, on a handset with multiple browsers installed, this resolves somewhat differently...to com.android.internal.app.ResolverActivity:

ResolveInfo{415c13b8 com.android.internal.app.ResolverActivity p=0 o=0 m=0x0}

The resolveActivity() docs here state:

Returns a ResolveInfo containing the final activity intent that was determined to be the best action. Returns null if no matching activity was found. If multiple matching activities are found and there is no default set, returns a ResolveInfo containing something else, such as the activity resolver.

So I have covered the first scenario, that of an activity intent determined to be the best action. Also the last scenario, that of multiple matching activities with no default action, returning the ResolverActivity.

I would really like to reproduce the scenario of resolveActivity() giving me a null when requesting the activity of a URL. Does anyone have any ideas how this can be done without, say, rooting the device?

Goo
  • 1,318
  • 1
  • 13
  • 31
AWT
  • 3,657
  • 5
  • 32
  • 60
  • As an aside, to "eat" the exception as you do is bad practice. Exceptions are thrown for good reason and as you are accessing an external resource, there are multiple reasons it might fail and your code should deal with them. – Simon Dec 21 '12 at 19:36
  • This is actually just a "dummy" intent that is only used to fetch browser type and version (if available), it is never used to retrieve any web pages or do anything else. I believe that, in this case, eating the exception and setting my browser type and version strings to "unknown" is adequate. There is nothing else I would want to do with the exception. – AWT Dec 21 '12 at 19:48
  • 2
    Good question. I don't know for sure either but my guess is that maybe you haven't covered the last scenario "that of multiple matching activities with no default action" even though you think you have, because you're specifying MATCH_DEFAULT_ONLY. I haven't cracked the source of PackageManager (good next step), but I wonder what it does if you tell it to match default, and there is no default, return null? Have you tested on a device or emulator with multiple browsers and NO DEFAULT set? (Make sure the chooser comes up if you click a link, etc.) – Charlie Collins Dec 21 '12 at 21:42
  • Good ideas, I will work through those tonight and see how it goes. – AWT Dec 22 '12 at 00:59
  • 2
    Maybe these crash reports coming from phone without browser? When you root your phone you can remove even system apps, so you can remove even build-in android browser. Also this could be because of custom firmware. You know, there are hundreds of china-phones working on android with custom firmware preinstalled. Often some android applications on this phones replaced with custom. So maybe there are custom browsers that did not resolve to your intent. – s.maks Feb 28 '13 at 10:06
  • @s.maks this is indeed the problem, I confirmed it by rooting my phone and removing all of the browsers. If you want to write it up as an answer I will accept it. – AWT Mar 01 '13 at 14:47

1 Answers1

0

I would really like to reproduce the scenario of resolveActivity() giving me a null when requesting the activity of a URL. Does anyone have any ideas how this can be done without, say, rooting the device?

  1. Go to Settings > Apps > ALL > Locate the browser(s) (on Nexus 4 with stock ROM that'd be Chrome) > Disable
  2. Start catching NPEs :)
ozbek
  • 20,955
  • 5
  • 61
  • 84