Email Attachments from Android Apps

December 16, 2010 by · 5 Comments 

Here’s a less ranty Android development post than my last hissy-fit about external storage.  From an Android app, it’s pretty easy to invoke the email application to send something by using an Intent.  If you search the Internet, you’ll see that there are a ton of folks having trouble with attachments in this situation.

I just got this to work and thought I’d share the fun.  Unlike my SD Card rant where the proper way to do things is easily found, programmatically adding an attachment to an email is tougher.  The examples out there don’t always work and there are little traps everywhere.

The Basics

Ok, here’s how I did it.  First I implemented the following method in my main activity.

private void emailFiles(String file) {
    Intent sendIntent = new Intent(Intent.ACTION_SEND);
    sendIntent.setType("application/zip");
    sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(file));
    sendIntent.putExtra(Intent.EXTRA_SUBJECT, "AlpineReplay Data File");
    sendIntent.putExtra(Intent.EXTRA_TEXT, "AlpineReplay data file attached.");
    sendIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{email.trim()});
    startActivity(Intent.createChooser(sendIntent, "Select Destination"));
 }

Which I call from a menu selection thusly…

emailFiles(zipFilePath);

Where zipFilePath is the path of a zip file I want to attach (seriously people…keep up) passed as the file argument.  However the format of this is pretty important.  It is passed to the function looking something like this:

file://sdcard/myappname/data/myzipfile.zip

In other words, the absolute path to the file. Here’s the two magic things to look out for.

First, you’ll see a bunch of examples on the internet showing exactly this string as the argument for sendIntent.putExtra() for the content, but this may not work in all cases.  Intent.EXTRA_STREAM should be given a properly formatted URI, which is why it looks like this in the example above.

sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(file));

That puts it in the form of a properly formatted URI (probably changing file:// to file:///…gotta have that third ‘/’ on Linux systems like Android or the files will get lost).

The second nuance I discovered was in this line:

 sendIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{email.trim()});

What the heck is that trim() crap all about? In my case, there was a newline after the email address I got from a EditText control. But you could get other cruft such as trailing whitespace, so trim(), which is a String method, will get rid of it all. I don’t know about all apps that accept file names from an Intent, but gMail can’t deal with those characters and will complain that it’s an invalid email address.

Just one more comment.  The SendIntent will cause a chooser to pop up with a list of applications capable of handling the attachment.  In my case that’s gMail, Bluetooth (file transfer), and DropBox.  If you don’t want those options you may need to whittle it down to just the one you want when you create the chooser.

About dave@kiwiluv.com

Comments

5 Responses to “Email Attachments from Android Apps”
  1. John says:

    After lots of digging around for how to generate and send an attachment in an Android app (i.e. am trying to add an export feature to my app) I came across your post. Thanks for the info – one thing that tripped me up throughout the whole process (and something I never found noted on any blog or help-site) was the piece around the URI generation. I was using the process of openFileOutput(…) and then to get the qualified name of the file back I used getFileStreamPath but that never worked. What I ended up having to do was to build the filename string using:

    filename = “file://” + getFileStreamPath().getAbsolutePath();

    Then use that on the intent as you note in your post:

    emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(filename));

    Maybe everyone else knew this or knows more about how to generate files but it was a thorn in my side for a while before I finally figured this out.

    John

  2. jd says:

    John
    I’m having the same problem you describe.
    I’m looking at what you posted – I don’t understand.
    getFileStreamPath() requires a string inside the ()
    how did you get that to work?
    jd

  3. sa says:

    Why is this code not working? It attaches a filename but no binary to Gmail.

    Intent sharingIntent = new Intent(Intent.ACTION_SEND);
    Uri documentUri = Uri.fromFile(f);
    sharingIntent.setType(“application/pdf”);
    sharingIntent.putExtra(Intent.EXTRA_STREAM, documentUri);
    startActivity(Intent.createChooser(sharingIntent, “Send by”));

    ‘f’ is a valid file.

  4. What device and OS version are you using?

  5. George says:

    It is important that g-mail can only handle file attachments from the external storage (even though it caches the file earlier from any location). This costed us one day to find out.

Speak Your Mind

Tell us what you're thinking...
and oh, if you want a pic to show with your comment, go get a gravatar!