Empty intent chooser (No application can perform t

2020-03-04 08:02发布

问题:

My intentchooser is on the basis of a whitelist (only a selection of applictions will show up in the intent chooser). The code is on the basis of another code wich does the oposite; blacklisting applications. I got that code from here and this is the related discussion related to it.

Context of how the chooser gets created:

        String[] whitelist = new String[] { "org.schiphol", "nl.negentwee", "org.schipholsecurity", "org.chineseschiphol", "nl.ns", "com.tomtom" };

    Intent intent = new Intent(Intent.ACTION_MAIN);
    //intent.addCategory(Intent.CATEGORY_LAUNCHER);

    startActivity(generateCustomChooserIntent(intent, whitelist));

The method I use to create the whitelisted chooser;

// Method:
private Intent generateCustomChooserIntent(Intent prototype, String[] whiteList) {
    List<Intent> targetedShareIntents = new ArrayList<Intent>();
    List<HashMap<String, String>> intentMetaInfo = new ArrayList<HashMap<String, String>>();
    Intent chooserIntent;

    Intent dummy = new Intent(prototype.getAction());
    dummy.setType(prototype.getType());
    List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(dummy, 0);
    MyLog.i(LOG_TAG, "Apps installed on device:" + resInfo.size());

    if (!resInfo.isEmpty()) {
        for (ResolveInfo resolveInfo : resInfo) {
            // MyLog.i(LOG_TAG, "Looking at:" + resolveInfo.activityInfo.packageName);

            if (resolveInfo.activityInfo == null) {
                MyLog.e(LOG_TAG, "resolved application has no activity info, so it is not usable.");
                continue;
            }

            if (Arrays.asList(whiteList).contains(resolveInfo.activityInfo.packageName)) {
                // MyLog.i(LOG_TAG, "=============================> accepted");

                HashMap<String, String> info = new HashMap<String, String>();
                info.put("packageName", resolveInfo.activityInfo.packageName);
                info.put("className", resolveInfo.activityInfo.name);
                info.put("simpleName", String.valueOf(resolveInfo.activityInfo.loadLabel(getPackageManager())));
                intentMetaInfo.add(info);
            } else {
                // MyLog.i(LOG_TAG, "rejected");
            }
        }

        if (!intentMetaInfo.isEmpty()) {
            MyLog.i(LOG_TAG, "--- done compiling list ---");

            // TODO enable sorting again
            // sorting for nice readability
            // Collections.sort(intentMetaInfo, new Comparator<HashMap<String, String>>() {
            // @Override
            // public int compare(HashMap<String, String> map, HashMap<String, String> map2) {
            // return map.get("simpleName").compareTo(map2.get("simpleName"));
            // }
            // });

            MyLog.i(LOG_TAG, "--- creating custom intent list ---");

            // create the custom intent list
            for (HashMap<String, String> metaInfo : intentMetaInfo) {
                MyLog.i(LOG_TAG, "adding " + metaInfo.get("packageName") + " to the intent list");

                Intent targetedShareIntent = (Intent) prototype.clone();
                targetedShareIntent.setPackage(metaInfo.get("packageName"));
                targetedShareIntent.setClassName(metaInfo.get("packageName"), metaInfo.get("className"));
                targetedShareIntents.add(targetedShareIntent);
            }

            MyLog.i(LOG_TAG, "--- done compiling intent list ---");
            MyLog.i(LOG_TAG, "total count targetedShareIntents: " + targetedShareIntents.size());

            chooserIntent = Intent.createChooser(targetedShareIntents.remove(targetedShareIntents.size() - 1), "Selecteer reis app (1)");
            MyLog.i(LOG_TAG, "--- chooser created ---");
            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[] {}));

            MyLog.e(LOG_TAG, "returning filled (custom) chooser");
            return chooserIntent;
        }
    }

    MyLog.e(LOG_TAG, "returning default chooser (empty)");
    return Intent.createChooser(prototype, "Selecteer reis app");
}

Now what happends is that the result chooser shows "No application can perform this action" While the logcat shows there are 5 apps selected.

Logcat Logged results:

06-28 13:04:48.679: I/NavigationTypeActivity(9400): Apps installed on device:356
06-28 13:04:48.687: I/NavigationTypeActivity(9400): --- done compiling list ---
06-28 13:04:48.687: I/NavigationTypeActivity(9400): --- creating custom intent list ---
06-28 13:04:48.687: I/NavigationTypeActivity(9400): adding org.chineseschiphol to the intent list
06-28 13:04:48.687: I/NavigationTypeActivity(9400): adding org.schiphol to the intent list
06-28 13:04:48.687: I/NavigationTypeActivity(9400): adding org.schipholsecurity to the intent list
06-28 13:04:48.687: I/NavigationTypeActivity(9400): adding nl.negentwee to the intent list
06-28 13:04:48.687: I/NavigationTypeActivity(9400): --- done compiling intent list ---
06-28 13:04:48.687: I/NavigationTypeActivity(9400): total count targetedShareIntents: 4
06-28 13:04:48.687: I/NavigationTypeActivity(9400): --- chooser created ---
06-28 13:04:48.687: E/NavigationTypeActivity(9400): returning filled (custom) chooser

回答1:

I got some feedback from an Android guru telling me the chooser should be defined with a working intent, for example the playstore or gmail or something. In theory you could supply the starting intent of your OWN application (you are sure that your own application is installed).

Intent chooserIntent = Intent.createChooser(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=gmail")), "example");

And later, that's why the list removes a single item from the list (you probably don't want your own application in the chooser).