小编典典

如何过滤 ACTION_SEND 意图的特定应用程序(并为每个应用程序设置不同的文本)

all

使用 ACTION_SEND 意图时如何过滤掉特定的应用程序?
已经以各种方式提出了这个问题,但我无法根据给出的答案收集解决方案。希望有人可以提供帮助。我想提供在应用程序内共享的能力。按照建议,我更愿意使用意图而不是使用 Facebook/Twitter API。

使用 ACTION_SEND 意图共享

使用 ACTION_SEND 意图共享很棒,但 问题是(1)我不希望那里的每个共享选项,我宁愿将其限制为 FB、Twitter
和电子邮件,以及(2)我不想共享每个共享应用程序都一样
。例如,在我的 twitter 分享中,我将包含一些提及和主题标签,将其限制为 140
个字符或更少,而 facebook 分享将包含链接和特色图片。

是否可以限制 ACTION_SEND(共享)意图的选项?我已经看到有关使用 PackageManager 和 queryIntentActivities
的一些信息,但无法弄清楚 PackageManager 和 ACTION_SEND 意图之间的联系。

或者

如果我可以使用 ACTION_SEND 意图直接转到 facebook 或 twitter
而不是弹出对话框,那么我的问题也可以解决,而不是过滤共享应用程序。如果是这种情况,那么我可以创建自己的对话框,当他们单击“Facebook”时,创建一个特定于
Facebook 的意图,然后将它们一直发送到 Facebook。与推特相同。

或者不可能吗?Facebook 和 Twitter API 是唯一的方法吗?


阅读 60

收藏
2022-07-08

共1个答案

小编典典

据我所知,StackOverflow 有很多人以各种方式提出这个问题,但还没有人完全回答。

我的规范要求用​​户能够选择电子邮件、推特、脸书或短信,并为每个用户选择自定义文本。这是我如何做到的:

public void onShareClick(View v) {
    Resources resources = getResources();

    Intent emailIntent = new Intent();
    emailIntent.setAction(Intent.ACTION_SEND);
    // Native email client doesn't currently support HTML, but it doesn't hurt to try in case they fix it
    emailIntent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(resources.getString(R.string.share_email_native)));
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, resources.getString(R.string.share_email_subject));
    emailIntent.setType("message/rfc822");

    PackageManager pm = getPackageManager();
    Intent sendIntent = new Intent(Intent.ACTION_SEND);     
    sendIntent.setType("text/plain");


    Intent openInChooser = Intent.createChooser(emailIntent, resources.getString(R.string.share_chooser_text));

    List<ResolveInfo> resInfo = pm.queryIntentActivities(sendIntent, 0);
    List<LabeledIntent> intentList = new ArrayList<LabeledIntent>();        
    for (int i = 0; i < resInfo.size(); i++) {
        // Extract the label, append it, and repackage it in a LabeledIntent
        ResolveInfo ri = resInfo.get(i);
        String packageName = ri.activityInfo.packageName;
        if(packageName.contains("android.email")) {
            emailIntent.setPackage(packageName);
        } else if(packageName.contains("twitter") || packageName.contains("facebook") || packageName.contains("mms") || packageName.contains("android.gm")) {
            Intent intent = new Intent();
            intent.setComponent(new ComponentName(packageName, ri.activityInfo.name));
            intent.setAction(Intent.ACTION_SEND);
            intent.setType("text/plain");
            if(packageName.contains("twitter")) {
                intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.share_twitter));
            } else if(packageName.contains("facebook")) {
                // Warning: Facebook IGNORES our text. They say "These fields are intended for users to express themselves. Pre-filling these fields erodes the authenticity of the user voice."
                // One workaround is to use the Facebook SDK to post, but that doesn't allow the user to choose how they want to share. We can also make a custom landing page, and the link
                // will show the <meta content ="..."> text from that page with our link in Facebook.
                intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.share_facebook));
            } else if(packageName.contains("mms")) {
                intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.share_sms));
            } else if(packageName.contains("android.gm")) { // If Gmail shows up twice, try removing this else-if clause and the reference to "android.gm" above
                intent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(resources.getString(R.string.share_email_gmail)));
                intent.putExtra(Intent.EXTRA_SUBJECT, resources.getString(R.string.share_email_subject));               
                intent.setType("message/rfc822");
            }

            intentList.add(new LabeledIntent(intent, packageName, ri.loadLabel(pm), ri.icon));
        }
    }

    // convert intentList to array
    LabeledIntent[] extraIntents = intentList.toArray( new LabeledIntent[ intentList.size() ]);

    openInChooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents);
    startActivity(openInChooser);       
}

我在不同的地方找到了一些如何做到这一点,但我还没有在其他任何地方看到所有这些。

请注意,此方法还隐藏了我不想要的所有愚蠢选项,例如通过 wifi 和蓝牙共享。

希望这可以帮助某人。

编辑:
在评论中,我被要求解释这段代码在做什么。基本上,它只为本地电子邮件客户端创建一个ACTION_SEND意图,然后将其他意图附加到选择器上。使原始意图电子邮件特定于摆脱所有额外的垃圾,如
wifi 和蓝牙,然后我从ACTION_SEND纯文本类型的通用中获取我想要的其他意图,并在显示选择器之前将它们附加上。

当我获取其他意图时,我为每个意图设置了自定义文本。

Edit2: 自从我发布此内容以来已经有一段时间了,事情发生了一些变化。如果您在选项列表中看到 gmail 两次,请尝试按照下面@h_k
的评论中的建议删除“android.gm”的特殊处理。

2022-07-08