打开失败:EACCES(权限被拒绝)

新手上路,请多包涵

我在某些设备上访问存储时遇到了一个非常奇怪的问题。该应用程序适用于我的测试设备(Nexus 4 和 7、三星 GS5)。我所有运行 Android 4.4.2 的设备。但是我收到了很多用户的电子邮件,说该应用程序无法写入存储(内部存储和 sd 卡都没有)。从用户反馈收到的日志文件中,我可以看到问题是以下代码:

 try {
    if (fStream == null) {
    fStream = new FileOutputStream(filename, true);
}
    fStream.write(data, 0, bytes);
    return;
} catch (IOException ex) {
    ex.printStackTrace();
}

它在 fStream = new FileOutputStream(filename, true); 行抛出异常创建 FileOutputStream 时。

堆栈日志是:

 W/System.err( 8147): Caused by: java.io.FileNotFoundException: /storage/emulated/0/my_folder/test_file_name.png: open failed: EACCES (Permission denied)
w/System.err( 8147):    at libcore.io.IoBridge.open(IoBridge.java:409)
W/System.err( 8147):    at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
W/System.err( 8147):    at java.io.FileOutputStream.<init>(FileOutputStream.java:128)
W/System.err( 8147):    at myapp.save(SourceFile:515)
W/System.err( 8147):    ... 8 more
W/System.err( 8147): Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied)
W/System.err( 8147):    at libcore.io.Posix.open(Native Method)
W/System.err( 8147):    at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
W/System.err( 8147):    at libcore.io.IoBridge.open(IoBridge.java:393)
W/System.err( 8147):    ... 11 more

在 AndroidManifest.xml 我声明了以下权限:

  <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19"/>
    <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

我已经确认用户在 SD 卡上使用了正确的应用程序。更奇怪的是它也无法写入内部存储。如果我同时具有读取和写入权限,怎么会发生这种情况?用户说他们当时没有将设备连接到 PC。

更新

事实证明,我过于频繁地调用打开和关闭 FileOutputStream,这会在某些时候引发 FileNotFoundException。听起来更像是线程问题。

原文由 user3613696 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.6k
2 个回答

不久前我遇到了类似的问题。

您的问题可能在两个不同的领域。这要么是您创建要写入的文件的方式,要么是您的写入方法可能存在缺陷,因为它依赖于手机。

如果要将文件写入 SD 卡上的特定位置,请尝试使用环境变量。它们应始终指向有效位置。这是一个写入下载文件夹的示例:

 java.io.File xmlFile = new java.io.File(Environment
    .getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
     + "/Filename.xml");

如果您将文件写入应用程序的内部存储。试试这个例子:

 java.io.File xmlFile = new java.io.File((getActivity()
   .getApplicationContext().getFileStreamPath("FileName.xml")
   .getPath()));

就我个人而言,我依靠外部库来处理流式传输到文件。这个还没有让我失望。

 org.apache.commons.io.FileUtils.copyInputStreamToFile(is, file);

由于写入命令失败,我已经丢失了太多次数据,因此我依靠知名且经过测试的库来完成我的 IO 繁重工作。

如果文件很大,您可能还想考虑在后台运行 IO,或使用回调。

如果您已经在使用环境变量,则可能是权限问题。在下面查看贾斯汀·菲德勒的回答。

原文由 Garret 发布,翻译遵循 CC BY-SA 4.0 许可协议

使用 Android 12 (API 31),我在 OS 文档中读到我们必须使用 Manifest main 属性:

例子:

  uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"

问题已解决。

原文由 FRX63 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题