使用 Intent.ACTION_SEND_MULTIPLE 發送帶多個附件的郵件,Gmail App 正常,但系統自帶「郵件」客戶端收到郵件無附件(正文、主題正常)。
Intent emailIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"a@b.com"});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "主題");
emailIntent.putExtra(Intent.EXTRA_TEXT, "正文");
emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); // ArrayList
emailIntent.setType("text/plain");
startActivity(Intent.createChooser(emailIntent, "發送郵件"));
ACTION_SEND_MULTIPLE;部分廠商/系統郵件客戶端僅處理 ACTION_SEND,忽略 EXTRA_STREAM 列表。Uri 必須授予目標 App 讀取權限(FLAG_GRANT_READ_URI_PERMISSION),否則客戶端無法讀取文件內容。setType("text/plain") 告訴系統這是純文本,附件類型應用 setType("*/*") 或具體類型(如 image/jpeg),並確保每個 Uri 對應正確 MIME。Intent emailIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"a@b.com"});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "主題");
emailIntent.putExtra(Intent.EXTRA_TEXT, "正文");
// 假設 uris 是 ArrayList,且來自 FileProvider
emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
// 關鍵:授予所有 Uri 讀取權限
emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// 類型設置為通用或具體附件類型
emailIntent.setType("*/*"); // 或 "image/*", "application/pdf" 等
startActivity(Intent.createChooser(emailIntent, "發送郵件"));
若 Uri 為 file:// 協議(Android 7.0+ 禁止跨應用暴露),必須遷移至 FileProvider 生成 content:// Uri。
若目標客戶端確不支持多附件,可:
ACTION_SEND 發送。ACTION_SEND(用戶體驗差,不推薦)。// frameworks/opt/email/src/com/android/email/activity/Welcome.java 片段
if (Intent.ACTION_SEND_MULTIPLE.equals(action) && intent.hasExtra(Intent.EXTRA_STREAM)) {
ArrayList list = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
if (list != null) {
for (Parcelable parcelable : list) {
Uri uri = (Uri) parcelable;
if (uri != null) {
addAttachmentFromSendIntent(uri); // 內部會檢查 MIME、權限
}
}
}
}
private void addAttachmentFromSendIntent(Uri uri) {
Attachment attachment = loadAttachmentInfo(uri); // 解析 MIME、大小
String mimeType = attachment.mMimeType;
// 關鍵過濾:只接受白名單類型
if (!TextUtils.isEmpty(mimeType) && MimeUtility.mimeTypeMatches(mimeType, ACCEPTABLE_ATTACHMENT_SEND_INTENT_TYPES)) {
addAttachment(attachment);
}
}
可見系統郵件客戶端會過濾 MIME 類型,若附件類型不在白名單(ACCEPTABLE_ATTACHMENT_SEND_INTENT_TYPES)中,會被靜默丟棄。
FileProvider 生成 content:// Uri。intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)。setType("*/*") 或遍歷附件設置 intent.setType(mimeType)(單附件時)。多附件郵件發送失效多因 Uri 權限缺失 或 MIME 類型被客戶端過濾。規範使用 FileProvider、授予權限、設置通用 MIME,可解決 90% 兼容性問題。