安卓棉花糖操作系统权限模型在OS 4.0上的READ_EXTERNAL_STORAGE权限总是未被授予。

12

当我在Android 4.0操作系统上运行我的应用程序并请求READ_EXTERNAL_STORAGE权限时,出现了问题:

ActivityCompat.requestPermissions(ctx, requestedPermissions, requestCode);

我总是被回调

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
        @NonNull int[] grantResults) { 

grantResults != PackageManager.PERMISSION_GRANTED

使用ActivityCompat.checkSelfPermission检查权限总是返回permissionDenied

在Android 6.0上通过系统对话框请求权限可以很好地工作。 除了Android 4.x(不包括4.0)之外,所有权限都一直被授予。 在Android 4.0上,除了READ_EXTERNAL_STORAGE权限,其他权限(相机、日历、联系人、电话)都表现良好。

可能是一个操作系统的问题?


1
https://dev59.com/G1wY5IYBdhLWcg3w36-G - frogatto
@dex 问题在于,与权限相关的活动方法仅在API 23上可访问。 - skirix
@Skirx:是的,你需要设置targetSDK = 23和compileSDK = 23才能使用它们,如果你没有设置这些,那么你将无法支持Android M。 - dex
@dex 这里的问题是我设置了android:minSdkVersion="14"和android:targetSdkVersion="23"。正如你在下面的问题中看到的,在4.0.3上会出现permissionDenied的情况。 如果我将android:minSdkVersion="23"和android:targetSdkVersion="23"设置为6.0,则仅在OS 6.0上运行,并且行为正常,没有问题。这里的问题是checkSelfPermission在OS 4.0.3上必须返回Granted而不是Denied。我认为这是CompatLibrary的问题。 - skirix
@skirix 我不是要求更改 minSDK 版本,而是建议更改 compileSDK 和 TargetSDK,并使用 activity 方法。如果您正在使用 gradle android {compileSdkVersion 23 buildToolsVersion '23.0.0'....} <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="23" />。 - dex
显示剩余2条评论
2个回答

11

ActivityCompat.requestPermissions()的作用是:

  • 如果您使用的是Android 6.0+,则调用实际的requestPermissions()

  • 在旧版本的Android上,使用PackageManager查看您是否持有请求的权限

READ_EXTERNAL_STORAGE的问题在于它是在API Level 16(Android 4.1)中添加的。 在比那更早的Android版本上,您不能持有它,因为它不存在。

要么:

  • 将您的minSdkVersion设置为16,或者

  • 放置自己的逻辑来处理此情况,认识到READ_EXTERNAL_STORAGE在API Level 16之前是不相关的


7
一个简单的解决方法是请求WRITE_EXTERNAL_STORAGE 权限代替 READ_EXTERNAL_STORAGE,该权限从API 4开始可用。在M版本中,WRITEREAD属于同一权限组,因此请求前者也将授予对后者的访问权限。唯一的缺点是,在4.1之前的版本中,如果您以前仅请求READ权限,则会看到需要新权限的提示。 - Sebastiano
1
@dextor:这假设 Android 会始终在权限组的级别而不是权限的级别要求用户授权。我不会这样假设。 - CommonsWare

0

在处理 Android 8.0 上的 FOREGROUND_SERVICE 时,我发现了这个问题。不幸的是,我的解决方案依赖于异常处理,但它不需要处理 API 级别支持权限的问题。您可以使用以下方法检查当前 API 级别上是否存在权限:

private boolean permissionExistsOnCurrentApiLevel(String permission) {
    try {
        getPackageManager().getPermissionInfo(permission, PackageManager.GET_META_DATA);
    } catch (PackageManager.NameNotFoundException e) {
        return false;
    }

    return true;
}

使用此方法,您可以实现自己的版本ContextCompat.checkSelfPermission,其中所有不存在的权限都自动视为已授予:

private int myCheckSelfPermission(@NonNull Context context, @NonNull String permission) {
    if(!permissionExistsOnCurrentApiLevel(permission)) {
        return PackageManager.PERMISSION_GRANTED;
    }

    return ContextCompat.checkSelfPermission(this, permission);
}

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