Android 如何通过 Intents 打开电子邮件程序(但仅限于电子邮件程序)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3312438/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 09:40:01  来源:igfitidea点击:

How to open Email program via Intents (but only an Email program)

android

提问by Dan Lew

I want to setup a part of my application that allows users to send a quick email to another user. It's not very hard to set this up:

我想设置我的应用程序的一部分,允许用户向另一个用户发送快速电子邮件。设置它并不难:

Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
intent.putExtra(Intent.EXTRA_TEXT, message);
Intent mailer = Intent.createChooser(intent, null);
startActivity(mailer);

However, the problem is that the ACTION_SEND is accepted by more than just email programs - for example, on my phone the Facebook app, Twitter, reddit is fun, and even Bluetooth come up as viable alternatives for sending this message. The message is entirely too long for some of these (especially Twitter).

然而,问题是 ACTION_SEND 不仅仅被电子邮件程序接受 - 例如,在我的手机上,Facebook 应用程序、Twitter、reddit 很有趣,甚至蓝牙也作为发送此消息的可行替代方案出现。对于其中一些(尤其是 Twitter)来说,这条消息太长了。

Is there a way to limit the chooser to just applications that support long messages (such as email)? Or is there a way to detect the app that the user has chosen and adjust the message appropriately?

有没有办法将选择器限制为仅支持长消息(例如电子邮件)的应用程序?或者有没有办法检测用户选择的应用程序并适当调整消息?

回答by Dan Lew

Thanks to Pentium10's suggestion of searching how Linkify works, I have found a great solution to this problem. Basically, you just create a "mailto:" link, and then call the appropriate Intent for that.:

感谢 Pentium10 建议搜索 Linkify 的工作原理,我找到了一个很好的解决方案。基本上,您只需创建一个“mailto:”链接,然后为此调用适当的 Intent。:

Intent intent = new Intent(Intent.ACTION_VIEW);
Uri data = Uri.parse("mailto:?subject=" + subject + "&body=" + body);
intent.setData(data);
startActivity(intent);

There are a few interesting aspects to this solution:

这个解决方案有几个有趣的方面:

  1. I'm using the ACTION_VIEW action because that's more appropriate for a "mailto:" link. You could provide no particular action, but then you might get some unsatisfactory results (for example, it will ask you if you want to add the link to your contacts).

  2. Since this is a "share" link, I am simply including no email address - even though this is a mailto link. It works.

  3. There's no chooser involved. The reason for this is to let the user take advantage of defaults; if they have set a default email program, then it'll take them straight to that, bypassing the chooser altogether (which seems good in my mind, you may argue otherwise).

  1. 我正在使用 ACTION_VIEW 操作,因为它更适合“mailto:”链接。您可以不提供特定操作,但随后您可能会得到一些不满意的结果(例如,它会询问您是否要向您的联系人添加链接)。

  2. 由于这是一个“共享”链接,我只是不包括电子邮件地址 - 即使这是一个 mailto 链接。有用。

  3. 不涉及选择器。这样做的原因是让用户利用默认值;如果他们设置了默认电子邮件程序,那么它会直接将他们带到那个程序,完全绕过选择器(这在我看来似乎很好,你可能会反驳)。

Of course there's a lot of finesse I'm leaving out (such as properly encoding the subject/body), but you should be able to figure that out on your own.

当然,我遗漏了很多技巧(例如正确编码主题/正文),但您应该能够自己弄清楚。

回答by Jeff S

Changing the MIME type is the answer, this is what I did in my app to change the same behavior. I used intent.setType("message/rfc822");

更改 MIME 类型就是答案,这就是我在我的应用程序中所做的更改相同行为的操作。我用了intent.setType("message/rfc822");

回答by Haris ur Rehman

This worked for me

这对我有用

Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
emailIntent.setType("vnd.android.cursor.item/email");
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] {"[email protected]"});
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "My Email Subject");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "My email content");
startActivity(Intent.createChooser(emailIntent, "Send mail using..."));

回答by idolize

Have you tried including the Intent.EXTRA_EMAILextra?

你试过包括Intent.EXTRA_EMAIL额外的吗?

Intent mailer = new Intent(Intent.ACTION_SEND);
mailer.setType("text/plain");
mailer.putExtra(Intent.EXTRA_EMAIL, new String[]{"[email protected]"});
mailer.putExtra(Intent.EXTRA_SUBJECT, subject);
mailer.putExtra(Intent.EXTRA_TEXT, bodyText);
startActivity(Intent.createChooser(mailer, "Send email..."));

That may restrict the list of available receiver applications...

这可能会限制可用接收器应用程序的列表...

回答by Ashish

Try this one

试试这个

Intent intent = new Intent("android.intent.action.SENDTO", Uri.fromParts("mailto", "[email protected]", null));
intent.putExtra("android.intent.extra.SUBJECT", "Enter Subject Here");
startActivity(Intent.createChooser(intent, "Select an email client")); 

回答by user10496632

None of the solutions worked for me. Thanks to the Open source developer, ckettifor sharing his/her concise and neat solution.

没有一个解决方案对我有用。感谢开源开发人员cketti分享他/她简洁而简洁的解决方案。

String mailto = "mailto:[email protected]" +
    "?cc=" + "[email protected]" +
    "&subject=" + Uri.encode(subject) +
    "&body=" + Uri.encode(bodyText);

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

try {
  startActivity(emailIntent);
} catch (ActivityNotFoundException e) {
  //TODO: Handle case where no email app is available
}

And thisis the link to his/her gist.

是链接到他/她的要点。

回答by BadSkillz

Try changing the MIME type from plain to message

尝试将 MIME 类型从普通更改为消息

intent.setType("text/message");

回答by Ashish Jaiswal

try this option:

试试这个选项:

Intent intentEmail = new Intent(Intent.ACTION_SEND);
intentEmail.setType("message/rfc822");

回答by Peterdk

This is a bit of a typo, since you need to switch your mimetype:

这有点打字错误,因为您需要切换 mimetype:

intent.setType("plain/text"); //Instead of "text/plain"

回答by Ayyappa

SEND TO EMAIL CLIENTS ONLY - WITH MULTIPLE ATTACHMENTS

仅发送给电子邮件客户 - 带有多个附件

There are many solutions but all work partially.

有很多解决方案,但都部分起作用。

mailtoproperly filters email apps but it has the inability of not sending streams/files.

mailto正确过滤电子邮件应用程序,但它无法不发送流/文件。

message/rfc822opens up hell of apps along with email clients

message/rfc822与电子邮件客户端一起打开了地狱般的应用程序

so, the solution for this is to use both.

因此,解决方案是同时使用两者。

  1. First resolve intent activities using mailto intent
  2. Then set the data to each activity resolved to send the required data
  1. 首先使用mailto意图解决意图活动
  2. 然后设置数据到每个activity解析发送需要的数据
private void share()
{
     Intent queryIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"));
     Intent dataIntent  = getDataIntent();

     Intent targetIntent = getSelectiveIntentChooser(context, queryIntent, dataIntent);
     startActivityForResult(targetIntent);
}

Build the required data intent which is filled with required data to share

构建所需的数据意图,其中填充了要共享的所需数据

private Intent getDataIntent()
{
        Intent dataIntent = buildIntent(Intent.ACTION_SEND, null, "message/rfc822", null);

        // Set subject
        dataIntent.putExtra(Intent.EXTRA_SUBJECT, title);

        //Set receipient list.
        dataIntent.putExtra(Intent.EXTRA_EMAIL, toRecipients);
        dataIntent.putExtra(Intent.EXTRA_CC, ccRecipients);
        dataIntent.putExtra(Intent.EXTRA_BCC, bccRecipients);
        if (hasAttachments())
        {
            ArrayList<Uri> uris = getAttachmentUriList();

            if (uris.size() > 1)
            {
                intent.setAction(Intent.ACTION_SEND_MULTIPLE);
                dataIntent.putExtra(Intent.EXTRA_STREAM, uris);
            }
            else
            {
                dataIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris.get(0));
            }
        }

        return dataIntent;
}

protected ArrayList<Uri> getAttachmentUriList()
{
        ArrayList<Uri> uris = new ArrayList();
        for (AttachmentInfo eachAttachment : attachments)
        {
            uris.add(eachAttachment.uri);
        }

        return uris;
}

Utitlity class for filtering required intents based on query intent

用于根据查询意图过滤所需意图的实用程序类

// Placed in IntentUtil.java
public static Intent getSelectiveIntentChooser(Context context, Intent queryIntent, Intent dataIntent)
{
        List<ResolveInfo> appList = context.getPackageManager().queryIntentActivities(queryIntent, PackageManager.MATCH_DEFAULT_ONLY);

        Intent finalIntent = null;

        if (!appList.isEmpty())
        {
            List<android.content.Intent> targetedIntents = new ArrayList<android.content.Intent>();

            for (ResolveInfo resolveInfo : appList)
            {
                String packageName = resolveInfo.activityInfo != null ? resolveInfo.activityInfo.packageName : null;

                Intent allowedIntent = new Intent(dataIntent);
                allowedIntent.setComponent(new ComponentName(packageName, resolveInfo.activityInfo.name));
                allowedIntent.setPackage(packageName);

                targetedIntents.add(allowedIntent);
            }

            if (!targetedIntents.isEmpty())
            {
                //Share Intent
                Intent startIntent = targetedIntents.remove(0);

                Intent chooserIntent = android.content.Intent.createChooser(startIntent, "");
                chooserIntent.putExtra(android.content.Intent.EXTRA_INITIAL_INTENTS, targetedIntents.toArray(new Parcelable[]{}));
                chooserIntent.addFlags(android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION);

                finalIntent = chooserIntent;
            }

        }

        if (finalIntent == null) //As a fallback, we are using the sent data intent
        {
            finalIntent = dataIntent;
        }

        return finalIntent;
}