Unable to open PDF from internal storage for viewing on Android 8 and 9 using File Provider

徘徊边缘 提交于 2020-01-06 04:36:30

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!