尝试将SD卡中的文件附加到电子邮件

69
我想启动一个发送邮件的Intent。这一切都有效,但是当我尝试发送电子邮件时,会发生一些“奇怪”的事情。
这里是代码。
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.setType("image/jpeg");
sendIntent.putExtra(Intent.EXTRA_SUBJECT, "Photo");
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://sdcard/dcim/Camera/filename.jpg"));
sendIntent.putExtra(Intent.EXTRA_TEXT, "Enjoy the photo");
startActivity(Intent.createChooser(sendIntent, "Email:"));

如果我使用Gmail菜单上下文启动,它会显示附件,让我输入收件人,编辑正文和主题。没什么大不了的。我点击发送,然后就发送了。唯一的问题是附件没有被发送。

所以,我想,为什么不尝试使用“电子邮件”菜单上下文(适用于我手机上的备用电子邮件帐户)。它显示附件,但正文或主题中完全没有任何文本。当我发送它时,附件正确发送了。这导致我认为出了些问题。我是否需要在清单中添加新的权限来启动发送带附件的电子邮件意图?我做错了什么?

13个回答

96

我也遇到了同样的问题

代码:

Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND); 
    emailIntent.setType("image/jpeg");
    emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] 
    {"me@gmail.com"}); 
    emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, 
    "Test Subject"); 
    emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, 
    "go on read the emails"); 
    Log.v(getClass().getSimpleName(), "sPhotoUri=" + Uri.parse("file:/"+ sPhotoFileName));
    emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:/"+ sPhotoFileName));
    startActivity(Intent.createChooser(emailIntent, "Send mail..."));

从adb logcat中:

V/DumbDumpersMain( 3972):   sPhotoUri=file://sdcard/DumbDumpers/DumbDumper.jpg
I/ActivityManager(   56):   Starting activity: Intent { action=android.intent.action.CHOOSER comp={android/com.android.internal.app.ChooserActivity} (has extras) }
I/ActivityManager(   56):   Starting activity: Intent { action=android.intent.action.SEND type=jpeg/image flags=0x3000000 comp={com.google.android.gm/com.google.android.gm.ComposeActivityGmail} (has extras) }
I/ActivityManager(   56):   Starting activity: Intent { action=android.intent.action.SEND type=jpeg/image flags=0x2800000 comp={com.google.android.gm/com.google.android.gm.ComposeActivity} (has extras) }
D/gmail-ls(  120):      MailProvider.query: content://gmail-ls/labels/me@gmail.com(null, null)
D/Gmail   ( 2507):      URI FOUND:file://sdcard/DumbDumpers/DumbDumper.jpg

看起来电子邮件提供商附加了一个长度为0的文件。当我检查文件系统时,文件存在且正确。创建图像文件的代码在尝试发送电子邮件之前已经完成。

有人在没有进行神奇重启的情况下解决了这个问题吗?(我已经尝试过了)

更新

对于我来说路径应该是

file:///sdcard/DumbDumpers/DumbDumper.jpg

你需要额外的/,因为这指向根目录,即:

file://+/sdcard/DumbDumpers/DumbDumper.jpg

组合为

file:///sdcard/DumbDumpers/DumbDumper.jpg

在上面的片段中,你需要:

emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://"+ sPhotoFileName));

6
我会尽力进行翻译:我点了个赞,但如果你将最终解决方案融入代码中,那就更好了。在这里,解决方案比故事更重要。 - Patrick O'Leary
3
我修改了答案以反映需要三条斜线的事实,并且我也点了赞。 - Chrispix
点赞,我不会重新修改这个,因为人们应该知道错误出在哪里。感谢你的解决方案。 - mad
点赞,但在 Facebook 上 EXTRA_TEXT 无法工作,发布后只有图片出现在我的动态上。你有什么办法可以解决这个问题吗? - varun bhardwaj
你不应该使用“硬编码”路径,因为它们可能会根据设备而变化。因此,我建议您在代码中进行轻微更改:File filelocation = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), filename); 然后定义:Uri path = Uri.fromFile(filelocation); 并将其放入您的意图中:emailIntent .putExtra(Intent.EXTRA_STREAM, path); - Carlos Borau

21

我想顺便提一下,我也遇到过GMail的同样问题,但是当我先将文件存储在SD卡上并从那里检索它,而不是从资源中检索时,问题似乎得以解决。因此,我的代码如下:

Intent i = new Intent(Intent.ACTION_SEND);
i.putExtra(Intent.EXTRA_SUBJECT, "Title");
i.putExtra(Intent.EXTRA_TEXT, "Content");
i.putExtra(Intent.EXTRA_STREAM, uri);
i.setType("text/plain");
startActivity(Intent.createChooser(i, "Send mail"));

在这里,

uri = Uri.fromFile(new File(context.getFilesDir(), FILENAME));

不起作用,而

uri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), FILENAME));

好的。

敬礼, 迈克尔


我也发现了同样的问题。不知道是 Gmail(或其他邮件程序)读取文件时权限问题吗?有一件事对我有帮助,就是当我使用内置的“邮件”程序(而不是 Gmail)时,它显示附件为 0 字节。很高兴在不必发送和检查电子邮件的情况下就能知道问题所在。 :-) - Tyler Collier
1
我建议用startActivityForResult()替换startActivity(),并在onActivityResult()中从SD卡的根目录中删除该文件。 - Paul Lammertsma
我认为这不是权限问题。这是一个与Android相关的问题,在2.3和4.2之间得到了修正。在2.3上,如果我将一个文件放在内部存储器上并将其设置为可读,则其他应用程序可以打开它,但仍然无法将其附加到Gmail上。需要在外部存储上。在4.2上,我没有这个问题。 - Tom

7

使用"Uri.fromFile(new File(Environment.getExternalStorageDirectory(),“文件名”))"代替"Uri.parse"

Environment.getExternalStorageDirectory()- SD卡或任何其他外部存储器的路径


4
    Intent i = new Intent(Intent.ACTION_SEND);
    i.setType("message/rfc822");
    i.putExtra(Intent.EXTRA_EMAIL  , new String[]{"example@mail.com"});
    i.putExtra(Intent.EXTRA_SUBJECT, "Data from app");
    i.putExtra(Intent.EXTRA_TEXT   , "experience number x");
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 

    Uri uri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "filename.txt"));
    i.putExtra(Intent.EXTRA_STREAM, uri);
    startActivity(Intent.createChooser(i, "Send email..."));

4

看起来这是正确的,不确定发生了什么,但重新启动后它开始工作了 :/


OP的代码有一个错别字:路径应该是file:///sdcard(注意三个斜杠,而不是两个)。 - Paul Lammertsma

3

来自RFC 1738第3.10节:

文件URL的格式如下:

   file://<host>/<path>

host 是指系统的完全限定域名,可以访问该路径的主机名,而 path 是具有层次结构的目录路径,格式为directory/directory/.../name

因此,它的格式就像http://host/path/from/root一样,是 file:///path/from/root,因为第二个和第三个斜杠之间有一个隐式的“localhost”。但是,如上所述,请使用 Uri.FromFile() 构建它。


关于三个斜杠的部分是我想要的。谢谢。 - Hoang Tran

3
我遇到了同样的问题,到处寻找解决办法。最终,我通过找到一个开源应用程序,并且它可以直接使用,然后参考其代码解决了这个问题。由于代码非常长,因此我不会在此引用它,而是提供一个链接。请查看第449行中的sendEmail函数。

http://rehearsalassist.svn.sourceforge.net/viewvc/rehearsalassist/android/trunk/src/urbanstew/RehearsalAssistant/SessionPlayback.java?revision=94&view=markup

我重新编写了代码,使其更加相似,现在它可以正常工作。我希望这可以帮助其他处于同样情况的人。

0
public void sendMail(String path) {
        Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
        emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
        new String[] {AppConstant.server_mail});
        emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
        "IBPS ERROR Mail");
        emailIntent.putExtra(android.content.Intent.EXTRA_TEXT,
        "This is an autogenerated mail from IBPS app");
        emailIntent.setType("image/png");
        Uri myUri = Uri.parse("file://" + path);
        emailIntent.putExtra(Intent.EXTRA_STREAM, myUri);
        startActivity(Intent.createChooser(emailIntent, "Send mail..."));
        }

0

0

发送带附件的电子邮件:(通过文档)

Intent emailIntent = new Intent(Intent.ACTION_SEND); emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);

emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"});

emailIntent.putExtra(Intent.EXTRA_SUBJECT, "邮件主题"); emailIntent.putExtra(Intent.EXTRA_TEXT, "邮件正文"); emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));

// 您还可以通过传递Uri的ArrayList来附加多个项目


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