Rasmus Rajje Josefsson Rasmus Rajje Josefsson - 2 years ago 128
Android Question

Attach a pdf to email, grant permission

If I grant

permission all works good, but can I get it to work without asking? It worked without It on my emulator, but on a real device it doesn't work without it.

Output stream

String fileName = "Körjorunal_" + lastUpdateTime + ".PDF";
String path = Environment.getExternalStorageDirectory().toString();

File file = new File(path, fileName)
pdfUri = Uri.fromFile(file);

OutputStream outputStream = new FileOutputStream(file);


// Gets invoked on setup,
mShareIntent = new Intent();

// Creates document type.

// Going via email:
mShareIntent.putExtra(Intent.EXTRA_SUBJECT, "Körjournal i bifogad PDF");

// Attach the PDf Uri.
mShareIntent.putExtra(Intent.EXTRA_STREAM, pdfUri);



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

Answer Source

FLAG_GRANT_*_URI_PERMISSION (for READ and WRITE) really are for where the Uri is from your own ContentProvider. If you want to avoid the need for the WRITE_EXTERNAL_STORAGE (and superfluous READ_EXTERNAL_STORAGE) permission:

Step #1: Write the file to internal storage, such as getCacheDir()

Step #2: Serve that file from internal storage using FileProvider

Step #3: Use your existing ACTION_SEND logic, substituting the Uri that you get from FileProvider

You will see that pattern used in this sample project. My sample is for ACTION_VIEW, not ACTION_SEND, but otherwise it is a close match.

One key difference, though, will be in how you grant the permissions, if your minSdkVersion is below 21. Uri values in extras were ignored by FLAG_GRANT_*_URI_PERMISSION on Android 4.4 and below. For those versions, the only solution that I know of is to manually grant rights to every possible app (in your case, every PDF viewer).

In this sample app, I use ACTION_IMAGE_CAPTURE to take a picture, and I use a FileProvider Uri for that (since file Uri values are going away). Just as you are using EXTRA_STREAM with a Uri, I am using EXTRA_OUTPUT, and so I run into the same Uri-in-an-extra permission problem. And, so, I go through all this mess:

  i.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);

  else {
    List<ResolveInfo> resInfoList=
        .queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY);

    for (ResolveInfo resolveInfo : resInfoList) {
      String packageName = resolveInfo.activityInfo.packageName;
      grantUriPermission(packageName, outputUri,

  startActivityForResult(i, CONTENT_REQUEST);

(here, i is my ACTION_IMAGE_CAPTURE Intent)

So, I grant any ACTION_IMAGE_CAPTUREIntentthe rights to work with thisUri` on Android 4.4 and older.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download