"Permission denied for attachment" (in Gmail 5.0) trying to attach a file to an email intent

This question was published earlier, but there was no clear or accepted answer, and all the decisions that were supposed to β€œwork” were not for me. See Here: The Gmail 5.0 application failed with "Permission denied for attachments" when it receives the intent ACTION_SEND

I have an application that creates data in a text file and should send the text file by email, automatically attaching it. I tried many ways so that this can be attached, and apparently this works for Gmail 4.9 and lower, but 5.0 has some new permission features that disable it from doing what I want.

Intent i = new Intent(Intent.ACTION_SEND); String to = emailRecipient.getText().toString(); i.setType("message/rfc822"); i.putExtra(Intent.EXTRA_EMAIL, new String[] { to }); i.putExtra(Intent.EXTRA_SUBJECT, "Pebble Accelerometer Data"); i.putExtra(Intent.EXTRA_TEXT, "Attached are files containing accelerometer data captured by SmokeBeat Pebble app."); String[] dataPieces = fileManager.getListOfData(getApplicationContext()); for(int i2 = 0; i2 < dataPieces.length; i2++){ i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(getApplicationContext().getFilesDir() + File.separator + dataPieces[i2]))); } i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(getApplicationContext().getFilesDir() + File.separator + fileManager.getCurrentFileName(getApplicationContext())))); Log.e("file loc", getApplicationContext().getFilesDir() + File.separator + fileManager.getCurrentFileName(getApplicationContext())); try { startActivity(Intent.createChooser(i, "Send Email")); } catch (android.content.ActivityNotFoundException ex) { Toast.makeText(Main.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show(); } 

The data may be empty yes, but the current line of the file below the for loop is always reliable and always gives something.

I tried to change

 Uri.fromFile() 

to

 Uri.parse() 

When I do this, it joins, but Gmail then crashes and when I check logcat due to a null pointer. Most likely, this is due to the fact that Gmail does not have access to the file and therefore is null.

I also tried using

 getCacheDir() 

instead

 getFilesDir() 

and has the same result.

What am I doing wrong here, and how do I fix it? Some sample code would be really, really convenient , because I'm new to Android development and explaining what I need to do without any repulsion probably won't help.

Many thanks.

+8
android android-intent permissions gmail
source share
2 answers

Ok guys. I took a break and came back, I realized this.

Here's how it works, you need to have write / read permissions for the external storage, so add these permissions to your manifest:

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

Then your file should be copied from your internal application storage directory to the external application directory. I recommend that you use the internal storage and what I am doing here so that you can find the SD cards yourself.

Here is a block of code that does magic. Logs are enabled, but you can delete them in any way.

 public void writeToExternal(Context context, String filename){ try { File file = new File(context.getExternalFilesDir(null), filename); //Get file location from external source InputStream is = new FileInputStream(context.getFilesDir() + File.separator + filename); //get file location from internal OutputStream os = new FileOutputStream(file); //Open your OutputStream and pass in the file you want to write to byte[] toWrite = new byte[is.available()]; //Init a byte array for handing data transfer Log.i("Available ", is.available() + ""); int result = is.read(toWrite); //Read the data from the byte array Log.i("Result", result + ""); os.write(toWrite); //Write it to the output stream is.close(); //Close it os.close(); //Close it Log.i("Copying to", "" + context.getExternalFilesDir(null) + File.separator + filename); Log.i("Copying from", context.getFilesDir() + File.separator + filename + ""); } catch (Exception e) { Toast.makeText(context, "File write failed: " + e.getLocalizedMessage(), Toast.LENGTH_LONG).show(); //if there an error, make a piece of toast and serve it up } } 
+6
source share

The same attachment was found. The permissions in the manifest had no effect, rather they no longer have an effect, since API 23. Finally, they decided it as follows.

I need to check and grant permissions at runtime, I did this in my main activity:

 public static final int MY_PERMISSIONS_REQUEST_READ_STORAGE=10001; private void checkPermission(){ if (this.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // Should we show an explanation? if (this.shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) { // Show an explanation to the user asynchronously } else { // No explanation needed, we can request the permission. this.requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_READ_STORAGE); } } } 

Now, when sending, create a file in the PUBLIC directory (try saving to the application folder - with the same failure problem)

 public File createFile(){ String htmlStr="<!DOCTYPE html>\n<html>\n<body>\n<p>my html file</p></body></html>"; File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "aimexplorersummary.html"); try { FileWriter writer = new FileWriter(file ,false); writer.write(htmlStr); } writer.flush(); writer.close(); } catch (IOException e) { e.printStackTrace(); return null; } return file; } 

Now make an intention to send and putExtra with uri to your file, which is in the public storage, to which the user must grant permissions, and this does not cause problems now

 public void send(){ Intent intentSend = new Intent(android.content.Intent.ACTION_SEND); intentSend.setType("text/html"); File file = createFile(); if(file!=null){ intentSend.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file)); } startActivity(Intent.createChooser(intentSend, "Send using:")); } 
+1
source share

All Articles