Gmail 5.0 App Fails with "Permission Denied for the Attachment" When It Receives Action_Send Intent

Gmail 5.0 app fails with Permission denied for the attachment when it receives ACTION_SEND intent

GMail 5.0 added some security checks to attachments it receives from an Intent. These are unrelated to unix permissions, so the fact that the file is readable doesn't matter.

When the attachment Uri is a file://, it'll only accept files from external storage, the private directory of gmail itself, or world-readable files from the private data directory of the calling app.

The problem with this security check is that it relies on gmail being able to find the caller app, which is only reliable when the caller has asked for result. In your code above, you do not ask for result and therefore gmail does not know who the caller is, and rejects your file.

Since it worked for you in 4.9 but not in 5.0, you know it's not a unix permission problem, so the reason must be the new checks.

TL;DR answer:
replace startActivity with startActivityForResult.

Or better yet, use a content provider.

Permission denied for the attachment (on Gmail 5.0) trying to attach file to email intent

Alright guys. Took a break and came back, figured it out.

Here's how it works, you need to have write/read permissions to 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 has to be copied from your app's internal storage directory into the app's external directory. I recommend you use internal storage, and that's what I'm doing here so you can figure out SD cards yourself.

Here is the block of code that does the magic. Logs are included but you can remove them by all means.

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's an error, make a piece of toast and serve it up
}
}

Gmail 5.0 app fails with Permission denied for the attachment when it receives ACTION_SEND intent

GMail 5.0 added some security checks to attachments it receives from an Intent. These are unrelated to unix permissions, so the fact that the file is readable doesn't matter.

When the attachment Uri is a file://, it'll only accept files from external storage, the private directory of gmail itself, or world-readable files from the private data directory of the calling app.

The problem with this security check is that it relies on gmail being able to find the caller app, which is only reliable when the caller has asked for result. In your code above, you do not ask for result and therefore gmail does not know who the caller is, and rejects your file.

Since it worked for you in 4.9 but not in 5.0, you know it's not a unix permission problem, so the reason must be the new checks.

TL;DR answer:
replace startActivity with startActivityForResult.

Or better yet, use a content provider.



Related Topics



Leave a reply



Submit