3

I'm testing out creating a .txt file, and then sending it as an email attachment, via an intent.

Creating the .txt File

    try {
        String fileName = "testFileName.txt";
        File root = new File(Environment.getExternalStorageDirectory(), "testDir");
        if (!root.exists()) {
            root.mkdirs();
        }
        File gpxfile = new File(root, fileName);
        FileWriter writer = new FileWriter(gpxfile);
        writer.append("Testing email txt attachment.");
        writer.flush();
        writer.close();
        sendEmail(gpxfile.getAbsolutePath());
    } catch (IOException e) {
        e.printStackTrace();
    }

Sending the email

protected void sendEmail(String fileName){
    Intent i = new Intent(Intent.ACTION_SEND);
    i.setType("message/rfc822");
    i.putExtra(Intent.EXTRA_SUBJECT, "Test subject");
    i.putExtra(Intent.EXTRA_TEXT, "This is the body of the email");
    i.putExtra(Intent.EXTRA_STREAM, Uri.parse(fileName));
    try {
        startActivity(Intent.createChooser(i, "Send mail..."));
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
    }
}

And this all seems to work fine. It opens up the email client, with the subject, body and attachment all visible

Composing email

And sends just fine, indicating there is an attachment

Sent email

But when I open gmail, there is no attachment shown

Gmail, no attachment

Same story when I view the email

Gmail, detailed, no attachment

And viewing the email on the phone, from within the "Sent" folder, also shows no attachment

Android, sent, no attachment

The code is a copy and paste from multiple different posts on SO, and seemingly they are not having any issues. Where is the file going? Is it being stopped by gmail? Or not sending at all? Does the file not exist?

Note: I do have <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> set in the manifest.

Thanks in advance.

Birrel
  • 4,754
  • 6
  • 38
  • 74
  • Instead of creating a `FileWriter` on the `File`, create a `FileWriter` from a `FileOutputStream` on the `File`. Then, between your calls to `flush()` and `close()` on the `FileWriter`, call `getFD().sync()` on the `FileOutputStream`. That is a blocking call and will not return until all bytes are written to disk. See if that helps. Also note that `ACTION_SEND` supports either `EXTRA_TEXT` or `EXTRA_STREAM` for an `Intent`, not both simultaneously, so do not be surprised if some apps ignore one or the other. – CommonsWare Jul 31 '15 at 19:28
  • @CommonsWare thanks for the input. I posted a solution that worked for me - it was just an issue with the path. And thanks for the tip on ACTION_SEND. The [Android Docs](https://developer.android.com/training/basics/intents/sending.html) includes both, so how can I ensure that both are included? – Birrel Jul 31 '15 at 19:33
  • "The Android Docs includes both" -- sigh. I will work to get that fixed. Quoting [the real docs](http://developer.android.com/reference/android/content/Intent.html#ACTION_SEND): "getType() is the MIME type of the data being sent. get*Extra can have either a EXTRA_TEXT or EXTRA_STREAM field, containing the data to be sent. If using EXTRA_TEXT, the MIME type should be "text/plain"; otherwise it should be the MIME type of the data in EXTRA_STREAM." – CommonsWare Jul 31 '15 at 19:40
  • "how can I ensure that both are included?" -- ummm... hold people hostage until all developers accede to your demands? Otherwise, you can't, as it is up to the recipient how to handle the request. – CommonsWare Jul 31 '15 at 19:40

1 Answers1

3

The problem was with the file path. Made the following changes:

sendEmail(gpxfile); // This is the file itself, not the file path

Then actually sending the email:

protected void sendEmail(File file){
    Uri path = Uri.fromFile(file); // This guy gets the job done!

    Intent i = new Intent(Intent.ACTION_SEND);
    i.setType("message/rfc822");
    i.putExtra(Intent.EXTRA_SUBJECT, "Test subject");
    i.putExtra(Intent.EXTRA_TEXT, "This is the body of the email");
    i.putExtra(Intent.EXTRA_STREAM, path); // Include the path
    try {
        startActivity(Intent.createChooser(i, "Send mail..."));
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
    }
}
Birrel
  • 4,754
  • 6
  • 38
  • 74