How to exclude a specific application from ACTION_SEND Intent?

Android N (API 24) introduces blacklist Intent.EXTRA_EXCLUDE_COMPONENTS, which is better and simpler than whitelist Intent.EXTRA_INITIAL_INTENTS.


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

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.


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