Reordering applications in Intent chooser

时间:2017-06-12 16:53:48

标签: java android

I have a "share" button on my Android application which calls Intent.ACTION_SEND to display the available applications that the user can utilize to share a link. But I'd like for the applications to be displayed in a certain order, let's say, Whatsapp, then Messenger, then Facebook, and then all the other ones indiscriminately.

I've tried a few methods, it kind of works when I filter the apps to just those three, but then if I add the rest of them, either the apps always get displayed in the same order (happens on my Xiaomi), or the whole thing gets messed up and even duplicates some apps (happens on the Motorola I tested on).

This is kind of what I tried to do, just for testing purposes:

Intent sharingIntent = new Intent(Intent.ACTION_SEND);
List<ResolveInfo> resInfo = mActivity.getPackageManager().queryIntentActivities(sharingIntent, 0);

I then performed three for() loops that would each fully iterate through the resInfo list. Each loop would search for a specific app (Whatsapp, then Messenger, then Facebook) and add it to the Chooser. I then added another similar for() method, this time in order to add the remaining apps:

for (ResolveInfo resolveInfo : resInfo) {
    String packageName = resolveInfo.activityInfo.packageName;

    Intent targetedShareIntent = new Intent(android.content.Intent.ACTION_SEND);
    targetedShareIntent.setType("text/plain");
    targetedShareIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareBody);
    targetedShareIntent.setPackage(packageName);

    if (!packageName.equals("com.whatsapp") ||
            !packageName.equals("com.facebook.orca") ||
            !packageName.equals("com.facebook.katana")) {
        Toast.makeText(mActivity, packageName, Toast.LENGTH_SHORT).show();
        targetedShareIntents.add(targetedShareIntent);
    }
}

If I don't add this last method, the Chooser will only display the three first apps I added, and they'll even be displayed in different order if I change the order of the for() loops. But when I do add this method, every app will be displayed in the same order as if I had just regularly called the chooser intent.

Is there any way to work around this?

1 个答案:

答案 0 :(得分:1)

注意:这个答案仅供参考。这不是一个完整的解决方案。

我创建了自定义http intent,它从选择器中排除了某些应用。这可能对你有所帮助。如果我有足够的时间,我将为您的要求创建代码。我正在分享可能对您有帮助的代码。

public static void showBrowserIntent(Activity activity, String fileUrl, String[] forbiddenApps) {
    String[] blacklist = new String[]{"com.google.android.apps.docs"};

    if (forbiddenApps != null) {
        blacklist = forbiddenApps;
    }

    Intent httpIntent = new Intent(Intent.ACTION_VIEW);
    httpIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    httpIntent.setData(Uri.parse(fileUrl));
    httpIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);


    List<Intent> targetedShareIntents = new ArrayList<Intent>();
    List<HashMap<String, String>> intentMetaInfo = new ArrayList<HashMap<String, String>>();
    Intent chooserIntent;

    List<ResolveInfo> resInfo = activity.getPackageManager().queryIntentActivities(httpIntent, 0);

    Intent chooser = Intent.createChooser(httpIntent, "Choose Downloader/Browser");

    if (!resInfo.isEmpty()) {
        for (ResolveInfo resolveInfo : resInfo) {
            if (resolveInfo.activityInfo == null
                    || Arrays.asList(blacklist).contains(
                    resolveInfo.activityInfo.packageName))
                continue;
            //Get all the posible sharers
            HashMap<String, String> info = new HashMap<String, String>();
            info.put("packageName", resolveInfo.activityInfo.packageName);
            info.put("className", resolveInfo.activityInfo.name);
            String appName = String.valueOf(resolveInfo.activityInfo
                    .loadLabel(activity.getPackageManager()));
            info.put("simpleName", appName);
            //Add only what we want
            if (!Arrays.asList(blacklist).contains(
                    appName.toLowerCase())) {
                intentMetaInfo.add(info);
            }
        }

        if (!intentMetaInfo.isEmpty()) {
            // 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"));
                        }
                    });

            // create the custom intent list
            for (HashMap<String, String> metaInfo : intentMetaInfo) {
                Intent targetedShareIntent = (Intent) httpIntent.clone();
                targetedShareIntent.setPackage(metaInfo.get("packageName"));
                targetedShareIntent.setClassName(
                        metaInfo.get("packageName"),
                        metaInfo.get("className"));
                targetedShareIntents.add(targetedShareIntent);
            }
            String shareVia = "Open with";
            String shareTitle = shareVia.substring(0, 1).toUpperCase()
                    + shareVia.substring(1);
            chooserIntent = Intent.createChooser(targetedShareIntents
                    .remove(targetedShareIntents.size() - 1), shareTitle);
            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,
                    targetedShareIntents.toArray(new Parcelable[]{}));
            activity.startActivity(chooserIntent);
        }
    } else {
        activity.startActivity(chooser);
    }

}