安卓系统出现异常:'open failed: EACCES (Permission denied)'

414

我遇到了以下问题:

打开失败:EACCES(Permission denied)

出错在这一行:OutputStream myOutput = new FileOutputStream(outFileName);

我已经检查了root权限,并尝试添加了 android.permission.WRITE_EXTERNAL_STORAGE 权限,但仍然无法解决问题。

请问该如何修复这个问题?

try {
    InputStream myInput;

    myInput = getAssets().open("XXX.db");

    // Path to the just created empty db
    String outFileName = "/data/data/XX/databases/"
            + "XXX.db";

    // Open the empty db as the output stream
    OutputStream myOutput = new FileOutputStream(outFileName);

    // Transfer bytes from the inputfile to the outputfile
    byte[] buffer = new byte[1024];
    int length;
    while ((length = myInput.read(buffer)) > 0) {
        myOutput.write(buffer, 0, length);
    }

    // Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();
    buffer = null;
    outFileName = null;
}
catch (IOException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

我在一台Android平板电脑上遇到了同样的问题,但我的情况可能是独特的,所以我在评论中报告了我的解决方案。当应用程序尝试访问包含50多个XML文件的目录/data/data/myapp/foo时,出现了错误。由于一个漏洞,该应用程序没有清理文件夹。删除一些旧文件后,错误消失了。我不知道为什么。这可能是通用Android设备的问题。 - Hong
这个帖子解决了我的问题:https://dev59.com/B1wX5IYBdhLWcg3wjwJZ - partho
36个回答

14

事实证明,这是一个愚蠢的错误,因为我仍然将手机连接到桌面电脑上,而没有意识到这一点。

所以我必须关闭USB连接,然后一切正常了。


也对我有用。但为什么它有效呢?不连接USB与PC有何不同? - user13107
好问题。我从未进一步调查过这个问题。我猜想,当你连接设备时,系统会有一个写锁(因此它可以在计算机上模拟USB设备)。也许这是为了避免不一致的数据。但我不确定。 - Tobias Reich
我在这里找到了原因:https://dev59.com/LGs05IYBdhLWcg3wLO-Q 同时请查看我的回答:https://dev59.com/EGox5IYBdhLWcg3w95E9#43863548 - user13107

13
我在三星Galaxy Note 3上运行CM 12.1时遇到同样的问题。对我来说,问题是我有一个

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="18"/>

我需要使用它来拍照并存储用户照片。当我试图在ImageLoader中加载这些相同的照片时,我收到了(Permission denied)错误消息。解决方法是明确添加

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

由于上述权限仅限制了API版本18及以下的写入权限,并且随之而来的是读取权限。


没帮到我!不过还是值得一试的!谢谢。 - Sakiboy

10
除了所有的答案,如果客户正在使用Android 6.0,则Android为(棉花糖)添加了新的权限模型
提示:如果您的目标版本为22或以下,则您的应用程序会在安装时请求所有权限,就像在运行低于Marshmallow的任何设备上一样。如果您正在尝试模拟器,则从Android 6.0开始,您需要显式地转到“设置”->“应用程序”->“YOURAPP”->“权限”并更改已授予的权限。

2
难以置信,我花了2天时间试图解决这个问题。每当我感觉在Android上一切顺利时,就会出现这样的情况。 - Jaime Ivan Cervantes

9

奇怪的是,在我的newFile之前加上斜杠"/"后,我的问题得到了解决。 我将其更改为:

File myFile= new File(Environment.getExternalStorageDirectory() + "newFile");

转换为:

File myFile= new File(Environment.getExternalStorageDirectory() + "/newFile");

更新:如评论中所提到,正确的做法是:

File myFile= new File(Environment.getExternalStorageDirectory(), "newFile");

2
这里没有什么奇怪的。在第一行中,您正在尝试在包含外部存储目录的同一目录中创建文件。即/storage/.../somethingnewfile而不是/storage/.../something/newfile。 - Stéphane
5
正确的做法是使用 File(dir, file) 构造函数。 - Nick Cardoso
@NickCardoso 你也可以使用File(String pathname)。看起来你没有理解问题的关键点。问题不在于如何使用File类。这个线程中的答案范围显示了这个错误有多么具有误导性,以及有多少种可能的解决方法。在我的情况下,错误是缺少斜杠。有些人发现这很有用。当然,你可以使用自己的访问文件的方法。继续发布你的答案。它可能会解决某个人的问题。 - Darush
@NickCardoso,您本可以建议编辑而不是发表评论,以防止读者被我的错误误导。您仍然感到困惑。如果一个人按照您指出的正确方式操作,他首先就不会来到这个线程。我只是在建议可能导致该错误的原因以及如何解决它。 - Darush
1
我想支持@NickCardoso... 当我使用File(pathname)构造函数时,我遇到了错误... 但是使用File(dir,file)构造函数一切正常... - Brontes
显示剩余5条评论

6
将文件存储在与应用程序目录不相关的“目录”中,在 API 29+ 以上是受到限制的。因此,要生成新文件或创建新文件,请使用您的应用程序目录,例如:
因此,正确的方法是:
val file = File(appContext.applicationInfo.dataDir + File.separator + "anyRandomFileName/")

您可以将任何数据写入此生成的文件!

上述文件是可访问的,不会抛出任何异常,因为它位于您自己开发的应用程序目录中。

另一个选择是在清单应用程序标记中使用android:requestLegacyExternalStorage="true",建议由Uriel提供,但这不是永久解决方案!


谢谢,不过这个答案可能不适用于当用户尝试从文件系统中读取所选文件时发生异常的情况 - 也就是说,该文件已经存在。而且,我已经将建议的参数添加到应用程序清单中了。 - JWL

6

我曾遇到同样的问题,但所有建议都没有帮助。但是我在一个物理设备Galaxy Tab上找到了一个有趣的原因。

当USB存储开启时,外部存储读写权限没有任何效果。只需关闭USB存储,并使用正确的权限,您就可以解决问题。


2
该死,我刚刚花了3个小时的时间在这个问题上。此外,我还不得不重新启动设备,才让它正常工作。非常感谢。 - crgarridos

5

我在尝试将图片写入Galaxy S5(安卓6.0.1)的DCIM/camera文件夹时遇到了同样的错误,后来我发现只有这个文件夹受到限制。我可以写入DCIM/任何其他文件夹,但不能写入camera文件夹。这可能是基于品牌的限制/自定义。


5

我希望所有在/data下的内容都属于“内部存储”。但是你应该能够写入/sdcard


5
我也尝试了<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />,但问题仍然存在。 - Mert
1
/data-partition通常对于普通(非root)用户是写保护的,试图进行普通文件访问。对于内部存储,有专门的方法来实现这一点,特别是如果您想要访问数据库。Android开发者页面应该可以帮助您解决此问题。 - ovenror

5

更改您的/system/etc/permission/platform.xml中的权限属性,同时需要按如下方式提及组。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
    <group android:gid="sdcard_rw" />
    <group android:gid="media_rw" />    
</uses-permission>

platform.xml被严格锁定,尝试通过adb shell进行操作,但需要使用ADB允许的任何脚本来进行修改。 - John
失败了。我的设备进入了启动循环。 - Tobse

4
也许答案就在这里:
在API版本号大于等于23的设备上,如果您安装了一个应用程序(该应用程序不是系统应用程序),则应该在“设置-应用程序”中检查存储权限,每个应用程序都有权限列表,您应该启用它!试试看。

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