If I grant READ_EXTERNAL_STORAGE
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);
document.writeTo(outputStream);
document.close();
outputStream.close();
Intent
// Gets invoked on setup,
mShareIntent = new Intent();
mShareIntent.setAction(Intent.ACTION_SEND);
mShareIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
mShareIntent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Creates document type.
mShareIntent.setType("application/pdf");
// Going via email:
mShareIntent.putExtra(Intent.EXTRA_SUBJECT, "Körjournal i bifogad PDF");
// Attach the PDf Uri.
mShareIntent.putExtra(Intent.EXTRA_STREAM, pdfUri);
mShareActionProvider.setShareIntent(mShareIntent);
Manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
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);
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) {
i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
else {
List<ResolveInfo> resInfoList=
getPackageManager()
.queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
grantUriPermission(packageName, outputUri,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION |
Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
startActivityForResult(i, CONTENT_REQUEST);
(here, i
is my ACTION_IMAGE_CAPTURE
Intent
)
So, I grant any ACTION_IMAGE_CAPTURE
Intentthe rights to work with this
Uri` on Android 4.4 and older.