Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/181.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
无法使用文件提供程序从内部存储器打开PDF以在Android 8和9上查看_Android_Pdf_Android 9.0 Pie_Android 8.1 Oreo - Fatal编程技术网

无法使用文件提供程序从内部存储器打开PDF以在Android 8和9上查看

无法使用文件提供程序从内部存储器打开PDF以在Android 8和9上查看,android,pdf,android-9.0-pie,android-8.1-oreo,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_V

仅适用于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);
File File=新文件(url);
setReadable文件(真、假);
意向意向=新意向(意向.行动\视图);
Uri pdfUri=FileProvider.getUriForFile(getApplicationContext(),BuildConfig.APPLICATION_ID+“.provider”,文件);
intent.setDataAndType(pdfUri,“应用程序/pdf”);
intent.addFlags(intent.FLAG\授予\读取\ URI\权限);
addFlags(intent.FLAG\u GRANT\u WRITE\u URI\u权限);
List resinfo List=getApplicationContext().getPackageManager().querytentActivities(intent,PackageManager.MATCH_DEFAULT_仅限);
对于(ResolveInfo ResolveInfo:ResInfo列表){
字符串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,“打开文件”);
星触觉(in);

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

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

我有这个问题。使用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);

您正试图和另一个应用程序共享来自内部存储的文件。您需要创建一个文件提供程序才能使其工作。您需要指定一个目录,以便文件提供程序为其生成URI

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

文件提供程序只能为您事先指定的目录中的文件生成内容URI。要指定目录,请使用元素的子元素以XML形式指定其存储区域和路径。例如,下面的paths元素告诉FileProvider您打算为私有文件区域的图像/子目录请求内容URI

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

这是
FileProvider


在本文中,我们首先将文件保存到内部存储器,然后使用外部应用程序从中读取

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

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>

但我使用文件提供商共享一个内部文件,供第三方应用程序访问。我想,文件提供者就是为了这个目的而使用的。如果您能给出一个有效的解决方案,那就太好了。@Gissipi_453您正在创建一个
意图
,该意图应该由另一个应用程序在安装该应用程序时实现。。。请参阅文档:。。。这就是为什么需要摆弄uri权限——否则就不需要了。您还可以在
Manifest.xml
中设置它:…匹配其中的所有PDF。。。。当您已经授予访问权限时,最好使用外部存储—因为这样它将是一个SD卡(当有SD卡时)。对于一些文件,您的方法很好,对于几百或数千个文件,这可能会有问题。它不能很好地扩展-因为清除数据(只需尝试使用设置>应用程序)将完全删除它们,而外部存储则不是这样。您是否提供了读写权限?是的,我提供了。我的清单上有这些——它们需要用户的运行时确认,你们做到了吗?是的。我也给了他们一些任务。还是不行。谢谢你的回答。正如你在我的问题中看到的,我已经在使用一个文件提供商了。正如我后来发现的,问题在于我如何使用我的文件路径。当您使用file file=new file(path)创建新文件时,不要在路径前面添加file://文件。@Gissipi_453它期望协议方案
内容://
,这可以省略(很可能是因为只有一个协议方案可供“选择”——因此知道使用哪一个,除非另有说明)。
    <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>
 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"));
        }