25

I post this question here for educational purposes, since I couldn't find answers anywhere and eventually found the root cause the old way, i.e. by myself.

Here's the problematic code :

// initially getting the intent from polling the PackageManager about activities resolving Search intent.

ComponentName componentName = intent.resolveActivity(pm);

if (componentName != null) {
    context.startActivity(intent);
}

despite the check i get an ActivityNotFound exception.

EDIT: apparently the point wasn't obvious to everyone so : how come there's an activity resolving the intent, yet trying to launch it throws an ActivityNotFound exception - two facts apparently contradictory ?

tangerine
  • 836
  • 1
  • 8
  • 14

2 Answers2

35

From what i could see, intent.resolveActivity() will return true if there is ANY activity resolving this intent. Even if this activity is not exported (which makes it unusable for all practical purposes in case it's not from your package). Android's API doesn't care to mention that, so you have to figure it out by yourself, and make sure that the activity you're trying to launch is indeed exported.

ActivityInfo activityInfo = intent.resolveActivityInfo(pm, intent.getFlags());
if (activityInfo.exported) {
    doSomething();
}

EDIT: the point of this question is that ResolveActivity will return a componentName even if activityInfo.exported==false AND it's not from your own package - which makes it unlaunchable, and surprised me cause the intent was resolved and yet unlaunchable.

Devashish Mamgain
  • 2,077
  • 1
  • 18
  • 39
tangerine
  • 836
  • 1
  • 8
  • 14
  • I'm confused. To me, it appears that Intent.resolveActivity only has one parameter and returns a ComponentName. – Mooing Duck Aug 18 '15 at 22:11
  • 1
    @MooingDuck the method used in the answer is `resolveActivityInfo()` not `resolveActivity()` – yuval Sep 17 '15 at 00:21
  • Your solution is great, but wouldn't it be easier just to wrap code that starts the activity in try block and catch exception if there is no browser to handle intent, and maybe inform the user that there is no web browser installed or that the app is in restricted mode? – Markonioninioni Nov 17 '17 at 12:26
  • 6
    Great solution, just needs a null check as activityInfo can be null. – Alex Jul 02 '18 at 05:32
  • @Markonionini You could do that, but it's generally considered better to save exceptions for truly exceptional behavior. http://thefinestartist.com/effective-java/57 – Ellen Spertus Feb 11 '20 at 19:33
  • Thanks! It has been working until API 29. Currently when opening URL in API 30 emulator it returns `intent.resolveActivityInfo(pm, intent.getFlags()) == null` and `intent.resolveActivity(pm) == null`. See https://stackoverflow.com/questions/62535856/intent-resolveactivity-returns-null-in-api-30 for more info. Or use https://stackoverflow.com/questions/5882656/no-activity-found-to-handle-intent-android-intent-action-view/62531168. – CoolMind Jun 23 '20 at 16:05
3

ActivityNotFound exception is thrown when a call to startActivity(Intent) or one of its variants fails because an Activity can not be found to execute the given Intent. For example, if you’re trying to send an email, but there is no app on your device that could process ACTION_SEND intent action, ActivityNotFound will be thrown.

A way to avoid the exception is to do the following:

final ComponentName componentName = intent.resolveActivity(pm);
if (componentName != null) {
  try {
    context.startActivity(intent);    
  } catch (ActivityNotFoundException ex) {
    // Notify the user?
  }
}
Tadej
  • 2,901
  • 1
  • 17
  • 23
  • I know that, that was not my point :) I wanted to draw the attention to the fact that resolveActivity returns a componentName even if exported==false AND it's not from your own package - which makes it unlaunchable. For my particular use, which i didnt include here, i simply filtered the results i got from the pm manager when looking for specific intents with the if(exported) check. – tangerine Mar 18 '14 at 12:42
  • Well, there is no way of knowing what your point is, if you leave it out of your question. Glad you figured it out. – Tadej Mar 18 '14 at 13:06
  • I added it to the answer - i'll add it to the question. Thanks for your input. – tangerine Mar 18 '14 at 13:13
  • @Tadej The original question contained the point if the edit history doesn't lie. You should realize that it's a little bit strange if ActivityNotFoundException occurs if componentName isn't null. – The incredible Jan Sep 07 '21 at 08:52