Android:如何将临时生成的图像附加到电子邮件中?

发布于 2024-09-15 16:33:50 字数 549 浏览 4 评论 0原文

我有一个以编程方式生成的图像,我想通过 ACTION_SENDEXTRA_STREAM 方法将其作为附件发送。

但我该怎么做呢?

我的第一次尝试(写入基于 context.getCacheDir() 的文件路径)似乎在 Gmail 预览中有效(无图像预览,但附加的文件名和图标可见),但附件从未到达在接收方。我猜这与生成文件的权限有关,但如何避免这种情况呢?我是否需要对这些生成的文件设置更宽松的设置(以便 Gmail 活动可以访问)?应用程序的缓存文件夹是否有可能?

是否有另一个更适合写入我的文件的文件位置?我考虑过下载文件夹,但认为对于只需要在通过电子邮件发送之前存在的东西来说,这将是一个尴尬的位置。

我什至尝试过纯粹使用 data:image/png;base64,ABCD... 样式的 URI 来编码我的图像。这也出现在 Gmail 预览中(附件图标,但没有文件名),但没有产生收件人端附件。

有没有人能够通过任何方式将一次性生成的图像附加到电子邮件意图中?我可能忽略了哪些选择?

I have a programmatically generated image that I want to send as an attachment via the ACTION_SEND and EXTRA_STREAM method.

But how do i do this?

My first attempt (writing to my context.getCacheDir() based file path) appeared to work in the Gmail preview (no image preview, but attached file name and icon was visible), but the attachment never arrived on the recipient side. I guess this has something to do with permissions on the generated file, but how to avoid this? Do I need to set more permissive settings on these generated files (so that the Gmail activity can access)? Is that even possible for the app's cache folder?

Is there another file location that would be more suitable to write my files to? I considered the downloads folder, but think it would be an awkward location for something that only needs to exist until it has been emailed.

I have even tried encoding my image purely in a data:image/png;base64,ABCD... style URI. This, too, showed up in Gmail preview (attachment icon, but no file name), but did not result in a recipient-side attachment.

Has anyone been able to attach a one-shot generated image to an email intent by any means? What options may I have overlooked?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小苏打饼 2024-09-22 16:33:52

我刚刚遇到了完全相同的问题(想在我的情况下附加一个文本文件)。如果您查看 Android 日志,会发现其原因是:

02-28 21:01:28.434: E/Gmail(19673): file:// attachment paths must point to file:///mnt/sdcard. Ignoring attachment file:///data/data/com.stephendnicholas.gmailattach/cache/Test.txt

作为解决方法(如 HRJ 提到的),您可以使用 ContentProvider 提供对应用程序内部缓存中的文件的访问权限,以便 Gmail 可以附加它们。我刚刚写了一篇关于如何做到这一点的博客文章

希望这对您有所帮助:)

I've just run into exactly the same issue (wanting to attach a text file in my case). If you look in the Android log, the reason for it is:

02-28 21:01:28.434: E/Gmail(19673): file:// attachment paths must point to file:///mnt/sdcard. Ignoring attachment file:///data/data/com.stephendnicholas.gmailattach/cache/Test.txt

As a workaround (as mentioned by HRJ), you can use a ContentProvider to provide access to files in your application's internal cache so that Gmail can attach them. I've just written up a blog post on how to do it.

Hopefully that's of some help :)

你是暖光i 2024-09-22 16:33:52
tableLayout.buildDrawingCache();
        Bitmap test = Bitmap.createBitmap(tableLayout.getDrawingCache());
        tableLayout.destroyDrawingCache();

        Log.d("Image", test.toString());

        String path = Environment.getExternalStorageDirectory().toString(); 
        Log.d("Path", path);
        File file = new File(path,"mail_image.png");
        Uri pngUri = Uri.fromFile(file);
        Log.d("Real Image Path", pngUri.toString());

        Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
        emailIntent.setType("image/png");
        emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, "email to"); 
        emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,"Subject"); 
        emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "From My App"); 
                    emailIntent.putExtra(android.content.Intent.EXTRA_STREAM, pngUri );

        startActivity(Intent.createChooser(emailIntent, "Send mail..."));
tableLayout.buildDrawingCache();
        Bitmap test = Bitmap.createBitmap(tableLayout.getDrawingCache());
        tableLayout.destroyDrawingCache();

        Log.d("Image", test.toString());

        String path = Environment.getExternalStorageDirectory().toString(); 
        Log.d("Path", path);
        File file = new File(path,"mail_image.png");
        Uri pngUri = Uri.fromFile(file);
        Log.d("Real Image Path", pngUri.toString());

        Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
        emailIntent.setType("image/png");
        emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, "email to"); 
        emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,"Subject"); 
        emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "From My App"); 
                    emailIntent.putExtra(android.content.Intent.EXTRA_STREAM, pngUri );

        startActivity(Intent.createChooser(emailIntent, "Send mail..."));
且行且努力 2024-09-22 16:33:51

我的问题实际上由两部分组成:

  1. context.getCacheDir() 对于您的应用程序来说是私有的。您不能将某些内容放在那里并期望其他应用程序能够访问它。
  2. 我误解了我应该使用的 MIME 类型。尽管我正在发送电子邮件文本,但为了附件的缘故,我确实需要指定 image/png

此外,研究表明,将(可能很大的)图像放在主内存上并不是一个好主意,即使您要立即清理它。

当我完成这些操作并将生成的图像写入 SD 卡上的公共位置后,它就工作得很好。

因此,总的来说:

在清单中请求 SD 卡访问

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

确保 SD 卡可用

if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) 
{
    //Bail gracefully
}

在 SD 卡上创建目录

File pngDir = new File(
    Environment.getExternalStorageDirectory(),   
    //Loose convention inferred from app examples
    "Android/data/com.somedomain.someapp/flotsam");

if (!pngDir.exists())
    pngDir.mkdirs();

写入将您的文件复制到该目录并捕获 Uri

File pngFile = new File(pngDir, "jetsam.png");
//Save file encoded as PNG
Uri pngUri = Uri.fromFile(pngFile);

构建 ACTION_SEND 意图

Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setType("image/png"); //
intent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] { "[email protected]" });
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Portable Network Graphics");
intent.putExtra(android.content.Intent.EXTRA_CC, new String[] { "[email protected]" });
intent.putExtra(Intent.EXTRA_TEXT, "Something textual");
intent.putExtra(Intent.EXTRA_STREAM, pngUri);

然后启动活动

context.startActivity(Intent.createChooser(intent, "Something Pithy"));

然后确保清理所有内容up...

警告 1

似乎对应用程序特定的 SD 卡目录有更多支持,但可惜的是,我所需的 SDK 版本中没有。

注意事项 2

这是对最终对我有用的解决方案的概述。这不一定是“最佳实践”方法。

警告 3

这确实意味着应用程序必须安装 SD 卡才能使用图像附件功能,但这对于我的用例来说是完全可以接受的。您的里程可能会有所不同。如果 SD 卡不可用,我会在电子邮件中附上一条友好注释,解释为什么无法附加图像以及如何纠正这种情况。

My problem really consisted of two parts:

  1. context.getCacheDir() is private to your app. You can't put something there and expect another app to be able to access it.
  2. I misunderstood what MIME type I should have been using. Even though I was sending email text, I really needed to specify image/png for the sake of my attachment.

Additionally, research indicated that putting (potentially large) images on the primary memory was not a good idea, even if you were going to immediately clean it up.

Once I did these things and wrote my generated images to a public location on the SD Card, it worked just fine.

So, in overview:

Request SD Card Access in your manifest

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Make sure SD Card is available

if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) 
{
    //Bail gracefully
}

Create a directory on the SD Card

File pngDir = new File(
    Environment.getExternalStorageDirectory(),   
    //Loose convention inferred from app examples
    "Android/data/com.somedomain.someapp/flotsam");

if (!pngDir.exists())
    pngDir.mkdirs();

Write your file to that directory and capture the Uri

File pngFile = new File(pngDir, "jetsam.png");
//Save file encoded as PNG
Uri pngUri = Uri.fromFile(pngFile);

Build an ACTION_SEND intent

Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setType("image/png"); //
intent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] { "[email protected]" });
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Portable Network Graphics");
intent.putExtra(android.content.Intent.EXTRA_CC, new String[] { "[email protected]" });
intent.putExtra(Intent.EXTRA_TEXT, "Something textual");
intent.putExtra(Intent.EXTRA_STREAM, pngUri);

And then start the activity

context.startActivity(Intent.createChooser(intent, "Something Pithy"));

And then make sure you clean everything up...

Caveat 1

There appears to be more support coming for app-specific SD Card directories, but alas, not in my required SDK version.

Caveat 2

This is an overview of the solution that eventually worked for me. It is not necessarily a "best practice" approach.

Caveat 3

This does mean that the application has to have an SD Card mounted in order to have the image attachments feature available, but this was totally acceptable for my use case. Your mileage may vary. If the SD Card is not available, I append a friendly note to the email explaining why the images could not be attached and how to rectify the situation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文