Android 11 文件适配

compileSDKversion
这个是编译期间你所使用的api版本,一般越高越好,越高表示开发时可以
使用的api越新,并且可以避免使用被抛弃的sdk。

minSdkVersion
这个是支持的最小SDK版本,很好理解,在小于minSdkVersion的手机系统上无法安装

targetSdkVersion
为兼容而生,使开发的app在各个版本的手机系统上表现一致,如果实际手机系统低于开发时定义的targetAPI,那么会以系统api版本为准。而如果实际手机系统的api版本高于开发时定义的targetApi,则会以targetSDK版本为准,缺点就是这样会放弃了新版本的一些特性

在Android 10之前的版本上,我们在做文件的操作时都会申请存储空间的读写权限。但是这些权限完全被滥用,造成的问题就是手机的存储空间中充斥着大量不明作用的文件,并且应用卸载后它也没有删除掉。
为了解决这个问题,Android 10 中引入了Scoped Storage 的概念,通过添加外部存储访问限制来实现更好的文件管理。

存储基本知识

首先明确一个概念,外部储存和内部储存。

  • 内部储存:/data 目录。
    获取本应用的内部储存路径,读写该路径下的文件不需要申请储存空间读写权限,且卸载应用时会自动删除。
一般我们使用getFilesDir()  方法,对应的目录:`//data/data/com.face.myapplication/files`

 getCacheDir() 方法,对应的目录`/data/user/0/com.face.myapplication/cache` 
  • 外部储存:/storage 或 /mnt 目录。一般我们使用getExternalStorageDirectory()方法获取的路径来存取文件。
外部存储 App私有目录 (App卸载的时候,会被清除。)

Android/data/--->存储各个App的外部私有目录
与内部存储类似,命名方式是:Android/data/xx------>xx指应用的包名。
如:/sdcard/Android/data/com.fish.myapplication

读写App外部私有目录

    private void testAppDir(Context context) {
        //4个基本方法
        File fileDir = context.getExternalFilesDir(null);
        //API>=19
        File[] fileList = context.getExternalFilesDirs(null);

        File cacheDir = context.getExternalCacheDir();
        //API>=19
        File[] cacheList = context.getExternalCacheDirs();

        //指定目录,自动生成对应的子目录
        File fileDir2 = context.getExternalFilesDir(Environment.DIRECTORY_DCIM);
    }


只要拿到根目录,就可以遍历寻找其它子目录/文件。

    private void testOtherDir(Context context) {
        File rootDir = Environment.getExternalStorageDirectory();
    }
   返回的rootDir路径:/storage/emulated/0/。
其它目录

比如各个App在/sdcard/目录下创建的目录,如支付宝创建的目录:alipy/,微博创建的目录: com.sina.weibo/,qq创建的目录:com.tencent.mobileqq/等。

image.png

以下目录无需存储权限即可访问:
1、App自身的内部存储
2、App自身的自带外部存储-私有目录

剩下的都需要申请存储权限,Android 10.0前后对于存储作用域访问的区别就体现在如何访问剩余这些目录内的文件。

其中比较容易混淆的是: 内部存储与外部存储里的App私有目录,两者命名风格很像。

不同点:
/data/data/com.fish.myapplication/ 位于内部存储,一般用于存储容量较小的,私密性较强的文件。而/sdcard/Android/data/com.fish.myapplication/ 位于外部存储,作为App私有目录,一般用于存储容量较大的文件,即使删除了也不影响App正常功能。

相同点:
属于App专属,App自身访问两者无需任何权限。
2、App卸载后,两者皆被删除。
3、两者目录下增加的文件最终会被统计到"设置->存储和缓存"里。

因为不同厂商、系统版本的原因,所以上述的方法并没有一个固定的文件路径。了解了上面的概念,那我们所说的外部储存访问限制,可以认为是针对getExternalStorageDirectory()路径下的文件。

Android 10.0 ( targetSdkVersion 改为 29)访问方式变更

在Android 10 之前 ,用户可以随意在SD 卡创建文件目录,比如我们能够直接在/sdcard/目录下创建目录/文件。事实上,很多App就是这么干的,目录结构很乱,而且App卸载后,对应的目录并没有删除,于是就是遗留了很多"垃圾"文件,久而久之不处理,用户的存储空间越来越小。
总结弊端如下:
1、在设置里"Clear storage"或者"Clear cache"并不能删除该目录下的文件
2、卸载App也不能删除该目录下的文件
3、App可以随意修改其它目录下的文件,如修改别的App创建的文件等,不安全

好处:
1、此处新建的目录不会被设置里的App存储用量统计,让用户"看起来"自己的App占用的存储空间很小
2、方便操作文件

面对众多App随意新建目录/文件的现象,Google在Android 10.0上重拳出击了引入Scoped Storage、分区存储,原理如下:

  • App访问自身内部存储空间与 访问外部存储空间的App私有目录不需要任何权限(这个与Android 10.0之前一致)

  • 外部存储空间-共享存储空间、外部存储空间-其它目录 App无法通过路径直接访问,不能新建、删除、修改目录/文件等, 需要通过Uri访问

适配

最简单粗暴的方法就是在 AndroidManifest.xml 中添加 android:requestLegacyExternalStorage="true" 来请求使用旧的存储模式。但是我不推荐此方法。因为在下一个版本的Android中,此条配置将会失效

  • requestLegacyExternalStorage 是什么?通过翻查官方文档,大概知道了这个属性的意思:在配置targetSdk >= 29,应用搭载在Android 10及以上版本的手机运行时,可以暂时停用「分区存储」
在AndroidManifest.xml 里application标签下添加:

微信图片_20220601173049.jpg

参考文章

你可能感兴趣的:(Android 11 文件适配)