How to exclude a specific application from ACTION_SEND Intent?

后端 未结 6 514
伪装坚强ぢ
伪装坚强ぢ 2020-12-19 04:55

I have used the following codes to exclude facebook app from my app chooser:

 List targetedShareIntents = new ArrayList();
    In         


        
相关标签:
6条回答
  • 2020-12-19 05:20

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

    0 讨论(0)
  • 2020-12-19 05:22

    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)
            }
        }
    
    0 讨论(0)
  • 2020-12-19 05:24

    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
        }
    }
    
    0 讨论(0)
  • 2020-12-19 05:28

    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

    0 讨论(0)
  • 2020-12-19 05:36

    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.

    0 讨论(0)
  • 2020-12-19 05:42

    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");
    
    0 讨论(0)
提交回复
热议问题