API 26+:WRITE_EXTERNAL_STORAGE权限始终被拒绝

24

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

我的应用程序需要此权限,因为它不使用应用程序的私有外部存储空间(从API 19开始不需要WRITE_EXTERNAL_STORAGE)。

我知道在API 26中有权限的行为更改。然而,这并不能解释我的问题。

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

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

(两个权限都在清单文件中通过<uses-permission声明)。

对话框出现,我点击“允许”:

enter image description here

然而,在onRequestPermissionsResult回调中,我得到了一个-1(拒绝)的结果,对于WRITE_EXTERNAL_STORAGE权限,而对于READ_EXTERNAL_STORAGE权限则为0(授予)。

既然我已经请求并且可能已经授予了这两个权限,那么这个结果不应该是两个权限都为0吗?

我尝试过仅请求WRITE_EXTERNAL_STORAGE权限,但在这种情况下,对话框根本不会出现。

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


“both permissions are declared via <uses-permission in manifest” - 你确定吗?如果在清单文件中没有请求“WRITE_EXTERNAL_STORAGE”,那么你的症状就符合我的预期。 - CommonsWare
4
是的,两者都在清单文件中。然而,我刚刚检查了build/intermediates/manifests/full/debug下合并后的清单文件,并注意到WRITE_EXTERNAL_STORAGE权限有一个属性android:maxSdkVersion="18"(我的清单文件中没有这个属性)。这可能是导致问题的原因吗? - Denys Kniazhev-Support Ukraine
6
啊,那可能就是问题所在了。大概是某个库有这个限制,正在被合并进来。尝试在你的<uses-permission>元素上添加tools:remove="android:maxSdkVersion",看看能否解决问题。 - CommonsWare
2
@CommonsWare,它起作用了!可能是因为我的minSdkVersion21,所以清单合并器添加了maxSdkVersion=18。这感觉很不直观,值得向谷歌报告一个错误。我已经更新了有关合并后清单的信息的问题。如果您将您的建议发布为答案,我将非常乐意接受。谢谢! - Denys Kniazhev-Support Ukraine
2
很高兴听到它正在工作。我会在下周写一篇博客来介绍这个。 - CommonsWare
显示剩余2条评论
2个回答

46
在某个地方,你添加了android:maxSdkVersion="18"属性。我猜测这是来自一个库。检查Android Studio中编辑自己清单时的"Merged Manifest"选项卡,它将详细说明哪些元素和属性是由什么贡献的。 android:maxSdkVersion具有在高版本Android SDK中删除<uses-permission>元素的效果,至少在运行时权限方面如此。
由于你需要该权限适用于所有版本,因此在<uses-permission>元素上添加tools:remove="android:maxSdkVersion"应该会恢复android:maxSdkVersion="18"并提供你所期望的结果。

3
从未注意到Android Studio实际上有一个“合并清单”选项卡,这真的很不错。 - Denys Kniazhev-Support Ukraine
2
和@DenisKniazhev一样,我也遇到了完全相同的问题,但这个解决方案起作用了! 我也不知道有类似“合并清单”的东西。 对于像我这样的人,“合并清单”选项卡可以在打开“AndroidManifest.xml”文件时找到,就在“文本”选项卡旁边,位于您的清单文件的左下角(适用于Android Studio 3.1.3)。 - Edward Quixote
什么是解决方案? - gurkan stack
3
如果您正在使用HockeyApp并且无法写入外部存储,那么这就是原因。您还可以使用tools:node="replace" - Carter Hudson
HockeyApp 让我感到开心。 - joe
Re:HockeyApp -- 很有趣 -- 又是微软的一次收购。 - steven smith

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

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