Skip to content

Instantly share code, notes, and snippets.

@mediavrog
Last active March 20, 2024 16:59
Show Gist options
  • Save mediavrog/5625602 to your computer and use it in GitHub Desktop.
Save mediavrog/5625602 to your computer and use it in GitHub Desktop.
Filter out Intents you don"t want to show from a IntentChooser dialog. For example your own app, competing apps or just apps you have a share integration by SDK already :) Based on http://stackoverflow.com/questions/5734678/custom-filtering-of-intent-chooser-based-on-installed-android-package-name/8550043#8550043
// Usage:
// blacklist
String[] blacklist = new String[]{"com.any.package", "net.other.package"};
// your share intent
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "some text");
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "a subject");
// ... anything else you want to add
// invoke custom chooser
startActivity(generateCustomChooserIntent(intent, blacklist));
// Method:
private Intent generateCustomChooserIntent(Intent prototype, String[] forbiddenChoices) {
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);
if (!resInfo.isEmpty()) {
for (ResolveInfo resolveInfo : resInfo) {
if (resolveInfo.activityInfo == null || Arrays.asList(forbiddenChoices).contains(resolveInfo.activityInfo.packageName))
continue;
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);
}
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) prototype.clone();
targetedShareIntent.setPackage(metaInfo.get("packageName"));
targetedShareIntent.setClassName(metaInfo.get("packageName"), metaInfo.get("className"));
targetedShareIntents.add(targetedShareIntent);
}
chooserIntent = Intent.createChooser(targetedShareIntents.remove(targetedShareIntents.size() - 1), getString(R.string.share));
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{}));
return chooserIntent;
}
}
return Intent.createChooser(prototype, getString(R.string.share));
}
@Nutomic
Copy link

Nutomic commented Apr 1, 2015

I've created a version of this with a whitelist instead of blacklist, and also cleaned the code in the process:

https://gist.github.com/Nutomic/528ac465df545f34193b

@bixir
Copy link

bixir commented Dec 15, 2015

This line:

info.put("simpleName", String.valueOf(resolveInfo.activityInfo.loadLabel(getPackageManager())));

doesn't always produce the expected label. For example, when using Intent.createChooser() I normally have these options: "ES Save to..." and "Send by LAN". but the above code produces in both cases the label "ES File Explorer". Also, it produces "Picasa Uploader" instead of "Picasa". For Picasa, even the icon is wrong (the generic android icon). What can be done to produce the normal labels and icons in all cases?

@Kevinrob
Copy link

Kevinrob commented Feb 5, 2018

@ranjeetscience
Copy link

Can anybody explain to me what is significance of this "targetedShareIntents.remove(targetedShareIntents.size() - 1)"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment