Android: Как подключить временное, сгенерированное изображение к электронному письму?

У меня есть программно сгенерированное изображение, которое я хочу отправить в качестве вложения с помощью методов ACTION_SEND и EXTRA_STREAM.

Но как мне это сделать?

Моя первая попытка (запись на мой путь к файлу context.getCacheDir()), похоже, работала в предварительном просмотре Gmail (без предварительного просмотра изображения, но вложенное имя файла и значок были видны), но приложение никогда не появлялось на стороне получателя. Я предполагаю, что это имеет какое-то отношение к разрешениям на сгенерированный файл, но как этого избежать? Нужно ли устанавливать более разрешительные настройки для этих сгенерированных файлов (чтобы доступ к активности Gmail)? Это возможно даже для папки кэша приложений?

Есть ли другое местоположение файла, которое было бы более подходящим для записи моих файлов? Я рассмотрел папку с загрузкой, но думаю, что это будет неудобное место для чего-то, что должно существовать только до тех пор, пока оно не будет отправлено по электронной почте.

Я даже пробовал кодировать свое изображение только в URI стиля data:image/png;base64,ABCD.... Это тоже появилось в предварительном просмотре Gmail (значок приложения, но не имя файла), но не привел к вложению получателя.

Кто-нибудь мог приложить одноразовое сгенерированное изображение к намерению электронной почты любыми способами? Какие варианты я могу упустить?

Ответы

Ответ 1

Моя проблема действительно состояла из двух частей:

  • context.getCacheDir() является приватным для вашего приложения. Вы не можете что-то там положить и ожидать, что другое приложение сможет получить к нему доступ.
  • Я неправильно понял, какой тип 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"));

И затем убедитесь, что вы все очистите...

Предостережение 1

Кажется, что больше подходит для каталогов SD-карт для приложений, но, увы, не в моей требуемой версии SDK.

Caveat 2

Это обзор решения, которое в конечном итоге сработало для меня. Это не обязательно подход "наилучшей практики".

Caveat 3

Это означает, что приложение должно иметь SD-карту, смонтированную для доступности функции вложений изображений, но это было вполне приемлемо для моего варианта использования. Ваш пробег может отличаться. Если SD-карта недоступна, я добавляю дружеское примечание к письму, объясняющее, почему изображения не могут быть прикреплены и как исправить ситуацию.

Ответ 2

Я просто столкнулся с одной и той же проблемой (желая прикрепить текстовый файл в моем случае). Если вы посмотрите в журнале 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 мог их присоединить. Я только что написал сообщение в блоге о том, как это сделать.

Надеюсь, что с помощью этой помощи:)

Ответ 3

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..."));