【问题标题】:How to exclude a specific application from ACTION_SEND Intent?如何从 ACTION_SEND Intent 中排除特定应用程序?
【发布时间】:2016-07-13 08:08:50
【问题描述】:

我已使用以下代码从我的应用选择器中排除 facebook 应用:

 List<Intent> targetedShareIntents = new ArrayList<Intent>();
    Intent intent = new Intent(android.content.Intent.ACTION_SEND);
    intent.setType("image/*");
    List<ResolveInfo> resInfo = getActivity().getPackageManager().queryIntentActivities(intent, 0);
    if (!resInfo.isEmpty()) {
        for (ResolveInfo resolveInfo : resInfo) {
            String packageName = resolveInfo.activityInfo.packageName;
            Intent targetedShareIntent = new Intent(android.content.Intent.ACTION_SEND);
            targetedShareIntent.setType("image/*");
            targetedShareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "tooter.nl");
            if (!TextUtils.equals(packageName, "com.facebook.katana")) {


                targetedShareIntent.putExtra(android.content.Intent.EXTRA_TEXT, st);
                targetedShareIntent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
                targetedShareIntent.setPackage(packageName);
                targetedShareIntents.add(targetedShareIntent);
            }

        }
        Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(0), "Select app to share");
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[targetedShareIntents.size()]));
        startActivity(chooserIntent);
    }

当我使用该代码时,Facebook 应用程序已被删除。但可悲的是,甚至 Twitter 应用程序也被从应用程序选择器中删除,而其他不必要的应用程序(如“Android 系统”)也列在了选择器上。我该怎么办 ?这段代码有什么遗漏或错误吗?

【问题讨论】:

  • 除了facebook和twitter只显示,如果你想在facebook和twitter上分享数据你应该使用Facebook和Twitter SDK@mrnobody
  • @muruga5000 是的,我使用了 facebook sdk,因此我想在我的发送意图的应用程序选择器中排除它。然而,当我这样做时,推特也没有显示。我不需要单独的 twitter 共享,所以我想在应用选择器中使用它
  • @mrnobody 你想从本机共享意图中仅排除 facebook 吗?
  • @RaguSwaminathan 是的
  • 你要分享图片还是文字

标签: android android-intent


【解决方案1】:

在下面查看我的答案。它将仅从共享中排除 Facebook 应用程序。

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

    }
  }
}

然后在任何你想要的地方调用上面的函数。 如有疑问请告诉我。

【讨论】:

  • 伟大的..快乐的编码.. :)
  • 它给了我错误直接共享不可用
  • 谨慎使用这种方式,就像在 Android 11 中一样,包可见性会影响您可以查询哪些包以及哪些包实际上会显示给用户,即使它在查询中找到它们也是如此。
  • 它一直工作到 android 9(包括在内),而不是 10 及以下,建议使用 EXTRA_EXCLUDE_COMPONENT 而不是 EXTRA_INITIAL_INTENTS
【解决方案2】:

对于 Android API 24 及更高版本,您可以使用:

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

剩下的,你可以有我写过的this solution(它允许你有一个要排除的条件

这是一个更通用的解决方案,可以选择排除所有 Android 版本:

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

【讨论】:

    【解决方案3】:

    Android N (API 24) 引入黑名单Intent.EXTRA_EXCLUDE_COMPONENTS,比白名单Intent.EXTRA_INITIAL_INTENTS更好更简单。

    【讨论】:

    • 感谢您的验证,因为我想知道为什么 Intent.EXTRA_EXCLUDE_COMPONENTS 不起作用。
    【解决方案4】:

    我不得不排除 facebook 应用,因为它们使用 Intent#EXTRA_EXCLUDE_COMPONENTS 的分享意图(与用户原创性有关)有问题我诉诸于此:

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

    这仅适用于android N及以上

    【讨论】:

    • 这是 2021 年适用于几乎所有新设备的唯一解决方案。谢谢
    【解决方案5】:

    根据 Ragu Swaminathan 的回答更新了 Kotlin 的回答

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

    【讨论】:

    • 它在 API 29 上仅显示 3 个意图,而不是列入白名单的 15 个意图。
    【解决方案6】:

    感谢 Ragu Swaminathan 的回答,它可以完美地排除 IntentChooser 中的特定应用程序。但是,由于在 'chooserIntent' 前面添加了 'shareIntentLists',如果列表的大小不是 4 的倍数,可能会出现一些空格。要解决此问题,请尝试:

    Intent chooserIntent = Intent.createChooser(new Intent(), "Choose app to share");
    

    【讨论】:

      猜你喜欢
      • 2013-09-12
      • 2015-08-29
      • 1970-01-01
      • 2022-08-04
      • 2016-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-29
      相关资源
      最近更新 更多