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

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

问题描述

这与请求Manifest.permission.WRITE_EXTERNAL_STORAGE权限时 Android棉花糖中引入的运行时权限的新模型有关

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.

然后,就像Google解释的那样,我请求对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.

有人遇到这种情况吗?

我正在使用一个官方仿真器,用于:

I am using one official emulator with:

  • 最新的Android 6.0(API 23)API 23,修订版1.
  • 运行Intel x86 Atom系统映像,API 23,修订版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天全站免登陆