Android上的例外'开放失败:EACCES(权限被拒绝)'

Mer*_*ert 249 android android-permissions android-5.0-lollipop android-storage

我正进入(状态

开放失败: EACCES (Permission denied)

在线上 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();
}
Run Code Online (Sandbox Code Playgroud)

Jus*_*ler 316

对于API 23+,您需要请求读/写权限,即使它们已经在您的清单中.

// Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
};

/**
 * Checks if the app has permission to write to device storage
 *
 * If the app does not has permission then the user will be prompted to grant permissions
 *
 * @param activity
 */
public static void verifyStoragePermissions(Activity activity) {
    // Check if we have write permission
    int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permission != PackageManager.PERMISSION_GRANTED) {
        // We don't have permission so prompt the user
        ActivityCompat.requestPermissions(
                activity,
                PERMISSIONS_STORAGE,
                REQUEST_EXTERNAL_STORAGE
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

AndroidManifest.xml中

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Run Code Online (Sandbox Code Playgroud)

有关请求API 23+权限的官方文档,请查看https://developer.android.com/training/permissions/requesting.html

  • 只是为了澄清,为了使其工作,活动必须处理活动权限请求响应.有关详细信息,请参阅http://developer.android.com/training/permissions/requesting.html#handle-response. (12认同)
  • 但是我在哪里使用它?例如,如果我想拍照,我是否必须在startActivityForResult或onActivityResult之前运行verifyStoragePermissions?这让我很困惑. (5认同)
  • 谢谢这解决了我的问题.只是注意:如果有人无法解析"Manifest.permission"你只需要导入"import android.Manifest". (3认同)

use*_*990 230

我遇到了同样的问题......那<uses-permission是在错误的地方.这是正确的:

 <manifest>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        ...
        <application>
            ...
            <activity> 
                ...
            </activity>
        </application>
    </manifest> 
Run Code Online (Sandbox Code Playgroud)

uses-permission标签必须是外面application的标签.

  • 警告在android 4.4.4中不要使用参数`android:maxSdkVersion ="18"`.它正在产生这个例外 (11认同)
  • 我收到一个警告:"`<uses> permission>`标签出现在`<application>`tag"之后 (3认同)
  • 这是uses-permission需要在应用程序之外 (2认同)
  • API 29 之后,您将需要这个:https://medium.com/@sriramripirala/android-10-open-failed-eacces-permission-denied-da8b630a89df (2认同)

小智 73

android:requestLegacyExternalStorage="true"添加到 Android Manifest 它在 SDK 29+
或在迁移Android X之后与 Android 10 (Q) 一起使用。

 <application
    android:name=".MyApplication"
    android:allowBackup="true"
    android:hardwareAccelerated="true"
    android:icon=""
    android:label=""
    android:largeHeap="true"
    android:supportsRtl=""
    android:theme=""
    android:requestLegacyExternalStorage="true">
Run Code Online (Sandbox Code Playgroud)

  • 不适用于 Android 11 (5认同)

h22*_*h22 58

我在模拟器中运行应用程序时观察过一次.在仿真器设置中,您需要正确指定外部存储器的大小("SD卡").默认情况下,"外部存储"字段为空,这可能意味着即使在清单中授予了权限,也不会抛出此类设备和EACCES.


joh*_*ohn 50

除了所有答案之外,请确保您没有将手机用作USB存储设备.

我在启用USB存储模式的HTC Sensation上遇到了同样的问题.我仍然可以调试/运行应用程序,但我无法保存到外部存储.


Uri*_*kel 29

Google在Android Q上具有一项新功能:外部存储的过滤视图。一个快速的解决方法是在AndroidManifest.xml文件中添加以下代码:

<manifest ... >
    <!-- This attribute is "false" by default on apps targeting Android Q. -->
    <application android:requestLegacyExternalStorage="true" ... >
     ...
    </application>
</manifest>
Run Code Online (Sandbox Code Playgroud)

您可以在这里了解更多信息:https : //developer.android.com/preview/privacy/scoped-storage

  • 先生,您节省了我很多时间。对于 Q 中的开发人员来说,很多事情已经成为一种痛苦。我认为这个答案应该作为一个单独的问题发布,并且值得更多的赞成。 (25认同)
  • 从 Android 11 开始,此规则不再有效 (6认同)
  • @RoshanaPitigala 需要为 android 11 做什么?任何链接? (2认同)
  • 来自权威的荒谬事情!给开发者带来额外的痛苦,为什么?我们来到安卓是我们的错吗? (2认同)

Pir*_*jin 28

我的问题是"TargetApi(23)",如果你的minSdkVersion低于23,则需要这个.

所以,我有以下代码段的请求权限

protected boolean shouldAskPermissions() {
    return (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1);
}

@TargetApi(23)
protected void askPermissions() {
    String[] permissions = {
            "android.permission.READ_EXTERNAL_STORAGE",
            "android.permission.WRITE_EXTERNAL_STORAGE"
    };
    int requestCode = 200;
    requestPermissions(permissions, requestCode);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
// ...
    if (shouldAskPermissions()) {
        askPermissions();
    }
}
Run Code Online (Sandbox Code Playgroud)


omz*_*zer 28

请注意,解决方案:

<application ...
    android:requestLegacyExternalStorage="true" ... >
Run Code Online (Sandbox Code Playgroud)

是暂时的,您的应用迟早应该迁移到使用Scoped Storage.

在 Android 10 中,您可以使用建议的解决方案绕过系统限制,但在 中Android 11 (R) it is mandatory to use scoped storage,如果您继续使用旧逻辑,您的应用可能会崩溃!

这个视频可能是一个很好的帮助。


jac*_*ood 16

Android 10 (API 29) 引入了 Scoped Storage。更改清单以请求旧存储不是长期解决方案。

当我Environment.getExternalStorageDirectory()context.getExternalFilesDir(null).

请注意,context.getExternalFilesDir(type)如果存储位置不可用,则可以返回 null,因此无论何时检查您是否具有外部权限,请务必检查。

在这里阅读更多。


Atu*_*hik 15

我也遇到了同样的问题.我发现如果你去设置 - >应用程序管理器 - >你的应用程序 - >权限 - >启用存储,它解决了这个问题.

  • 我找不到这个部分? (3认同)

Tob*_*ich 13

事实证明,这是一个愚蠢的错误,因为我的手机仍然连接到台式电脑,并没有意识到这一点.

所以我不得不关闭USB连接,一切正常.


Zoo*_*ooS 13

我在三星Galaxy Note 3上遇到了同样的问题,运行CM 12.1.我的问题是我有

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="18"/>
Run Code Online (Sandbox Code Playgroud)

并且必须使用它来拍摄和存储用户照片.当我试图在ImageLoader中加载那些相同的照片时,我收到了(Permission denied)错误.解决方案是明确添加

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Run Code Online (Sandbox Code Playgroud)

由于上述权限仅将写入权限限制为API版本18,并且具有读取权限.


Nou*_*ane 9

除了所有答案之外,如果客户使用Android 6.0,Android 为(Marshmallow)添加了新的权限模型.

技巧:如果您的目标是22或更低版本,您的应用程序将在安装时请求所有权限,就像在Marshmallow下运行操作系统的任何设备上一样.如果您正在尝试使用模拟器,那么从Android 6.0开始,您需要明确地去设置 - > apps-> YOURAPP - >权限并更改权限(如果您已经提供).

  • 真是难以置信,我花了2天的时间来弄清楚这一点。每当我觉得Android上的一切运行顺利时,就会发生这种情况。 (2认同)

小智 6

我有同样的问题,没有任何建议有帮助.但是我发现了一个有趣的原因,在物理设备上,Galaxy Tab.

启用USB存储时,外部存储读写权限不起作用.只需关闭USB存储,并使用正确的权限,您将解决问题.

  • 该死的,我只花了大约三个小时的时间。另外,我必须重新启动设备,它才能正常工作。非常感谢 (2认同)

San*_*Sur 6

上面限制将文件存储在directory应用程序目录之外的目录中。因此,要生成新文件或创建新文件,请使用您的应用程序目录,如下所示:-API 29+

所以正确的方法是:-

val file = File(appContext.applicationInfo.dataDir + File.separator + "anyRandomFileName/")
Run Code Online (Sandbox Code Playgroud)

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

上面的内容file是可以访问的,但不能访问throw any exception,因为它位于您自己开发的应用程序的目录中。

另一种选择是 android:requestLegacyExternalStorage="true"按照manifest application tag建议的,Uriel但它不是永久的解决方案!


小智 5

我希望下面的所有内容都/data属于"内部存储".但是,您应该能够写信给/sdcard.

  • 我也试过<uses-permission android:name ="android.permission.WRITE_INTERNAL_STORAGE"/>.还是一样的. (5认同)

小智 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>
Run Code Online (Sandbox Code Playgroud)


小智 5

尝试在Galaxy S5(android 6.0.1)的DCIM / camera文件夹中写入图像时遇到相同的错误,我发现只有此文件夹受到限制。我可以直接写入DCIM /任何文件夹,但不能写入相机。这应该是基于品牌的限制/定制。


Dar*_*ush 5

在我的newFile之前加一个斜杠“ /”之后,奇怪的是我的问题解决了。我改变了这个:

File myFile= new File(Environment.getExternalStorageDirectory() + "newFile");
Run Code Online (Sandbox Code Playgroud)

对此:

File myFile= new File(Environment.getExternalStorageDirectory() + "/newFile");
Run Code Online (Sandbox Code Playgroud)

  • 这里没什么奇怪的。在第一行中,您试图在与包含外部存储目录的目录相同的目录中创建一个文件。即 /storage/.../somethingnewfile 而不是 /storage/.../something/newfile (2认同)
  • 正确的方法是使用File(dir,file)cosntructor (2认同)

小智 5

也许答案是这样的:

在API >= 23的设备上,如果你安装了应用程序(该应用程序不是系统应用程序),你应该在“设置-应用程序”中检查存储权限,每个应用程序都有权限列表,你应该检查它!尝试


Sha*_*bin 5

Android Q解决方案:

<application ...
    android:requestLegacyExternalStorage="true" ... >
Run Code Online (Sandbox Code Playgroud)