使用ACTION_SEND意图过滤特定应用程序时出现异常?[重复]

3
I希望您在使用ACTION_SEND时能够过滤特定的应用程序,按照以下说明进行操作如何为ACTION_SEND意图过滤特定的应用程序(并针对每个应用程序设置不同的文本)
它在我的手机(Android M4 Aqua)上完美运行,但当我使用LG G3手机时,它会重复发送gmail,而且无法过滤Android Beam,Zalo,Blue Mail等应用程序。
它显示如下图片:过滤列表 以下是来自上述链接的代码:
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);       
 }

以下是我在LG G3手机上的调试结果: LG G3上的调试

“intentList”与上面代码中的列表“intentList”相同。

“resolveInfoList”是列表“resInfo”。

“list”只是一个测试列表,我用它来添加发送方包名。正如你所看到的,“intentList”只包含一个项目(gmail包项),但G3上的过滤器列表显示了6个项目:两个Gmail、Zalo、Android Beam、Email、BlueMail。我无法弄清楚为什么它与意图列表不同。有人能告诉我代码错在哪里吗?(这段代码在我的Android M4 Aqua上完美运行)更新 根据Keivan Esbati的评论,我更新了代码,几乎达到了我想要的效果,但出现了问题,如果我像这样添加gmail:

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

    Intent emailIntent = new Intent();
    emailIntent.setAction(Intent.ACTION_SENDTO);
    emailIntent.setData(Uri.parse("mailto:"));
    emailIntent.putExtra(Intent.EXTRA_TEXT, "123");
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, "q23");

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


    Intent openInChooser = Intent.createChooser(emailIntent, "string");

    List<ResolveInfo> resInfo = pm.queryIntentActivities(sendIntent, 0);
    List<LabeledIntent> intentList = new ArrayList<LabeledIntent>();
    for (int i = 0; i < resInfo.size(); i++) {
        ResolveInfo ri = resInfo.get(i);
        String packageName = ri.activityInfo.packageName;
        if (packageName.contains("android.email")) {
            emailIntent.setPackage(packageName);
        }

        if (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");
            intent.putExtra(Intent.EXTRA_TEXT, shareText.getText()
                .toString());
            intent.putExtra(Intent.EXTRA_SUBJECT,
                getString(R.string.intent_subject));
            intentList.add(new LabeledIntent(intent, packageName, ri
                .loadLabel(pm), ri.icon));
        }
    }

在LG G3中应该可以工作,但在Sony M4中只显示默认邮件。如果像下面的代码一样将其删除:

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

        Intent emailIntent = new Intent();
        emailIntent.setAction(Intent.ACTION_SENDTO);
        emailIntent.setData(Uri.parse("mailto:"));

        emailIntent.putExtra(Intent.EXTRA_TEXT, "123");
        emailIntent.putExtra(Intent.EXTRA_SUBJECT, "q23");

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


        Intent openInChooser = Intent.createChooser(emailIntent, "string");

        List<ResolveInfo> resInfo = pm.queryIntentActivities(sendIntent, 0);
        List<LabeledIntent> intentList = new ArrayList<LabeledIntent>();
        for (int i = 0; i < resInfo.size(); i++) {
            ResolveInfo ri = resInfo.get(i);
            String packageName = ri.activityInfo.packageName;
            if (packageName.contains("android.email")) {
                emailIntent.setPackage(packageName);
            }
        }
   //tried to remove duplicated items but it didn't work
  Set<LabeledIntent> stringSet=new HashSet<LabeledIntent>();
        stringSet.addAll(intentList);
        intentList.clear();
        intentList.addAll(stringSet);
        LabeledIntent[] extraIntents = intentList.toArray(new LabeledIntent[intentList.size()]);
        openInChooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents);
        startActivity(openInChooser);
    }

即使我尝试使用哈希表删除标记列表中的重复项,它仍然没有起作用,仍然有两个Gmail项留在列表中。我该如何摆脱它?
1个回答

1
这是因为Intent.EXTRA_INITIAL_INTENTS标记告诉选择器要在初始Intent的应用程序中添加支持特定意图的应用程序。 由于Gmail应用程序同时支持emailIntent和sendIntent,因此它在列表中出现两次。 您可以简单地删除android.gm部分,因为Gmail支持message/rfc822邮件。 更新: 由于您为两个Intent创建了选择器,因此必须查询两个Intent并仅添加不重复的应用程序,因此首先查询电子邮件Intent,添加所有应用程序,然后查询发送Intent,但仅添加其包名称尚不存在的应用程序。

我将标志从Intent.EXTRA_INITIAL_INTENTS更改为EXTRA_SHORTCUT_NAME(或ACTION_SEND),重复项消失了,但Android Beam仍然存在。你能建议我选择哪种意图以及为什么吗? - Btnisme123
我按照你的建议将“emailIntent”操作从SEND更改为SENDTO,并添加了intent.setData(Uri.parse("mailto:")),但它只显示一个文本对话框:“没有应用程序可以执行此操作”。 - Btnisme123
抱歉,忘了提到你需要删除emailIntent.setType("message/rfc822")这部分代码。 完整的示例可以参考Google官方指南: https://developer.android.com/guide/components/intents-common.html#Email - Keivan Esbati
我更新了我的答案,代码部分应该很容易实现,看起来你只是忘记了如果你不查询第一个意图,你就找不到要删除的重复项。 由于你为两个Intent创建了chooser,所以不可避免地会跨越相同的应用程序,因此一种方法是手动删除相同的包。 - Keivan Esbati
@Btnisme123,你已经查询并添加了兼容的应用程序(queryIntentActivities),但是你忘记查询你的第一个意图了..(你只将第一个意图添加到了选择器中,并且只查询了第二个意图)。像第二个意图一样查询你的第一个意图,如果它还没有被添加到列表中,就将其添加进去。 - Keivan Esbati
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接