Android: jak dołączyć tymczasowy, wygenerowany obraz do wiadomości e-mail?

Mam wygenerowany programowo obraz, który chcę wysłać jako załącznik za pomocą metody ACTION_SEND i EXTRA_STREAM.

Ale jak mam to zrobić?

Moja pierwsza próba (zapis do mojej ścieżki pliku context.getCacheDir()) zadziałała w podglądzie Gmaila (nie było podglądu obrazu, ale była widoczna nazwa i ikona załączonego pliku), ale załącznik nigdy nie dotarł po stronie odbiorcy. Domyślam się, że ma to coś wspólnego z uprawnieniami do generowanego pliku, ale jak tego uniknąć? Czy muszę ustawić więcej ustawienia permissive na tych generowanych plikach(tak, że aktywność Gmail może uzyskać dostęp)? Czy jest to w ogóle możliwe dla folderu pamięci podręcznej aplikacji?

Czy jest inna lokalizacja pliku, do której lepiej byłoby zapisać moje pliki? Rozważałem folder pobrań, ale myślę, że byłoby to niewygodne miejsce dla czegoś, co musi istnieć tylko do czasu, aż zostanie wysłane e-mailem.

Próbowałem nawet kodować mój obraz wyłącznie w stylu data:image/png;base64,ABCD... URI. To też pojawiło się w Gmail preview (załącznik ikona, ale bez nazwy pliku), ale nie skutkowała dołączeniem po stronie odbiorcy.

Czy ktoś był w stanie w jakikolwiek sposób dołączyć do wiadomości e-mail jedno zdjęcie wygenerowane? Jakie opcje mogłem przeoczyć?

Author: el2iot2, 2010-08-26

3 answers

Mój problem składał się naprawdę z dwóch części:

  1. {[6] } jest prywatna dla Twojej aplikacji. Nie możesz umieścić czegoś tam i oczekiwać, że inna aplikacja będzie w stanie uzyskać do niego dostęp.
  2. źle zrozumiałem, jakiego typu MIME powinienem używać. Mimo, że wysyłałem e-maila, naprawdę musiałem określić image/png ze względu na mój załącznik.

Dodatkowo badania wykazały, że umieszczanie (potencjalnie dużych) obrazów w pamięci podstawowej nie było dobrym pomysłem, nawet jeśli zamierzaliśmy natychmiast go posprzątać.

Kiedy zrobiłem te rzeczy i zapisałem wygenerowane obrazy do publicznego miejsca na karcie SD, działało to dobrze.

Tak, w skrócie:

Poproś o dostęp do karty SD w manifeście

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Upewnij się, że karta SD jest dostępna

if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) 
{
    //Bail gracefully
}

Utwórz katalog na karcie SD

File pngDir = new File(
    Environment.getExternalStorageDirectory(),   
    //Loose convention inferred from app examples
    "Android/data/com.somedomain.someapp/flotsam");

if (!pngDir.exists())
    pngDir.mkdirs();

Zapisz swój plik do tego katalogu i przechwyć Uri

File pngFile = new File(pngDir, "jetsam.png");
//Save file encoded as PNG
Uri pngUri = Uri.fromFile(pngFile);

Zbuduj ACTION_SEND intent

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

A następnie rozpocznij aktywność

context.startActivity(Intent.createChooser(intent, "Something Pithy"));
I upewnij się, że wszystko posprzątasz...

Zastrzeżenie 1

Wydaje się, że więcej wsparcia nadchodzi dla katalogów kart SD specyficznych dla aplikacji, ale niestety, nie w mojej wymaganej wersji SDK.

Zastrzeżenie 2

To jest przegląd rozwiązania, które ostatecznie zadziałało dla mnie. Niekoniecznie jest to " najlepszy praktyka " podejście.

Zastrzeżenie 3

Oznacza to, że aplikacja musi mieć zamontowaną kartę SD, aby mieć dostępną funkcję załączników obrazu, ale było to całkowicie dopuszczalne w moim przypadku użytkowania. Przebieg może się różnić. Jeśli karta SD nie jest dostępna, dołączam przyjazną notatkę do e-maila wyjaśniającą, dlaczego zdjęcia nie mogą być dołączone i jak naprawić sytuację.

 18
Author: el2iot2,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-27 17:04:20

Właśnie natknąłem się na dokładnie ten sam problem(chcąc załączyć plik tekstowy w moim przypadku). Jeśli zajrzysz do dziennika Androida, powodem tego jest:

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

Jako obejście (jak wspomniano przez HRJ), możesz użyć ContentProvider, aby zapewnić dostęp do plików w wewnętrznej pamięci podręcznej aplikacji, aby Gmail mógł je dołączyć. Właśnie napisałem post na blogu o tym, jak to zrobić.

Mam nadzieję, że to pomoże:)

 4
Author: stephendnicholas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-28 22:22:53
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..."));
 -1
Author: Peter Eskandar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-30 22:12:51