7

一开始你会想“等等,这个问题是重复的!”。继续阅读。

我正在尝试使用 Intent ACTION_SENDTO(使用电子邮件 URI 作为数据)来让电子邮件应用程序响应。

(使用ACTION_SEND没有数据 URI 的标准“发送”选择器意味着非电子邮件应用程序(例如 Google Drive)也会响应)。

我的问题是附件适用ACTION_SEND于所有设备,但是 - 当ACTION_SENDTO仅使用某些设备正确附加文件时。Nexus 7 工作,但三星 Galaxy Tab 和 Acer Iconia工作。

您可以在下面并排看到不同的方法:

    String email    = getActivity().getResources().getString(R.string.supportEmail);
    String subject  = getActivity().getResources().getString(R.string.sFeedback);
    subject         = String.format(subject, 
                      getActivity().getResources().getString(R.string.productName));
    String content  = getActivity().getResources().getString(R.string.whatFeedbackWouldYouLikeToProvide) + "\n\n" + 
                      mMessage.getText().toString();
    File toSend     = new File(outfile);

    if(toSend.exists()) {
        Log.e("Feedback", "File path: " + toSend.getAbsolutePath());

        Intent emailIntent = new Intent(android.content.Intent.ACTION_SENDTO);
        emailIntent.setData(Uri.parse("mailto:" +email));
        emailIntent.putExtra(android.content.Intent.EXTRA_STREAM,   Uri.fromFile(toSend));
        emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,  subject);               
        emailIntent.putExtra(android.content.Intent.EXTRA_TEXT,     content);  

    /*  Intent emailIntent = new Intent(Intent.ACTION_SEND);
        emailIntent.setType("message/rfc822");
        emailIntent.putExtra(Intent.EXTRA_EMAIL  , new String[]{email});
        emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
        emailIntent.putExtra(Intent.EXTRA_TEXT   , content);
        emailIntent.putExtra(Intent.EXTRA_STREAM , Uri.fromFile(toSend)); */

        try {
            startActivity(emailIntent);
        } catch (ActivityNotFoundException anfe) {
            Toast.makeText(getActivity(), getResources().getString(R.string.pleaseInstallAnEmailClientInOrderToSendUsFeedback), 8000).show();
        }
    }

您可以看到文件路径似乎不是问题,我在一些记录中添加了报告:

三星提供:

04-11 11:40:09.953: E/Feedback(6286): File path: /storage/sdcard0/logs.zip

Nexus 提供:

04-11 11:38:59.249: E/Feedback(12702): File path: /storage/emulated/0/logs.zip

(两者都基于getExternalStorageDirectory()确保跨应用访问)。

有谁知道为什么有区别?

4

6 回答 6

16

我想出的唯一解决方案是以下一个。这是我在寻找完整答案时发现的其他一些内容的混合体。以下将仅显示电子邮件应用程序并允许包含附件。最重要的部分在这里找到:https ://stackoverflow.com/a/8550043/4927659

ArrayList<Uri> uris = new ArrayList<>();
uris.add(Uri.parse("file://" + filepath)); 
//filepath is something like that: /mnt/sdcard/DCIM/DSC0001.JPG
Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(
                "mailto", "example@gmail.com", null));
        emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Mail subject");
        List<ResolveInfo> resolveInfos = getPackageManager().queryIntentActivities(emailIntent, 0);
        List<LabeledIntent> intents = new ArrayList<>();
        for (ResolveInfo info : resolveInfos) {
            Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
            intent.setComponent(new ComponentName(info.activityInfo.packageName, info.activityInfo.name));
            intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"example@gmail.com"});
            intent.putExtra(Intent.EXTRA_SUBJECT, "Mail subject");
            intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); //ArrayList<Uri> of attachment Uri's
            intents.add(new LabeledIntent(intent, info.activityInfo.packageName, info.loadLabel(getPackageManager()), info.icon));
        }
        Intent chooser = Intent.createChooser(intents.remove(intents.size() - 1), "Send email with attachments...");
        chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents.toArray(new LabeledIntent[intents.size()]));
        startActivity(chooser);
于 2015-12-21T05:46:57.090 回答
5

尝试通过 ACTION_SENDTO 解决活动,但实际上是通过 ACTION_SEND 发送。

Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(
                    "mailto", "", null));
            intent.putExtra(Intent.EXTRA_SUBJECT, title);
            intent.putExtra(Intent.EXTRA_TEXT, text);
            intent.putExtra(Intent.EXTRA_STREAM, getSnapshotUri(snapshot, context, event));

            List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentActivities(intent, 0);
            if (resolveInfos.size() == 0) {
                new AlertDialog.Builder(context)
                        .setMessage(R.string.no_mail_app)
                        .setPositiveButton(R.string.ok, null)
                        .show();
            } else {
                String packageName = resolveInfos.get(0).activityInfo.packageName;
                String name = resolveInfos.get(0).activityInfo.name;

                intent.setAction(Intent.ACTION_SEND);
                intent.setComponent(new ComponentName(packageName, name));

                context.startActivity(intent);
            }
于 2015-09-16T09:05:01.400 回答
2

我遇到了类似的问题,整天摸不着头脑,直到在中文博客上找到了可能的答案:http: //flysnow.iteye.com/blog/1128354

在文章的最后,它谈到了 Android 内置电子邮件客户端的意图过滤器:

<activity
    android:name=".activity.MessageCompose"
    android:label="@string/app_name"
    android:enabled="false">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <action android:name="android.intent.action.SENDTO" />
        <data android:scheme="mailto" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
    </intent-filter>
    <intent-filter android:label="@string/app_name">
        <action android:name="android.intent.action.SEND" />
        <data android:mimeType="text/plain" />
        <data android:mimeType="image/*" />
        <data android:mimeType="video/*" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

你可以看到它有两个意图过滤器来不同地处理 SEND 和 SENDTO 意图,并且只有 SEND 是用 mimeType 指定的。代码片段可以追溯到 Android 1.6,但没有太大变化。您可以在最新版本中找到它:

https://android.googlesource.com/platform/packages/apps/Email/+/f44b729bff619d0a9f0b1492726351e41c1e5d5d/AndroidManifest.xml

我不确定他们为什么不在 SENDTO 意图中指定 mimeType,但事实就是这样,我认为大多数电子邮件客户端可能都是这样做的(Gmail 除外,它可以在使用 SENDTO 意图时成功附加文件)。你的情况可能也是这样吗?因此,为了安全起见,您应该只使用 SEND 意图发送附件。

于 2014-12-02T09:33:30.233 回答
0

您可以尝试将主体和主体放在 Uri 中。 这个问题似乎暗示这可能会解决问题。

于 2013-04-11T11:16:03.327 回答
0

Intent.ACTION_SEND即使指定了收件人(这是不正确的,但是..),事情也会由不同的电子邮件客户端正确处理。因此,如果要支持 Gmail 以外的其他客户端,则必须使用此操作。这就是它的工作原理。

要添加接收者,只需添加与使用时添加的完全相同的行Intent.ACTION_SENDTO

Intent emailIntent = new Intent(Intent.ACTION_SEND);
String mailto = "abc@def.com";
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{mailTo});
...

在我的情况下,文件附件没有添加到 Gmail 以外的客户端中,Intent.ACTION_SENDTO并切换到Intent.ACTION_SEND解决它。

于 2016-03-21T14:08:01.167 回答
0

经过大量尝试和组合,这是我用来仅在电子邮件应用程序中发送多个附件的版本:

public static void sendMailWithAttachedFiles(Context activityContext, ArrayList<String> filePaths, String MAIL, String SUBJECT, String TEXT) {
    ArrayList<Uri> uris = new ArrayList<>();
    for (String filePath : filePaths) {
        File file = new File(filePath);

        Uri csvUri = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            csvUri = FileProvider.getUriForFile(activityContext, activityContext.getPackageName() + ".provider", file);
        } else {
            //doesn't work in API 24+
            csvUri  =   Uri.fromFile(file);
        }

        uris.add(csvUri);
    }

    Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto", MAIL, null));
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, SUBJECT);
    emailIntent.putExtra(Intent.EXTRA_TEXT, TEXT);


    List<ResolveInfo> resolveInfos = activityContext.getPackageManager().queryIntentActivities(emailIntent, 0);
    List<LabeledIntent> intents = new ArrayList<>();
    for (ResolveInfo info : resolveInfos) {
        Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
        intent.setComponent(new ComponentName(info.activityInfo.packageName, info.activityInfo.name));
        intent.putExtra(Intent.EXTRA_EMAIL, new String[]{MAIL});
        intent.putExtra(Intent.EXTRA_SUBJECT, SUBJECT);
        intent.putExtra(Intent.EXTRA_TEXT, TEXT);
        intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
        intents.add(new LabeledIntent(intent, info.activityInfo.packageName, info.loadLabel(activityContext.getPackageManager()), info.icon));
    }
    Intent chooser = Intent.createChooser(intents.remove(intents.size() - 1), "Send email using");
    chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents.toArray(new LabeledIntent[intents.size()]));
    activityContext.startActivity(chooser);
}

在清单中:

    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths" />
    </provider>

在 res 文件夹中创建 xml 文件夹并添加此文件 provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="external_files" path="."/>
</paths>
于 2021-03-08T13:02:38.273 回答