开发者

Intent resolution and difference between ACTION_CHOOSER and ACTION_PICK_ACTIVITY

I have a question about intent resolution and the difference between Intent.ACTION_PICK_ACTIVITY and Intent.ACTION_CHOOSER (including it's convenience function version, Intent.createChooser()).

I'm writing a "package manager" app. In it I have a ListActivity that displays all packages installed on the device (populated with PackageManager.getInstalledPackages()). I also have a context menu registered on the list, one of whose items is "Launch".

Below is my code from onContextItemSelected() for handling the "Launch" context menu item.

Intent intent ;
List<ResolveInfo> ris ;
int nLauchables ;
int REQUEST_LAUNCH = 1 ;    // for use in onActivityResult()
// PackageInfo pi ;         // set outside this code

intent = new Intent (Intent.ACTION_MAIN) ;
intent.addCategory (Intent.CATEGORY_LAUNCHER) ;
intent.setPackage (pi.packageName) ; // limit to launchable activities in the package represented by pi

ris = getPackageManager ().queryIntentActivities (intent, 0) ; // get list of launchable activities in pi
nLaunchables = ris.size () ;

if (ris == null || nLaunchables == 0) {
// do nothing (in the real code, the "Launch" item is already disabled in this case, so this never happens)
    }
else if (nLaunchables == 1) {
// only 1 launchable activity, so just start that activity

    intent.setComponent (new ComponentName (ris.get (0).activityInfo.packageName, ris.get (0).activityInfo.name)) ;

    startActivity (intent) ;
    }
else if (nLaunchables > 1) {
// mutiple launchable activites, so let the user choose which one they want to launch

//  Intent chooseIntent = new Intent (Intent.ACTION_CHOOSER) ;
//  chooseIntent.putExtra (Intent.EXTRA_INTENT, intent) ;
//  chooseIntent.putExtra (Intent.EXTRA_TITLE, "Select activity") ;
//  startActivity (chooseIntent) ;                                     // doesn't show all launchable activities in the package
//
// or
//
//  startActivity (Intent.createChooser (intent, "Select activity") ;  // doesn't show all launchable activities in the package

    Intent pickIntent = new Intent (Intent.ACTION_PICK_ACTIVITY) ;
    pickIntent.putExtra (Intent.EXTRA_INTENT, intent) ;

    startActivityForResult (pickIntent, REQUEST_LAUNCH) ;
    }

I first tried the ACTION_CHOOSER version...but it doesn't always show all launchable activities in the package. For example, Google Maps has 4 launchable activities (Latitude, Maps, Navigation and Places) that show up with ACTION_PICK_ACTIVITY but ACTION_CHOOSER only shows 2 (Latitude, Maps). The only thing I can see that is different between the activities that do show when using ACTION_CHOOSER and those that don't is that they have CATEGORY_DEFAULT in their <intent-filter>s.

Below are the parts of the documentation that I have consulted to understand what is going on:

Docs for CATEGORY_DEFAULT say, in part, "Setting this will hide from the user any activities without it set when performing an action on some data."

This seems to explain the behavior I'm seeing...but...

Docs for ACTION_CHOOSER say, in part, "...all possible activities will always be shown even if one of them is currently marked as the preferred activity." (emphasis mine)

This seems to be in conflict with the above docs for CATEGORY_DEFAULT and suggests that using ACTION_CHOOSER and ACTION_PICK_ACTIVITY should produce the same results....and...

Docs for Intents and Intent Resolution (sorry, as a new user, I'm limited to 2 links in a post, so I can't 开发者_运维百科link to this...just look in the "Intent Resolution" section, "Category test" subsection), says, in part, "Android treats all implicit intents passed to startActivity() as if they contained at least one category: android.intent.category.DEFAULT" (the CATEGORY_DEFAULT constant). Therefore, activities that are willing to receive implicit intents must include android.intent.category.DEFAULT" in their intent filters. (Filters with android.intent.action.MAIN" and android.intent.category.LAUNCHER" settings are the exception. They mark activities that begin new tasks and that are represented on the launcher screen. They can include "android.intent.category.DEFAULT" in the list of categories, but don't need to.)" (emphasis mine)

Again, this seems to explicitly say that using ACTION_CHOOSER and ACTION_PICK_ACTIVITY should produce the same results.

So, is this just a case of incomplete documentation for ACTION_CHOOSER (i.e., that it doesn't mention that CATEGORY_DEFAULT activities are excluded) or is there something else going on?

Using ACTION_PICK_ACTIVITY works for me but is not ideal because of the need for calling startActivityForResult() with it (rather than just startActivity()).


I think your reading of those last two excerpts from the documentation is not the intended meaning. Starting with the ACTION_CHOOSER doc, "...all possible activities will always be shown even if one of them is currently marked as the preferred activity," specifically refers to preferred activities. Normally, when you use an implicit intent, and more than one activity matches, if the user has previously chosen "Always" from a previous chooser for this intent, then you'll get that activity without a chooser. If you use the ACTION_CHOOSER intent, you'll get all the activities that match, even if one has been chosen. That's all this line means: "all possible activities" means all activities that match the intent filter, taking categories into account too. It's simply another explanation of the difference between getting a chooser automatically vs. using ACTION_CHOOSER.

The other part you call out, about android.intent.action.MAIN and android.intent.category.LAUNCHER, doesn't mean that that action and category are handled specially in the intent filtering process. Don't forget that most people reading this documentation are simply writing launchable apps, and need to know what to put in their manifest to get an activity shown in the launcher. The "exception" here isn't an exception to the intent filter rules: it's an exception to the usual behaviour that implicit intents use CATEGORY_DEFAULT, and that's only an exception because launchers set this category (CATEGORY_LAUNCHER) instead of CATEGORY_DEFAULT.

In summary, the whole area of intent resolution is quite underdocumented, as you've found, but there's no inconsistency in the excerpts you've mentioned: they're just talking about slightly different things.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜