Android Studio的mailto Intent不能显示主题和邮件正文

29
我正在尝试从我的Android应用程序发送电子邮件。通过点击按钮,Gmail应该打开并显示一个新的电子邮件,其中包含我预先定义的收件人、主题和邮件正文。到目前为止,我已经尝试发送Intent.ACTION_VIEW以及Intent.ACTION_SENDTO。两者都只显示我的草稿与收件人。主题和消息都被压制了。奇怪的是,在使用模拟器时,它可以正常工作。我还尝试查看Android错误日志。似乎我没有权限。这真的是一个权限问题吗?或者可能是其他问题?
以下是我的代码:
  • 通过ACTION_VIEW发送电子邮件
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("mailto:" + to));
intent.putExtra(intent.EXTRA_SUBJECT, subject);
intent.putExtra(intent.EXTRA_TEXT, message);
mainActivity.startActivity(intent);
  • 通过ACTION_SENDTO发送电子邮件
Intent email = new Intent(Intent.ACTION_SENDTO);
email.setType("message/rfc822");
email.putExtra(Intent.EXTRA_EMAIL, new String[]{to});
email.putExtra(Intent.EXTRA_SUBJECT, subject);
email.putExtra(Intent.EXTRA_TEXT, message);
mainActivity.startActivity(Intent.createChooser(email, "Choose an Email client :"));
  • 来自logcat的错误消息
2019-12-13 01:30:35.172 29268-29268/? E//system/bin/webview_zygote32: failed to make and chown /acct/uid_99044: Permission denied
2019-12-13 01:30:35.172 29268-29268/? E/Zygote: createProcessGroup(99044, 0) failed: Permission denied
2019-12-13 01:30:35.206 29289-29289/? E/asset: setgid: Operation not permitted
2019-12-13 01:30:35.226 29296-29296/? E/asset: setgid: Operation not permitted
2019-12-13 01:30:35.355 29268-29268/? E/Typeface: Error mapping font file /system/fonts/NotoSansKhmer-Regular.ttf
2019-12-13 01:30:35.356 29268-29268/? E/Typeface: Error mapping font file /system/fonts/NotoSansKhmer-Bold.ttf
2019-12-13 01:30:35.356 29268-29268/? E/Minikin: Could not get cmap table size!
2019-12-13 01:30:35.356 29268-29268/? E/Typeface: Unable to load Family: null:und-Khmr
2019-12-13 01:30:35.484 29268-29268/? E/Typeface: Error mapping font file /system/fonts/LGAka_Light.ttf
2019-12-13 01:30:35.484 29268-29268/? E/Minikin: Could not get cmap table size!
2019-12-13 01:30:35.484 29268-29268/? E/Typeface: Unable to load Family: lg-lgaka:null
2019-12-13 01:30:35.816 29342-29342/? E//system/bin/webview_zygote32: failed to make and chown /acct/uid_99045: Permission denied
2019-12-13 01:30:35.816 29342-29342/? E/Zygote: createProcessGroup(99045, 0) failed: Permission denied
2019-12-13 01:30:35.842 29354-29354/? E/asset: setgid: Operation not permitted
2019-12-13 01:30:35.864 29367-29367/? E/asset: setgid: Operation not permitted
2019-12-13 01:30:36.139 29342-29342/? E/Typeface: Error mapping font file /system/fonts/NotoSansKhmer-Regular.ttf
2019-12-13 01:30:36.139 29342-29342/? E/Typeface: Error mapping font file /system/fonts/NotoSansKhmer-Bold.ttf
2019-12-13 01:30:36.139 29342-29342/? E/Minikin: Could not get cmap table size!
2019-12-13 01:30:36.139 29342-29342/? E/Typeface: Unable to load Family: null:und-Khmr
2019-12-13 01:30:36.362 29342-29342/? E/Typeface: Error mapping font file /system/fonts/LGAka_Light.ttf
2019-12-13 01:30:36.362 29342-29342/? E/Minikin: Could not get cmap table size!
2019-12-13 01:30:36.362 29342-29342/? E/Typeface: Unable to load Family: lg-lgaka:null
2019-12-13 01:30:36.523 4349-4359/? E/GBMv2: FPS Scaler: EXP
2019-12-13 01:30:36.602 29342-29342/? E/WebViewFactory: can't load with relro file; address space not reserved
2019-12-13 01:30:37.058 29220-29220/? E/Gmail: Gmail:EditWebView JS Console: b/119949571:draft.editor.onLoad; source: file:///android_asset/draft_editor_gmail_compiled.js at 89
2019-12-13 01:30:37.146 29220-29220/? E/Gmail: Gmail:EditWebView JS Console: b/119949571:draft.editor.onLoad is finished; source: file:///android_asset/draft_editor_gmail_compiled.js at 90

ACTION_VIEWACTION_SENDTO都没有文档支持EXTRA_SUBJECTEXTRA_TEXT - CommonsWare
设置类型为("text/plain") - Elias Fazel
10个回答

74

我认为我们遇到了同样的问题。Android API 29引入了一些关于向其他应用程序发送数据的改进。在此处查看更多详细信息:向其他应用程序发送简单数据

这是对我有效的解决方案。

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

final Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"address@mail.com"});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "The subject");
emailIntent.putExtra(Intent.EXTRA_TEXT, "The email body");
emailIntent.setSelector( selectorIntent );

activity.startActivity(Intent.createChooser(emailIntent, "Send email..."));
简而言之,您是要求使用Android标准应用选择器,并且指定要发送电子邮件。 因此,结果只会出现电子邮件客户端。 如果用户仅安装了一个电子邮件客户端,则意图将立即重定向到它。
希望这也能帮助您。

8
最终,我已经有了代码,过去10-11年它一直可以在Gmail上使用,但突然之间停止了工作。按照这种方式操作是正确的选择。 :) - Roy Solberg
也适用于我。Intent.createChooser是可选的,可以直接传递emailIntent。 - melbic
运行得非常好,节省了我几分钟的苦思冥想。非常感谢。 - ibyte
1
它有点能用,但需要用户选择“Gmail”,并提供“复制”和“Paypal”选项,这只会导致奇怪或无效的行为。 - pete
@pete 这是由于“ACTION_SEND”意图的广泛范围,我同意这对用户来说有点令人困惑。我没有尝试过,但我相信您可以在extras中指定MIME数据类型,这应该进一步筛选出显示的应用程序列表。 - Bryan W

17

尝试运行这段代码,它对我有用。

Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:")); // only email apps should handle this
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{email});
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject here");
intent.putExtra(Intent.EXTRA_TEXT,"Body Here");
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
}

还需在Android清单文件中添加意图过滤器。

<activity ...>
<intent-filter>
    <action android:name="android.intent.action.SENDTO" />
    <data android:scheme="mailto" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

请您能否对答案进行一些解释? - Yonlif
非常感谢,我甚至可以选择使用一个电子邮件客户端作为标准。必须将intent-filter标签放在service标签内,并将其命名为MainActivity。因此,它看起来像这样:<service android:name="MainActivity"> - Paul
3
它仍然没有显示主题和正文! - Ahmed Elsayed

15
为了使其在三星和Pixel设备上正常工作,我们不仅需要在URL中添加参数,还需要在额外信息中添加参数。

为了使其在三星和Pixel设备上正常工作,我们不得不在URL和额外信息中都添加参数。

val email = "xxxx@xxxx.com"
val subject = "xxxx"
val body = "xxxx"

val selectorIntent = Intent(Intent.ACTION_SENDTO)
val urlString = "mailto:" + Uri.encode(email) + "?subject=" + Uri.encode(subject) + "&body=" + Uri.encode(body)
selectorIntent.data = Uri.parse(urlString)

val emailIntent = Intent(Intent.ACTION_SEND)
emailIntent.putExtra(Intent.EXTRA_EMAIL, arrayOf(email))
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject)
emailIntent.putExtra(Intent.EXTRA_TEXT, body)
emailIntent.selector = selectorIntent

startActivity(Intent.createChooser(emailIntent, "Send email"))

6

我们旧的电子邮件代码几天前停止工作。

代码如下:

public static void shareTextToEmail(Context context, String[] email, String subject, String text)
    Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:" + TextUtils.join(",", email)));
    emailIntent.putExtra(Intent.EXTRA_EMAIL, email);
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
    emailIntent.putExtra(Intent.EXTRA_TEXT, text);
    try {
        context.startActivity(Intent.createChooser(emailIntent, context.getString(R.string.share_email_title)));
    } catch (android.content.ActivityNotFoundException e) {
        Toast.makeText(context, context.getString(R.string.share_no_intent_handler_found), Toast.LENGTH_SHORT).show();
    }
}

我已经采用了 Zak.Antonio 的答案:

public static void shareTextToEmail(Context context, String[] email, String subject, String text)
    Intent selectorIntent = new Intent(Intent.ACTION_SENDTO);
    selectorIntent.setData(Uri.parse("mailto:"));

    final Intent emailIntent = new Intent(Intent.ACTION_SEND);
    emailIntent.putExtra(Intent.EXTRA_EMAIL, email);
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
    emailIntent.putExtra(Intent.EXTRA_TEXT, text);
    emailIntent.setSelector(selectorIntent);

    try {
        context.startActivity(Intent.createChooser(emailIntent, context.getString(R.string.share_email_title)));
    } catch (android.content.ActivityNotFoundException e) {
        Toast.makeText(context, context.getString(R.string.share_no_intent_handler_found), Toast.LENGTH_SHORT).show();
    }
}

重点如下:
  • emailIntent 中的 Intent.ACTION_SENDTO 替换为 Intent.ACTION_SEND
  • Intent.ACTION_SENDTO 移至 selectorIntent
  • 不要在意图数据中放置电子邮件,只将它们放在Intent.EXTRA_EMAIL 的附加项中

1
我也像你的答案一样解决了这个问题。其他答案不太好。 - Junyoung LEE
这个例子对我仍然不起作用,直到我把电子邮件“to”地址放入一个数组中,就像其他答案一样。(我在Pixel,Android 10上进行测试)。否则,这个例子也很棒。 - gjgjgj
@gjgjgj 在这个例子中,变量 email 是一个 String[] - Artem Mostyaev

4
如果你的应用程序目标为Android 11(API级别30)或更高版本,则我们需要添加以下内容:

在Manifest文件中设置queries如下:

<manifest package="com.example.app">
    ...
    <!-- Package visibility -->
    <queries>
        <!-- Mail -->
        <intent>
            <action android:name="android.intent.action.SENDTO" />
            <data android:scheme="mailto" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent>
    </queries>
    ...
</manifest>

Kotlin打开电子邮件应用程序的方法:

fun composeEmail(recipient: String, subject: String, body: String) {
    val selectorIntent = Intent(Intent.ACTION_SENDTO).apply{
        data = Uri.parse("mailto:") // only email apps should handle this
    }
    val emailIntent = Intent(Intent.ACTION_SEND).apply {
        putExtra(Intent.EXTRA_EMAIL, arrayOf(recipient))
        putExtra(Intent.EXTRA_SUBJECT, subject)
        putExtra(Intent.EXTRA_TEXT, body)
        selector = selectorIntent
    }
    if (emailIntent.resolveActivity(packageManager) != null) {
        startActivity(emailIntent)
    }
}

1
事实上,在AndroidManifest.xml中,像您的示例一样的查询标签是API 30+中唯一缺失的东西。打开电子邮件应用程序的意图甚至不需要更改。我使用已经适用于API 29的相同代码。因此,查询标签是正确的解决方案。 - Rado

4

使用 Uri 解析的方式对我有效

Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:?subject=" + subject + "&to=" + to));
 context.startActivity(emailIntent);

3

在运行Android 10的三星手机上,无论是向SENDTO intent添加Extras还是使用selectorIntent似乎都不起作用。对电子邮件地址、主题和正文进行Uri编码似乎是跨多个运行Android 10及以下设备的最佳选择。 EmailIntentLibrary 在解决复杂正文内容的URI编码细节方面提供了很大的帮助。

val email = Uri.encode("xxxx@xxxx.com")
val subject = Uri.encode("xxxx")
val body = Uri.encode("some body. one two & more. \n new line \n &%>?")
val uri = "mailto:$email?subject=$subject&body=$body"
val intent = Intent(Intent.ACTION_SENDTO)
intent.type = "text/plain"
intent.data = Uri.parse(uri)
startActivity(intent)

如果您可以接受选择器中有很多选项,下面来自Android开发指南的示例是有效的(用于过滤这些选项的ACTION_SENDTO示例对我无效)。请参考以下示例:
fun composeEmail(addresses: Array<String>, subject: String, attachment: Uri) {
    val intent = Intent(Intent.ACTION_SEND).apply {
        type = "*/*"
        putExtra(Intent.EXTRA_EMAIL, addresses)
        putExtra(Intent.EXTRA_SUBJECT, subject)
        putExtra(Intent.EXTRA_STREAM, attachment)
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}

感谢您指出EmailIntentLibrary。 它是唯一一个具有正确实现和清晰解决方案的库。 - Hoang Nguyen Huu

2
请尝试这段代码。
    val emailIntent = Intent(Intent.ACTION_SEND)
    emailIntent.setType("text/plain")
    emailIntent.putExtra(Intent.EXTRA_EMAIL, arrayOf("jon@example.com")) 
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject")
    emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text")
    val packageManager = packageManager
    val activities = packageManager.queryIntentActivities(emailIntent, 0)
    val isIntentSafe = activities.size > 0
    if (isIntentSafe) {
        startActivity(emailIntent);
    }else{
        Log.d("MainActivty","Email App not installed");
    }

这是什么语言?我尝试将其翻译为Java,但我不知道变量packageManager和activities的类型。 - Paul
这是 Kotlin。packageManager 是类型为 android.content.pm.PackageManager 的对象。 - vinodaw

1

我之前尝试了其他的解决方案,但都无法解决我的问题。以下是最终有效的解决方法:

    val selectorIntent = Intent(Intent.ACTION_SENDTO).apply {
        data = Uri.parse("mailto:")
    }

    val emailIntent = Intent(Intent.ACTION_SEND).apply {
        selector = selectorIntent
        putExtra(
            Intent.EXTRA_EMAIL,
            arrayOf(resources.getString(R.string.support_email_address))
        )
        putExtra(
            Intent.EXTRA_SUBJECT,
            resources.getString(R.string.support_email_subject)
        )
        putExtra(
            Intent.EXTRA_TEXT,
            resources.getString(R.string.support_email_body)
        )
        putExtra(
            Intent.EXTRA_STREAM,
            latestLogFileUri
        )
    }

    emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)

    if (selectorIntent.resolveActivity(packageManager) != null) {
        Handler(Looper.getMainLooper()).postDelayed({
            startActivity(
                Intent.createChooser(
                    emailIntent,
                    resources.getString(R.string.support_email_chooser_title)
                )
            )
        }, 2000)
    }

不要忘记将以下内容添加到您的AndroidManifest.xml文件中:

    <queries>
        <intent>
            <action android:name="android.intent.action.SENDTO" />
            <data android:scheme="mailto" />
        </intent>
        <intent>
            <action android:name="android.intent.action.SEND" />
            <data android:mimeType="*/*" />
        </intent>
    </queries>

0
最佳解决方案
val intent = Intent(Intent.ACTION_SENDTO)
        intent.data = Uri.parse("mailto:example@gmail.com?bcc=exampleEmail2@gmail.com&subject=subject text...!&body= extra text ..")
        startActivity(intent)

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