12

On the Emulator with a default mail-app all works fine. But I have no attach when I'am receiving a mail which I've sent from my Hero using a Gmail app. The default Mail app on the hero works fine.

How can I make this code works with Gmail app on Hero?
You can see the code below.

    private void startSendIntent() {
        Bitmap bitmap = Bitmap.createBitmap(editableImageView.getWidth(), editableImageView.getHeight(), Bitmap.Config.RGB_565);
        editableImageView.draw(new Canvas(bitmap));
        File png = getFileStreamPath(getString(R.string.file_name));
        FileOutputStream out = null;
        try {
            out = openFileOutput(getString(R.string.file_name), MODE_WORLD_READABLE);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) out.close();
            }
            catch (IOException ignore) {}
        }
        final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
        emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(png));
        emailIntent.setType("image/png");
        startActivity(Intent.createChooser(emailIntent, getString(R.string.send_intent_name)));
}

in Logs I see the following:

02-05 17:03:37.526: DEBUG/Gmail(11511): URI FOUND:file:///sdcard/DCIM/100MEDIA/IMAG0001.jpg
02-05 17:03:37.535: DEBUG/Gmail(11511): ComposeActivity added to message:0 attachment:|IMAG0001.jpg|image/jpeg|0|image/jpeg|LOCAL_FILE|file:///sdcard/DCIM/100MEDIA/IMAG0001.jpg size:0
02-05 17:03:37.585: INFO/Gmail(11511): >>>>> Attachment uri: file:///sdcard/DCIM/100MEDIA/IMAG0001.jpg
02-05 17:03:37.585: INFO/Gmail(11511): >>>>>           type: image/jpeg
02-05 17:03:37.585: INFO/Gmail(11511): >>>>>           name: IMAG0001.jpg
02-05 17:03:37.585: INFO/Gmail(11511): >>>>>           size: 0

Thank you for the answer.

shinydev
  • 759
  • 2
  • 7
  • 20
  • 1
    What build number is on your Hero? I have come across several issues where HTC's sense overlay have broken Android functionality, not recieving an OUT_GOING_CALL intent in some cases is one, this may be another if you have there latest build – Donal Rafferty Feb 05 '10 at 11:08
  • I have build 2.73.411.17 and software version 1.0.0.A6288 – shinydev Feb 05 '10 at 12:25

3 Answers3

32

For me the problem was solved with the following lines of code:

Bitmap screenshot = Bitmap.createBitmap(_rootView.getWidth(), _rootView.getHeight(), Bitmap.Config.RGB_565);
_rootView.draw(new Canvas(screenshot));

String path = Images.Media.insertImage(getContentResolver(), screenshot, "title", null);
Uri screenshotUri = Uri.parse(path);

final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
emailIntent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
emailIntent.setType("image/png");

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

The key thing is that I'm saving the screen-shot to the media library and then it can successfully send a file from there.

i_am_jorf
  • 53,608
  • 15
  • 131
  • 222
Aleks N.
  • 6,051
  • 3
  • 42
  • 42
  • Yes, I solved the problem this way. It seems that there are differents between HTC sense devices permissions and the emulator permissions. – shinydev Aug 20 '10 at 14:22
  • 2
    @Aleks N., this is a nice approach (meaning it works well - I tried it out). But my only question is - is the image then stored somewhere on the phone? Or is this temporary storage? – Phil Sep 02 '11 at 17:28
  • It worked for me too! Thanks a lot. @Phil, the image is stored in the phone in the same folder where your camera's pictures are saved. –  Sep 06 '11 at 19:55
  • 10
    Any way to delete the file afterwards? – Kevin Coulombe Dec 20 '11 at 22:58
  • `File file = new File(uri.getPath()); file.delete();` – Ben Kane Oct 08 '13 at 16:42
  • @KevinCoulombe Did u manage to delete the file after the file shared. – AndroidDev Feb 20 '14 at 06:32
  • @AndroidDev If I remember correctly, I ended up re-using the same filename for every image I sent. It leaves the last sent image when the application is uninstalled, but that was the best I could come up with at the time. If you find any way to delete it, could you post a link here? I might work on this project again at some point and that was one of those tickets that stay in the bug tracker forever... – Kevin Coulombe Feb 21 '14 at 16:23
  • 1
    By the way this requires `android.permission.WRITE_EXTERNAL_STORAGE` – Greg Ennis Jul 26 '14 at 16:18
  • It crashes on 5.0 onwards – Sagar Patil Mar 23 '16 at 10:37
  • @SagarPatil You might wish to provide us with details. – Aleks N. Mar 23 '16 at 13:11
7

getFileStreamPath() or openFileOutput() will create files in a private directory that is inaccessible to other apps (i.e. Gmail). Use external storage to create publicly-accessible files:

private static final int REQUEST_SHARE = 39714;

private File png = null;

private void startSendIntent() {
    png = new File(new File(Environment.getExternalStorageDirectory(), "Pictures"), getString(R.string.file_name));

    FileOutputStream out = null;
    try {
        out = new FileOutputStream(png);
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
        out.flush();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (out != null) out.close();
        }
         catch (IOException ignore) {}
        }
        final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
        emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(png));
        emailIntent.setType("image/png");
        startActivityForResult(Intent.createChooser(emailIntent, getString(R.string.send_intent_name)), REQUEST_SHARE);
    }
}

This will not work when the external storage is unavailable, like when it is mounted as a USB drive. See the Storage API Guide for more about detecting whether external storage is available.

If your minimum API level is 8 or above, you can use Context.getExternalCacheDir() or Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) as the parent directory.

Unless you end up using getExternalCacheDir(), make sure you use a unique filename to prevent one of the users' files from accidentally getting overwritten.

Finally, you can override onActivityResult() to delete the file after the share operation completes:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if(requestCode == REQUEST_SHARE) {
        if(this.png == null) {
            return;
        }

        this.png.delete();
    }
}
robinj
  • 921
  • 5
  • 14
  • Thanks a lot for the tip. This is the simplest way to do the job. In my case Context.getExternalCacheDir() does not work, but Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) works perfectly. – Hong Nov 25 '14 at 15:23
2

I had the same symptoms. In my case it was because I was initially saving the attachment with the permissions MODE_PRIVATE. As soon as I changed it to MODE_WORLD_READABLE it seems Gmail was then able to access the file and send the attachment properly. Although I see in your code snippet you were using MODE_WORLD_READABLE ... weird.

http://developer.android.com/reference/android/content/Context.html#MODE_WORLD_READABLE

joergl
  • 2,850
  • 4
  • 36
  • 42