转载:https://juejin.cn/post/6844904113096900621
Android10 存储权限已经打开,仍提示Permissioin denied
日常搬砖写Demo时,新建了一个工程,在写文件时发现提示Permission denied,然后把运行时权限加上,仍然提示denied,打开权限管理查看也已经打开了读写权限。排查了好一会儿终于了发现问题,记录一下。
Android10(29)对存储权限的修改
Android 10之前
内存存储 :(data/xxxx/)通过getFilesDir()得到存储路径
外部存储:(sdcard(mnt)/xxxx),通过getExternalStorageDirectory()得到路径
Android 10(29)之后
特定目录:无需权限申请,卸载自动删除 getExternalFilesDir()得到路径
媒体文件目录 (照片,视频等):需要READ_EXTERNAL_STORAGE,使用MeidaStore访问。
其他目录:使用SAF访问。
在Android 10上即使拥有了读写权限,也无法正常的读取文件。
解决方案
同一份的代码放到真正工程中就没得问题,Demo工程就Permission denied。仔细对比之后最终定位到了targetSdkVersion上,之前对targetSdkVersion的理解是一知半解,趁此机会加深一下理解。
出现原因
AS上新建工程compileSdkVersion通常都等于targetSdkVersion,一般来说默认为最新版本。 targetSdkVersion=29 表示当前工程的代码已经完美适配了10.0,当运行在10.0设备上时,将按照10.0的新特性来执行,根据Google在10上对存储权限的优化,所以提示没权限也很正常。
解决问题
由于只是个Demo工程,将targetSdkVersion降到28就可以解决此问题。
targetSdkVersion > 设备sdkVersion: 栗如 targetSdkVersion是29,但是运行的设备是7.0,这时候你想让他按照10.0的特性来运行,肯定不现实,也不可能,所以将按照7.0特性运行。
targetSdkVersion = 设备sdkVersion: 这是Google最希望见到的,此时将按照targetSdkVersion指定版本运行。
targetSdkVersion < 设备sdkVersion: 设备的sdkVersion要高于targetSdkVersion,通常来说设备拥有按照高低版本特性运行的能力。 这种情况下Google会选择targetSdkVersion来运行(所以把targetSdkVersion降为28就解决了没权限问题)
在真实的工程中解决权限适配问题,还是要根据不同版本号来适配的,我这里只是个Demo,所以就简单粗暴的解决了。
总结
对targetSdkVersion,minSdkVersion,compileSdkVersion的理解,看过几篇文章,觉得很简单,一代而过,并没有花时间是彻底搞懂,但是苍天饶过谁,这回就掉进了坑里,多付出了好几倍的时间来从坑里爬出来。