I have used the following codes to exclude facebook app from my app chooser:
List targetedShareIntents = new ArrayList();
In
Android N (API 24) introduces blacklist Intent.EXTRA_EXCLUDE_COMPONENTS, which is better and simpler than whitelist Intent.EXTRA_INITIAL_INTENTS.
Updated Kotlin answer based on Ragu Swaminathan's answer
fun share() {
val shareIntent = Intent()
shareIntent.action = Intent.ACTION_SEND
shareIntent.type = "text/plain"
val resInfoList = activity?.packageManager?.queryIntentActivities(shareIntent, 0)
val shareIntentList = arrayListOf<Intent>()
if (resInfoList?.isNotEmpty() == true) {
for (resInfo in resInfoList) {
val packageName = resInfo.activityInfo.packageName
if (!packageName.toLowerCase().contains("discord")) {
val intent = Intent()
intent.component = ComponentName(packageName, resInfo.activityInfo.name)
intent.action = Intent.ACTION_SEND
intent.type = "text/plain"
intent.`package` = packageName
intent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
shareIntentList.add(intent)
}
}
}
if (shareIntentList.isEmpty()) {
Toast.makeText(activity, "No apps to share!", Toast.LENGTH_LONG).show()
} else {
val chooserIntent = Intent.createChooser(Intent(), "Choose app to share")
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, shareIntentList.toTypedArray())
activity?.startActivity(chooserIntent)
}
}
For Android API 24 and above, you can use this:
val components = arrayOf(ComponentName(applicationContext, YourActivity::class.java))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
startActivity(Intent.createChooser(intent, null).putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS,components))
For the rest, you can have this solution I wrote about (which allows you to have a condition which to exclude
Here's a more generalized solution, to be able to choose which to exclude for all Android versions:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val targetIntent = Intent(Intent.ACTION_SEND)
targetIntent.type = "text/plain"
targetIntent.putExtra(Intent.EXTRA_SUBJECT, "subject")
targetIntent.putExtra(Intent.EXTRA_TEXT, "text")
val excludedAppsPackageNames = hashSetOf( "com.pushbullet.android","com.android.bluetooth","com.google.android.apps.docs","com.google.android.gm")
getIntentChooser(this, targetIntent, "choose!", object : ComponentNameFilter {
override fun shouldBeFilteredOut(componentName: ComponentName): Boolean = excludedAppsPackageNames.contains(componentName.packageName)
})?.let { startActivity(it) }
}
interface ComponentNameFilter {
fun shouldBeFilteredOut(componentName: ComponentName): Boolean
}
private fun getIntentChooser(context: Context, intent: Intent, chooserTitle: CharSequence? = null, filter: ComponentNameFilter): Intent? {
val resolveInfos = context.packageManager.queryIntentActivities(intent, 0)
// Log.d("AppLog", "found apps to handle the intent:")
val excludedComponentNames = HashSet<ComponentName>()
resolveInfos.forEach {
val activityInfo = it.activityInfo
val componentName = ComponentName(activityInfo.packageName, activityInfo.name)
// Log.d("AppLog", "componentName:$componentName")
if (filter.shouldBeFilteredOut(componentName))
excludedComponentNames.add(componentName)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return Intent.createChooser(intent, chooserTitle).putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedComponentNames.toTypedArray())
}
if (resolveInfos.isNotEmpty()) {
val targetIntents: MutableList<Intent> = ArrayList()
for (resolveInfo in resolveInfos) {
val activityInfo = resolveInfo.activityInfo
if (excludedComponentNames.contains(ComponentName(activityInfo.packageName, activityInfo.name)))
continue
val targetIntent = Intent(intent)
targetIntent.setPackage(activityInfo.packageName)
targetIntent.component = ComponentName(activityInfo.packageName, activityInfo.name)
// wrap with LabeledIntent to show correct name and icon
val labeledIntent = LabeledIntent(targetIntent, activityInfo.packageName, resolveInfo.labelRes, resolveInfo.icon)
// add filtered intent to a list
targetIntents.add(labeledIntent)
}
val chooserIntent: Intent?
// deal with M list seperate problem
chooserIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// create chooser with empty intent in M could fix the empty cells problem
Intent.createChooser(Intent(), chooserTitle)
} else {
// create chooser with one target intent below M
Intent.createChooser(targetIntents.removeAt(0), chooserTitle)
}
if (chooserIntent == null) {
return null
}
// add initial intents
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toTypedArray<Parcelable>())
return chooserIntent
}
return null
}
}
I had to exclude facebook apps as they had a broken share intent (something about user originality) using Intent#EXTRA_EXCLUDE_COMPONENTS I resorted to this:
Intent intent = new Intent(Intent.ACTION_SEND);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
intent.setTypeAndNormalize("text/plain");
} else {
intent.setType("text/plain");
}
intent.putExtra(Intent.EXTRA_TEXT, "Text to share");
Intent chooser = Intent.createChooser(intent, "Share Text");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
ArrayList<ComponentName> targets = new ArrayList<>();
// remove facebook which has a broken share intent
for (ResolveInfo candidate : requireActivity().getPackageManager().queryIntentActivities(intent, 0)) {
String packageName = candidate.activityInfo.packageName;
if (packageName.toLowerCase().contains("facebook")) {
targets.add(new ComponentName(packageName, candidate.activityInfo.name));
}
}
chooser.putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, targets.toArray(new ComponentName[0]));
}
startActivity(chooser);
This only works for android N and above
Check my answer below. It will exclude only facebook application from sharing.
void shareOnOtherSocialMedia() {
List<Intent> shareIntentsLists = new ArrayList<Intent>();
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("image/*");
List<ResolveInfo> resInfos = getPackageManager().queryIntentActivities(shareIntent, 0);
if (!resInfos.isEmpty()) {
for (ResolveInfo resInfo : resInfos) {
String packageName = resInfo.activityInfo.packageName;
if (!packageName.toLowerCase().contains("facebook")) {
Intent intent = new Intent();
intent.setComponent(new ComponentName(packageName, resInfo.activityInfo.name));
intent.setAction(Intent.ACTION_SEND);
intent.setType("image/*");
intent.setPackage(packageName);
shareIntentsLists.add(intent);
}
}
if (!shareIntentsLists.isEmpty()) {
Intent chooserIntent = Intent.createChooser(shareIntentsLists.remove(0), "Choose app to share");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, shareIntentsLists.toArray(new Parcelable[]{}));
startActivity(chooserIntent);
} else
Log.e("Error", "No Apps can perform your task");
}
}
}
And call the above function wherever you want. Let me know for queries.
Thanks to Ragu Swaminathan's answer, it works perfectly to exclude specific application in an IntentChooser. However, because the 'shareIntentLists' is added in front of the 'chooserIntent', some empty spaces may occur if the size of list is not multiple of 4. To solve this, try:
Intent chooserIntent = Intent.createChooser(new Intent(), "Choose app to share");