API 26+: WRITE_EXTERNAL_STORAGE 权限总是被拒绝

API 26+: WRITE_EXTERNAL_STORAGE permission is always denied

我已将我的应用程序切换到目标 API 27,现在无法授予它 WRITE_EXTERNAL_STORAGE 权限 -- grantResult 始终是 -1.

我的应用需要此权限,因为它不使用应用的私人外部存储 space(doesn't require WRITE_EXTERNAL_STORAGE 从 API 19 开始)。

我知道在 API 26 中有 behavior changes for permissions。然而这并不能解释我的问题。

我正在以标准方式请求 READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE 权限:

ActivityCompat.requestPermissions(activity, new String[] {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
    }, requestCode);

(两种权限均通过清单中的 <uses-permission 声明)。

对话框出现,我点击 "Allow":

但是在 onRequestPermissionsResult 回调中,我得到 WRITE_EXTERNAL_STORAGE-1(拒绝)(以及 READ_EXTERNAL_STORAGE0(授予))。

两者的结果不应该是 0 因为我已经请求并且大概已经授予了两者吗?

我曾尝试单独请求 WRITE_EXTERNAL_STORAGE,但在这种情况下,对话框根本没有出现。

更详细一点:我刚刚检查了 build/intermediates/manifests/full/debug 中的合并清单,注意到 WRITE_EXTERNAL_STORAGE 权限具有属性 android:maxSdkVersion="18"(我的清单中没有这样的属性)。这可能是因为我的应用有 minApiVersion=21,但我不确定。

沿线的某个地方,您正在选择 android:maxSdkVersion="18" 属性。我的猜测是它来自图书馆。当您编辑自己的清单时,请检查 Android Studio 中的 "Merged Manifest" 选项卡。它将详细说明各种元素和属性的贡献。

android:maxSdkVersion 会在更高的 Android SDK 版本上删除您的 <uses-permission> 元素,至少在运行时权限的工作方式方面是这样。

由于所有版本都需要此权限,因此在 <uses-permission> 元素上添加 tools:remove="android:maxSdkVersion" 应该会还原 android:maxSdkVersion="18" 并提供您所期望的内容。

我在清单中注意到我的权限中有一个 space,它是 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE "/>,我将其更改为 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>,问题解决了。