无法打开内部存储器中的PDF以使用File Provider在Android 8和9上查看

时间:2019-03-01 16:02:12

标签: android pdf android-9.0-pie android-8.1-oreo

仅适用于Android 8和9。

我在这里有一个PDF文件管理器-

String url = "file:///storage/emulated/0/Android/data/com.verna.poc/files/Download/mypdf.pdf";

我正在尝试使用此文件打开该文件以供查看-

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);

文件选择器选项正在打开,当我使用Google PDF阅读器打开文件时,PDF阅读器会立即打开和关闭。我的代码有什么问题?

4 个答案:

答案 0 :(得分:1)

从拥有该私有目录的应用程序内访问文件-Intent不会将其剪切,因为该文件可能是任何应用程序发送的。如果必须是文件选择器Intent,则在SD卡上为您的应用创建一个共享目录,任何应用都可以在其中访问该目录;常规Downloads目录也适用于此。 另一个选择(如最初建议的那样)是创建一个简单的文件选择器,该文件选择器位于应用程序内,因此不需要Intent来选择文件...这都有一定的进步和缺点。 ;选择一种最适合您的可能性...通常,它是私有存储位置还是共享存储位置。

答案 1 :(得分:1)

您正试图与另一个应用共享内部存储中的文件。您将需要创建一个文件提供程序才能正常工作。您需要指定一个目录,您希望文件提供程序为该目录生成

  

FileProvider是ContentProvider的特殊子类,它通过为文件而非文件:/// Uri创建content:// Uri来促进与应用程序关联的文件的安全共享。

     

FileProvider只能为您预先指定的目录中的文件生成内容URI。要指定目录,请使用元素的子元素以XML格式指定其存储区域和路径。例如,以下path元素告诉FileProvider,您打算为私有文件区域的images /子目录请求内容URI。

这个答案有一个很好的例子

link

这是FileProvider的文档页面

FileProvider

答案 2 :(得分:0)

我知道了。在使用File file = new File(path)制作新文件时,请勿在路径前添加file://

这是正确的-

String url = "/storage/emulated/0/Android/data/com.verna.poc/files/Download/mypdf.pdf";
File file= new File(url);

这是错误的-

String url = "file:///storage/emulated/0/Android/data/com.verna.poc/files/Download/mypdf.pdf";
File file= new File(url);

答案 3 :(得分:0)

在这种情况下,我们首先将文件保存到内部存储,然后使用外部应用程序读取文件。

我使用以下方法将文件保存在内部存储中:

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文件提供者声明了file_path.xml:

  <?xml version="1.0" encoding="utf-8"?>
   <paths>
      <files-path path="/" name="secretpdf" />
   </paths>

PFB文件提供者的Android清单条目:

    <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>

使用以下代码启动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"));
        }