异常“打开失败:EACCES(权限被拒绝)”在安卓上
我正在得到
打开失败:
EACCES(权限被拒绝)
在线 OutputStream myOutput = new FileOutputStream(outFileName);
我检查了根目录,并尝试了 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();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
我在运行 CM 12.1 的 Samsung Galaxy Note 3 上遇到了同样的问题。对我来说,问题是我
必须使用它来拍摄和存储用户照片。当我尝试在 ImageLoader 中加载这些相同的照片时,出现
(权限被拒绝)
错误。解决方案是显式添加,因为上述权限仅限制 API 版本 18 之前的写入权限以及读取权限。
I had the same problem on Samsung Galaxy Note 3, running CM 12.1. The issue for me was that i had
and had to use it to take and store user photos. When I tried to load those same photos in ImageLoader i got the
(Permission denied)
error. The solution was to explicitly addsince the above permission only limits the write permission up to API version 18, and with it the read permission.
除了所有答案之外,如果客户端使用 Android 6.0,Android 还添加了新的 权限模型。
技巧:如果您的目标版本为 22 或更低版本,您的应用程序将在安装时请求所有权限,就像在运行 Marshmallow 以下操作系统的任何设备上一样。如果您正在尝试模拟器,那么从 android 6.0 开始,您需要明确转到设置 -> 应用程序 -> 。您的应用程序 ->权限并更改权限(如果您已授予任何权限)。
In addition to all answers, if the clients are using Android 6.0, Android added new permission model for (Marshmallow).
Trick: If you are targeting version 22 or below, your application will request all permissions at install time just as it would on any device running an OS below Marshmallow. If you are trying on the emulator then from android 6.0 onwards you need to explicitly go the settings->apps-> YOURAPP -> permissions and change the permission if you have given any.
奇怪的是,在我的 newFile 之前添加斜杠 "/" 之后,我的问题就解决了。我将其更改
为:
更新:
正如评论中提到的,正确的方法是:
Strangely after putting a slash "/" before my newFile my problem was solved. I changed this:
to this:
UPDATE:
as mentioned in the comments, the right way to do this is:
我遇到了同样的问题,但没有任何建议有帮助。但我发现了一个有趣的原因,在物理设备上,Galaxy Tab。
当 USB 存储打开时,外部存储读写权限不会产生任何影响。
只需关闭 USB 存储,并获得正确的权限,问题就会得到解决。
I had the same problem and none of suggestions helped. But I found an interesting reason for that, on a physical device, Galaxy Tab.
When USB storage is on, external storage read and write permissions don't have any effect.
Just turn off USB storage, and with the correct permissions, you'll have the problem solved.
在
API 29+
以上限制将文件存储在与应用目录无关的目录
中。因此,要生成新文件或创建新文件,请使用您的应用程序目录,如下所示:-所以正确的方法是:-
您可以将任何数据写入此生成的文件中!
上面的
文件
是可访问的,并且不会抛出任何异常
,因为它位于您自己开发的应用程序的目录中。另一个选项是
manifest application tag
中的android:requestLegacyExternalStorage="true"
,如Uriel
建议,但它不是永久解决方案!To store a file in a
directory
which is foreign to the app's directory is restricted aboveAPI 29+
. So to generate a new file or to create a new file use your application directory like this :-So the correct approach is :-
You can write any data into this generated file !
The above
file
is accessible and would notthrow any exception
because it resides in your own developed app's directory.The other option is
android:requestLegacyExternalStorage="true"
inmanifest application tag
as suggested byUriel
but its not a permanent solution !我希望
/data
下面的所有内容都属于“内部存储”。但是,您应该能够写入/sdcard
。I would expect everything below
/data
to belong to "internal storage". You should, however, be able to write to/sdcard
.更改
/system/etc/permission/platform.xml
中的权限属性
和组需要如下提及。
Change a permission property in your
/system/etc/permission/platform.xml
and group need to mentioned as like below.
当我试图在 Galaxy S5 (android 6.0.1) 上的 DCIM/camera 文件夹中写入图像时,我遇到了同样的错误,我发现只有这个文件夹受到限制。我只是可以写入 DCIM/任何文件夹,但不能写入相机。
这应该是基于品牌的限制/定制。
I had the same error when was trying to write an image in DCIM/camera folder on Galaxy S5 (android 6.0.1) and I figured out that only this folder is restricted. I simply could write into DCIM/any folder but not in camera.
This should be brand based restriction/customization.
当您的应用程序属于系统应用程序时,它无法访问SD卡。
When your application belongs to the system application, it can't access the SD card.
也许答案是这样的:
在API>=23的设备上,如果你安装了应用程序(该应用程序不是系统应用程序),你应该在“设置-应用程序”中检查存储权限,每个应用程序都有权限列表,你应该检查一下!尝试
Maybe the answer is this:
on the API >= 23 devices, if you install app (the app is not system app), you should check the storage permission in "Setting - applications", there is permission list for every app, you should check it on! try
请记住,即使您在清单中设置了所有正确的权限:
允许第三方应用程序在您的外部卡上写入的唯一位置是“它们自己的目录”
(即/sdcard/Android/data/)
尝试写入其他任何地方:你会得到异常:
EACCES(权限被拒绝)
keep in mind that even if you set all the correct permissions in the manifest:
The only place 3rd party apps are allowed to write on your external card are "their own directories"
(i.e. /sdcard/Android/data/)
trying to write to anywhere else: you will get exception:
EACCES (Permission denied)
从 Android 29 开始使用此已弃用的方法时,您将收到相同的错误:
java.io.FileNotFoundException:打开失败:EACCES(权限被拒绝)
此处的解决方案:
getExternalStoragePublicDirectory 在 Android 中已弃用问
When using this deprecated method from Android 29 onwards you will receive the same error:
java.io.FileNotFoundException: open failed: EACCES (Permission denied)
Resolution here:
getExternalStoragePublicDirectory deprecated in Android Q
就我而言,我使用的是 文件选择器库,它返回外部存储的路径,但它启动了来自
/root/
。即使在运行时授予了WRITE_EXTERNAL_STORAGE权限,我仍然收到错误EACCES(权限被拒绝)。因此,请使用Environment.getExternalStorageDirectory()来获取外部存储的正确路径。
示例:
无法写入:
/root/storage/emulated/0/newfile.txt
可以写入:
/storage/emulated/0/newfile.txt
输出 1:
输出 2:
In my case I was using a file picker library which returned the path to external storage but it started from
/root/
. And even with the WRITE_EXTERNAL_STORAGE permission granted at runtime I still got error EACCES (Permission denied).So use
Environment.getExternalStorageDirectory()
to get the correct path to external storage.Example:
Cannot write:
/root/storage/emulated/0/newfile.txt
Can write:
/storage/emulated/0/newfile.txt
Output 1:
Output 2:
我正在 init.rc 中的 /data/ 下创建一个文件夹(在 Nexus 7 上使用 aosp),并且遇到了这个问题。
事实证明,给予文件夹 rw (666) 权限是不够的,必须是 rwx (777),然后一切就可以了!
I am creating a folder under /data/ in my init.rc (mucking around with the aosp on Nexus 7) and had exactly this problem.
It turned out that giving the folder rw (666) permission was not sufficient and it had to be rwx (777) then it all worked!
如果您通过以下 adb 命令拥有 root 设备,则可以绕过 6.0 后存储权限的强制执行:
The post 6.0 enforcement of storage permissions can be bypassed if you have a rooted device via these adb commands:
我在小米设备(android 10)上遇到了同样的错误。以下代码解决了我的问题。
库:Dexter(https://github.com/Karumi/Dexter) 和图像选择器(https://github.com/Dhaval2404/ImagePicker)
添加清单( android:requestLegacyExternalStorage="true")
i faced the same error on xiaomi devices (android 10 ). The following code fixed my problem.
Libraries: Dexter(https://github.com/Karumi/Dexter) and Image picker(https://github.com/Dhaval2404/ImagePicker)
Add manifest ( android:requestLegacyExternalStorage="true")
就我而言,由于我无法在 sd 卡上创建新文件,因此错误出现在该行上
,因此我必须使用 DocumentFile 方法。
对于上述问题,可以用这种方法解决问题,
也请参阅此线程,
如何使用 Android 5.0 (Lollipop) 提供的新 SD 卡访问 API?
In my case the error was appearing on the line
since I could not create a new file on the sd card,so I had to use the DocumentFile approach.
For the above question the problem may be solved with this approach,
See this thread too,
How to use the new SD card access API presented for Android 5.0 (Lollipop)?
我使用以下流程来处理 Android 11 和 targetapi30 的情况
在我的情况下,根据范围存储在根目录文件中作为预创建的文件目录//<图像/视频...根据要求>
复制选取的文件,并在从我的外部存储选取时将文件复制到缓存目录中
然后在上传时(单击我的发送/上传按钮)将文件从缓存目录复制到我的作用域存储目录,然后执行我的上传过程
使用此解决方案,因为在播放商店中上传应用程序时,它会生成 MANAGE_EXTERNAL_STORAGE 权限的警告就我而言,有时会被游戏商店拒绝。
此外,由于我们使用目标 API 30,因此我们无法将文件从内部存储共享或转发到应用程序
I Use the below process to handle the case with android 11 and targetapi30
As pre-created file dir as per scoped storage in my case in root dir files//<Image/Video... as per requirement>
Copy picked file and copy the file in cache directory at the time of picking from my external storage
Then at a time to upload ( on my send/upload button click) copy the file from cache dir to my scoped storage dir and then do my upload process
use this solution due to at time upload app in play store it generates warning for MANAGE_EXTERNAL_STORAGE permission and sometimes rejected from play store in my case.
Also as we used target API 30 so we can't share or forward file from our internal storage to app
2022 Kotlin 请求许可的方式:
2022 Kotlin way to ask permission:
Google 在 Android Q 上推出了一项新功能:外部存储的过滤视图。对此问题的快速修复是在 AndroidManifest.xml 文件中添加此代码:
您可以在此处阅读有关它的更多信息:https://developer.android.com/training/data-storage/use-cases
编辑: 我开始明白投反对票,因为这个答案超出了Android 11 的日期。因此,无论谁看到此答案,请转到上面的链接并阅读说明。
Google has a new feature on Android Q: filtered view for external storage. A quick fix for that is to add this code in the AndroidManifest.xml file:
You can read more about it here: https://developer.android.com/training/data-storage/use-cases
Edit: I am starting to get downvotes because this answer is out of date for Android 11. So whoever sees this answer please go to the link above and read the instructions.
对于 API 23+,您需要请求读/写权限,即使它们已经在您的清单中。
AndroidManifest.xml
有关请求 API 23+ 权限的官方文档,请检查 https://developer.android.com/training /permissions/requesting.html
For API 23+ you need to request the read/write permissions even if they are already in your manifest.
AndroidManifest.xml
For official documentation about requesting permissions for API 23+, check https://developer.android.com/training/permissions/requesting.html
我遇到了同样的问题... 位于错误的位置。这是正确的:
uses-permission
标记需要位于application
标记之外。I had the same problem... The
<uses-permission
was in the wrong place. This is right:The
uses-permission
tag needs to be outside theapplication
tag.将 android:requestLegacyExternalStorage="true" 添加到 Android 清单
它可在 SDK 29+ 上与 Android 10 (Q) 配合使用
或迁移 Android X 后。
Add android:requestLegacyExternalStorage="true" to the Android Manifest
It's worked with Android 10 (Q) at SDK 29+
or After migrating Android X.
我在模拟器内运行应用程序时观察到过一次。在模拟器设置中,您需要正确指定外部存储(“SD 卡”)的大小。默认情况下,“外部存储”字段为空,这可能意味着不存在此类设备,并且即使在清单中授予了权限,也会抛出 EACCES。
I have observed this once when running the application inside the emulator. In the emulator settings, you need to specify the size of external storage ("SD Card") properly. By default, the "external storage" field is empty, and that probably means there is no such device and EACCES is thrown even if permissions are granted in the manifest.
除了所有答案之外,请确保您没有将手机用作 USB 存储设备。
我在启用 USB 存储模式的 HTC Sensation 上遇到了同样的问题。我仍然可以调试/运行该应用程序,但无法保存到外部存储。
In addition to all the answers, make sure you're not using your phone as a USB storage.
I was having the same problem on HTC Sensation on USB storage mode enabled. I can still debug/run the app, but I can't save to external storage.
请注意,解决方案:
是暂时的,您的应用迟早应该迁移到使用
作用域存储
。在 Android 10 中,您可以使用建议的解决方案来绕过系统限制,但在
Android 11 (R) 中,强制使用作用域存储
,如果继续使用旧逻辑,您的应用可能会崩溃!此视频可能会很有帮助。
Be aware that the solution:
Is temporary, sooner or later your app should be migrated to use
Scoped Storage
.In Android 10, you can use the suggested solution to bypass the system restrictions, but in
Android 11 (R) it is mandatory to use scoped storage
, and your app might break if you kept using the old logic!This video might be a good help.
我的问题是“TargetApi(23)”,如果您的 minSdkVersion 低于 23,则需要它。
因此,我使用以下代码片段请求许可
My issue was with "TargetApi(23)" which is needed if your minSdkVersion is bellow 23.
So, I have request permission with the following snippet
Android 10 (API 29) 引入了分区存储。更改清单以请求旧存储并不是长期解决方案。
当我将之前的
Environment.getExternalStorageDirectory()
实例(API 29 已弃用)替换为context.getExternalFilesDir(null)
时,我修复了该问题。请注意,如果存储位置不可用,
context.getExternalFilesDir(type)
可能会返回 null,因此无论何时检查您是否具有外部权限,请务必检查这一点。点击此处了解更多信息。
Android 10 (API 29) introduces Scoped Storage. Changing your manifest to request legacy storage is not a long-term solution.
I fixed the issue when I replaced my previous instances of
Environment.getExternalStorageDirectory()
(which is deprecated with API 29) withcontext.getExternalFilesDir(null)
.Note that
context.getExternalFilesDir(type)
can return null if the storage location isn't available, so be sure to check that whenever you're checking if you have external permissions.Read more here.
我也有同样的经历。我发现,如果您转到设置 ->应用管理器->您的应用程序 ->权限->启用存储,它解决了问题。
I'm experiencing the same. What I found is that if you go to Settings -> Application Manager -> Your App -> Permissions -> Enable Storage, it solves the issue.
事实证明,这是一个愚蠢的错误,因为我的手机仍然连接到台式电脑,但没有意识到这一点。
所以我必须关闭 USB 连接,一切正常。
It turned out, it was a stupid mistake since I had my phone still connected to the desktop PC and didn't realize this.
So I had to turn off the USB connection and everything worked fine.