Android: How do I attach a temporary, generated image to an email?
My problem really consisted of two parts:
context.getCacheDir()
is private to your app. You can't put something there and expect another app to be able to access it.- I misunderstood what MIME type I should have been using. Even though I was sending email text, I really needed to specify
image/png
for the sake of my attachment.
Additionally, research indicated that putting (potentially large) images on the primary memory was not a good idea, even if you were going to immediately clean it up.
Once I did these things and wrote my generated images to a public location on the SD Card, it worked just fine.
So, in overview:
Request SD Card Access in your manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Make sure SD Card is available
if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
{
//Bail gracefully
}
Create a directory on the SD Card
File pngDir = new File(
Environment.getExternalStorageDirectory(),
//Loose convention inferred from app examples
"Android/data/com.somedomain.someapp/flotsam");
if (!pngDir.exists())
pngDir.mkdirs();
Write your file to that directory and capture the Uri
File pngFile = new File(pngDir, "jetsam.png");
//Save file encoded as PNG
Uri pngUri = Uri.fromFile(pngFile);
Build an 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[] { "someone@somewhere.com" });
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Portable Network Graphics");
intent.putExtra(android.content.Intent.EXTRA_CC, new String[] { "carbon@somewhere.com" });
intent.putExtra(Intent.EXTRA_TEXT, "Something textual");
intent.putExtra(Intent.EXTRA_STREAM, pngUri);
And then start the activity
context.startActivity(Intent.createChooser(intent, "Something Pithy"));
And then make sure you clean everything up...
Caveat 1
There appears to be more support coming for app-specific SD Card directories, but alas, not in my required SDK version.
Caveat 2
This is an overview of the solution that eventually worked for me. It is not necessarily a "best practice" approach.
Caveat 3
This does mean that the application has to have an SD Card mounted in order to have the image attachments feature available, but this was totally acceptable for my use case. Your mileage may vary. If the SD Card is not available, I append a friendly note to the email explaining why the images could not be attached and how to rectify the situation.
Attaching file in email
Try this out -
final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND_MULTIPLE);
emailIntent.setType("plain/text");
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,new String[]{"email"});
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "subject");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT,"Test");
//has to be an ArrayList
ArrayList<Uri> uris = new ArrayList<Uri>();
//convert from paths to Android friendly Parcelable Uri's
for (String file : filePaths)
{
File fileIn = new File(file);
Uri u = Uri.fromFile(fileIn);
uris.add(u);
}
emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
context.startActivity(emailIntent);
And, also just refer previous question on Stackoverflow about attach the images in Email through Intent.
Will anyone give example for sending mail with attachment in android
I got Working Code
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
buttonSend = (Button) findViewById(R.id.buttonSend);
textTo = (EditText) findViewById(R.id.editTextTo);
textSubject = (EditText) findViewById(R.id.editTextSubject);
textMessage = (EditText) findViewById(R.id.editTextMessage);
buttonSend.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String to = textTo.getText().toString();
String subject = textSubject.getText().toString();
String message = textMessage.getText().toString();
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("plain/text");
File data = null;
try {
Date dateVal = new Date();
String filename = dateVal.toString();
data = File.createTempFile("Report", ".csv");
FileWriter out = (FileWriter) GenerateCsv.generateCsvFile(
data, "Name,Data1");
i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(data));
i.putExtra(Intent.EXTRA_EMAIL, new String[] { to });
i.putExtra(Intent.EXTRA_SUBJECT, subject);
i.putExtra(Intent.EXTRA_TEXT, message);
startActivity(Intent.createChooser(i, "E-mail"));
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
public class GenerateCsv {
public static FileWriter generateCsvFile(File sFileName,String fileContent) {
FileWriter writer = null;
try {
writer = new FileWriter(sFileName);
writer.append(fileContent);
writer.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally
{
try {
writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return writer;
}
}
Add this line in AndroidManifest.xml file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-p
Android send mail with attachment from string
This code saves you from adding a manifest uses permission to read from external sd card. It creates a temp in files directory on your app private directory then creates the file with the contents of your string and allows read permission so that it can be accessed.
String phoneDesc = "content string to send as attachment";
FileOutputStream fos = null;
try {
fos = openFileOutput("tempFile", Context.MODE_WORLD_READABLE);
fos.write(phoneDesc.getBytes(),0,phoneDesc.getBytes().length);
fos.flush();
fos.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
finally {
if (fos != null)try {fos.close();} catch (IOException ie) {ie.printStackTrace();}
}
File tempFBDataFile = new File(getFilesDir(),"tempFile");
Intent emailClient = new Intent(Intent.ACTION_SENDTO, Uri.parse("someone@somewhere.com"));
emailClient.putExtra(Intent.EXTRA_SUBJECT, "Sample Subject";
emailClient.putExtra(Intent.EXTRA_TEXT, "Sample mail body content");
emailClient.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(tempFBDataFile));//attachment
Intent emailChooser = Intent.createChooser(emailClient, "select email client");
startActivity(emailChooser);
This should be called whenever you dont need the file anymore.
File tempData = new File(getFilesDir(),"tempFile");
if (tempData.exists()) {
tempData.delete();
}
Sending an html file as attachment
As for now, we can use context.getFilesDir() to retrieve a File object to the "files" directory. With that you can also get another File object to your stored HTML page. You can also use the File.exists() and File.isFile() method for checking. Thanks for Christian Lisching
Related Topics
How to Be Notified on Wifi Network Status Change
Onclick Not Triggered on Linearlayout with Child
Fragment Already Added Illegalstateexception
Why Emulator Is Very Slow in Android Studio
Create SQLite Database in Android
How to Use Bluetooth in Android Emulator
Send Auto Email Programmatically
Add Google Maps API V2 in a Fragment
How to Write Jarlist Cache File While Creating Android Project
Android: How to Attach a Temporary, Generated Image to an Email
Get Android Google Analytics Referrer Tag
How to Set Different Applicationid for Each Flavor Combination Using Flavordimensions
Android: Change Default Home Application
Position of Dialogfragment in Android