在运行时请求和允许 WRITE_EXTERNAL_STORAGE 权限对当前会话没有影响 [英] Requesting and allowing WRITE_EXTERNAL_STORAGE permission at runtime has no effects on the current session

查看:108
本文介绍了在运行时请求和允许 WRITE_EXTERNAL_STORAGE 权限对当前会话没有影响的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是关于请求 Manifest 时 Android Marshmallow 中引入的运行时权限的新模型.permission.WRITE_EXTERNAL_STORAGE 权限.

this is regarding the new model of runtime permissions introduced in Android Marshmallow when requesting Manifest.permission.WRITE_EXTERNAL_STORAGE permission.

简而言之,我遇到的是,如果我请求(并且用户允许)Manifest.permission.WRITE_EXTERNAL_STORAGE 权限,应用程序将无法从外部存储读取和写入目录直到我销毁并重新启动应用程序.

In short, what I am experiencing is that if I request (and the user allows) Manifest.permission.WRITE_EXTERNAL_STORAGE permission, the app won't be able to read and write from the external storage directory until I destroy and restart the app.

这就是我正在做的/正在经历的:

This is what I am doing/experiencing:

我的应用程序从以下状态开始:

My app starts from a state where:

ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED

这是,我无权访问外部存储.

This is, I don't have permissions to to access external storage.

然后,我像谷歌解释的那样请求 Manifest.permission.WRITE_EXTERNAL_STORAGE 的许可

Then, I request permission to Manifest.permission.WRITE_EXTERNAL_STORAGE just as Google explains

private void requestWriteExternalStoragePermission() {
    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
        new AlertDialog.Builder(this)
                .setTitle("Inform and request")
                .setMessage("You need to enable permissions, bla bla bla")
                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ActivityCompat.requestPermissions(MendeleyActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, RC_PERMISSION_WRITE_EXTERNAL_STORAGE);
                    }
                })
                .show();
    } else {
        ActivityCompat.requestPermissions(MendeleyActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, RC_PERMISSION_WRITE_EXTERNAL_STORAGE);
    }
}

一旦用户允许权限,onRequestPermissionsResult 就会被调用.

Once the user allows the permission, onRequestPermissionsResult gets invoked.

@Override
public void onRequestPermissionsResult(int requestCode,  String permissions[], int[] grantResults) {
    switch (requestCode) {
        case RC_PERMISSION_WRITE_EXTERNAL_STORAGE: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 && PackageManager.PERMISSION_GRANTED
                // allowed 
            } else {
                // denied
            }
            break;
        }
    }
}

执行 allowed 块,确认用户已授予权限.

The allowed block is executed, confirming the user has granted permissions.

立即在此之后,如果我不销毁并再次打开该应用程序,我仍然没有访问外部存储的权限.更具体地说:

Immediately after this, if I don't destroy and open the app again, I still have no access permission to external storage. More specifically:

hasWriteExternalStoragePermission();                  // returns true
Environment.getExternalStorageDirectory().canRead();  // RETURNS FALSE!!
Environment.getExternalStorageDirectory().canWrite(); // RETURNS FALSE!!

所以,Android 运行时似乎认为我有权限,但文件系统没有...实际上,尝试访问 Environment.getExternalStorageDirectory() 会引发异常:

So, it seems the Android runtime thinks I have permissions, but the file system doesn't... Indeed, trying to access Environment.getExternalStorageDirectory() throws the exception:

android.system.ErrnoException: open failed: EACCES (Permission denied)
at libcore.io.Posix.open(Native Method)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
at libcore.io.IoBridge.open(IoBridge.java:438)
at java.io.FileOutputStream.<init>(FileOutputStream.java:87) 
at java.io.FileOutputStream.<init>(FileOutputStream.java:72) 

如果我现在销毁应用程序并再次打开它,行为就会变得正常,能够在外部存储文件夹中读写.

If I now destroy the app and open it again, the behaviour becomes as it should, being able to read and write in the external storage folder.

有人遇到过这种情况吗?

Is anyone experiencing this?

我正在使用一个官方模拟器:

I am using one official emulator with:

  • 最新的 Android 6.0 (API 23) API 23,修订版 1.
  • 运行 Intel x86 Atom 系统映像、API 23、Rev 1 的模拟器.

我使用以下方法构建应用程序:

I build the app with:

android {
    compileSdkVersion 23
    buildToolsVersion "22.0.1"

    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 23
    }
...
}

如果有人证实了这一点并且我不是唯一的人,我想我们需要打开一个错误,但我希望我做错了什么,因为我认为这样的核心功能不太可能在 SDK 中出现错误.

If someone confirms this and I am not the only one I guess we'll need to open a bug, but I hope I am doing something wrong, as I think such a core feature is unlikely to be buggy in the SDK.

推荐答案

http://developer.android.com/reference/android/Manifest.permission.html#WRITE_EXTERNAL_STORAGE:

从 API 级别 19 开始,读取/写入 getExternalFilesDir(String) 和 getExternalCacheDir() 返回的特定于应用程序的目录中的文件不需要此权限.

Starting in API level 19, this permission is not required to read/write files in your application-specific directories returned by getExternalFilesDir(String) and getExternalCacheDir().

运行时权限从 API 级别 23 开始,显然高于 19,因此不再需要该权限,除非您正在访问 getExternalFilesDir() 指向的文件夹之外的数据.因此,我认为这是仅在模拟器上进行测试时才会出现的错误.

Runtime permissions start at API level 23, obviously above 19, so the permission is not required anymore unless you're accessing the data outside of the folder pointed by getExternalFilesDir(). Therefore, I believe this is a bug only present when testing on an emulator.

在级别低于 19 的目标上,不支持在运行时请求权限,只需在清单中声明权限即可.

On targets below level 19, which don't support requesting permission at runtime, just claim the permission in manifest and it will work.

这篇关于在运行时请求和允许 WRITE_EXTERNAL_STORAGE 权限对当前会话没有影响的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆