写入SD卡时出现“java.io.FileNotFoundException: Permission denied”错误。

3

在stackoverflow上有很多类似的问题,但我仍然找不到解决我的特定问题的方法:

我有一个带有WRITE_EXTERNAL_STORAGE权限和非导出文件提供程序的应用程序。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.cgogolin.library"
      ...
      <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
      <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="23" />
      ...
      <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.cgogolin.library.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths"/>
      </provider>
</application>

这进一步在 provider_paths.xml 文件中进行了详细说明:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
  <external-path name="external_files" path="."/>
  <root-path name="external_files2" path="/storage/"/>
</paths>

我希望使用它来将SD卡中的文件提供给其他应用程序使用(在这种情况下,我的应用程序更像是一个文件浏览器,但并非完全如此...)。

由于我正在使用API级别23,因此我还通过调用动态请求权限

requestPermissions(new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE, android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_PERMISSION_REQUEST);

弹出会话窗口,当我点击“允许”后(由于描述在授予权限后必须重新启动应用程序才能写入外部存储的错误),应用程序正确获取权限。我可以通过测试是否来验证

android.support.v4.content.ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED

确实如此。我也可以通过类似以下方式从SD卡获取File文件的Uri

Uri uri = android.support.v4.content.FileProvider.getUriForFile(context, "com.cgogolin.library.fileprovider", file);

我可以从那个文件中读取内容,例如成功地启动一个 Intent.ACTION_VIEW 来在外部应用程序中打开该文件。

但是:尽管拥有写入权限,我无法向该文件写入内容。所有尝试使用以下任一方式打开 uriOutputStreamParcelFileDescriptor 均失败:

context.getContentResolver().openOutputStream(uri, "wa");
context.getContentResolver().openFileDescriptor(uri, "wa");

无论是直接从我的应用程序还是通过Intent打开的应用程序,都会导致一个

java.io.FileNotFoundException: Permission denied

我的错误在哪里?我认为在checkSelfPermission()告诉我我拥有WRITE_EXTERNAL_STORAGE权限后,我应该能够实际执行操作。


你希望我如何创建文件?是在我的应用程序内部还是通过adb? - cgogolin
我可以毫不费力地做到这一点。例如,如果我在默认的“文件”应用程序中选择了一个sdcard上的文件,并使用与我在上面示例中发送Intent.ACTION_VIEW的完全相同的应用程序打开它,则我可以覆盖该文件或将其保存到同一目录中的新文件中。如果我使用Intent.ACTION_OPEN_DOCUMENT从后者应用程序打开sdcard上的文件,也是同样的情况。 - cgogolin
根据您的问题,我想使用sdcard来为其他应用程序提供文件服务(在这种情况下,我的应用程序更像是一个文件浏览器,但并非完全如此...)。如果您正在访问其他应用程序的私有目录,则Android操作系统不允许,因为它遵循Linux文件系统。 - Lovekush Vishwakarma
您不能使用FileProvider从SD卡中提供文件。但我不确定您是否真的使用了来自SD卡的文件。请告诉我们完整的路径,以便我们进行检查。 - greenapps
以上示例中 File file 的样本路径为 /storage/0000-0000/dir/file1.pdf - cgogolin
显示剩余4条评论
2个回答

0
并且我想使用它来从sd卡向其他应用程序提供文件。
首先,FileProvider上没有记录的“root-path”。
其次,除非是非常特定的位置(例如,getExternalFilesDirs()返回的第二个及后续值),否则您无法读取或写入可移动存储。外部存储权限与可移动存储无关。

好的,我肯定有读取权限。我认为写入问题已经通过新的WRITE_EXTERNAL_STORAGE权限得到解决,必须动态请求该权限?肯定有一种方法可以实现这一点。例如,使用SolidExplorer,我可以写入SD卡上的所有目录。 - cgogolin
是的,您始终会拥有读取访问权限。但是现在卡片是只读的。如果您使用存储访问框架而不是文件和FileOutputStream类,您也可以写入所有目录。 - greenapps
不是像SolidExplorer这样的应用程序,它们甚至可以在没有root权限的情况下编写。那么,如果不使用上述方法,这些应用程序如何实现呢? - cgogolin

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接