Jaqualembo
Jaqualembo

Reputation: 201

Reordering applications in Intent chooser

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?

Upvotes: 0

Views: 861

Answers (1)

Sagar Chapagain
Sagar Chapagain

Reputation: 1763

Note: This answer is for idea only. It is not a complete solution.

I have created the custom http intent which excludes certain apps from the chooser. This might be helpful for you. If I got enough time I will create code for your requirement. I am sharing my code which might be helpful for you.

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);
    }

}

Upvotes: 1

Related Questions