问题
For Android 8 and 9 only.
I have a PDF filer here -
String url = "file:///storage/emulated/0/Android/data/com.verna.poc/files/Download/mypdf.pdf";
I'm trying to open this file for viewing using this -
File file= new File(url);
file.setReadable(true, false);
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri pdfUri = FileProvider.getUriForFile(getApplicationContext(), BuildConfig.APPLICATION_ID + ".provider", file);
intent.setDataAndType(pdfUri, "application/pdf");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
List<ResolveInfo> resInfoList = getApplicationContext().getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
getApplicationContext().grantUriPermission(packageName, pdfUri,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
Intent in = Intent.createChooser(intent, "Open File");
startActivity(in);
The File chooser option is opening and when I open the file using Google PDF reader, the PDF reader opens and closes immediately. Whats wrong in my code ?
回答1:
access the file from within the app which owns that private directory - an Intent
won't cut it, because this could have been sent by just any application. and if it has to be a file-chooser Intent
, then create a shared directory for your app on the SD card, where any application can access it; the regular Downloads
directory would also be suitable for that.
another option (as initially suggested) would be to create a simple file-chooser, which resides within the application, so that no Intent
would be required to select a file... this all has certain advances and dis-advances; choose the one possibility, which suits you the best... in general, it's private vs. shared storage location.
回答2:
You are trying to share a file from internal storage with the another app. You will need to create a file provider for this to work. You will need to specify a directory which you want the file provider to generate Uris for
FileProvider is a special subclass of ContentProvider that facilitates secure sharing of files associated with an app by creating a content:// Uri for a file instead of a file:/// Uri.
A FileProvider can only generate a content URI for files in directories that you specify beforehand. To specify a directory, specify the its storage area and path in XML, using child elements of the element. For example, the following paths element tells FileProvider that you intend to request content URIs for the images/ subdirectory of your private file area.
This answer has a good example on this
link
Here is the doc page for FileProvider
FileProvider
回答3:
I got the issue. When you are making a new file using, File file = new File(path), don't add file://
infront of the path.
This is correct -
String url = "/storage/emulated/0/Android/data/com.verna.poc/files/Download/mypdf.pdf";
File file= new File(url);
This is wrong -
String url = "file:///storage/emulated/0/Android/data/com.verna.poc/files/Download/mypdf.pdf";
File file= new File(url);
回答4:
In this we first save the file to internal storage and then read from it using external app.
I use below method to save the file in internal storage :
private void savePDFtoInternalStorage(byte[] pdfAsBytes){
//Save in internal memo cache
File directory = mFragmentActivity.getFilesDir();
//updating path for pdf to match with file_path.xml
mCardStmtFile = new File(directory.getAbsolutePath(), "sample.pdf");
OutputStream outputStream = null;
try {
PbLogger.e(TAG, "writing to mStmtFile");
outputStream = new FileOutputStream(mCardStmtFile, false);
outputStream.write(pdfAsBytes);
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
PFB the file provider declared file_path.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path path="/" name="secretpdf" />
</paths>
PFB the Android Manifest Entry for file provider :
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.***.********.provider"
android:exported="false"
android:grantUriPermissions="true">
<!-- ressource file to create -->
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths">
</meta-data>
</provider>
Use below code to launch PDF :
Intent intentShareFile = new Intent(Intent.ACTION_VIEW);
if (mStmtFile.exists()) {
intentShareFile.setType("application/pdf");
Uri fileUri = FileProvider.getUriForFile(
mFragmentActivity,
"com.****.********.provider",
mCardStmtFile);
intentShareFile.putExtra(Intent.EXTRA_STREAM, fileUri);
intentShareFile.putExtra(Intent.EXTRA_SUBJECT,
getDescription());
//adding grant read permission to share internal file
intentShareFile.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(intentShareFile, "Share File"));
}
来源:https://stackoverflow.com/questions/54948250/unable-to-open-pdf-from-internal-storage-for-viewing-on-android-8-and-9-using-fi