首先还是要丢一下官方适配连接,刚开始准备适配的朋友还是去官网玩耍一波:
https://developer.android.google.cn/about/versions/10
先说下我的需求适配android 10沙盒,需要获取到根目录权限,能够自由的去操控存储。
当去看完官方android 10的文档说明时,并没有发现适配根目录的方案,坑爹吧,怎么下手啊
没辙继续看官方说明的,然后找到下面连接,去github下载Demo测试
https://developer.android.google.cn/training/data-storage/files/media#manage-groups-of-files
测试跳转也只能跳转到下载位置,需要手动切换显示隐藏文件的时候可以允许手机文件权限:
好吧,继续在搜素没有发现另外可行方案,官网也是只是说明了一下变更,并没有适配方案出来,发现华为官网适配也是需要引导用户手动授权,好咯,只能先如此了。
下面也放一下跳转代码以及回调返回的Uri
private static final int READ_REQUEST_CODE = 42;
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION |
Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
startActivityForResult(intent, READ_REQUEST_CODE);
@Override
public void onActivityResult(int requestCode, int resultCode,Intent resultData) {
//使用resultdata.getdata ( )提取该URI
if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
Uri uri = null;
if (resultData != null) {
uri = resultData.getData();
}
}
}
如此就可以获取到根目录的Uri了,下面你可以在你的根目录上为所欲为了...
下面继续说一下适配过程中的坑:
第一个坑: 一个是通过上面获取到根目录Uri的时候去循环根目录寻找文件时,是通过DocumentFile.fromTreeUri(Context,uri).listFiles();当循环拿到子目录的根据子目录Uri去获取子目录文件的时候,神奇的事情就发生了,拿到的目录还是根目录下的子目录 what?什么鬼?断点日志确定不是子目录Uri路径错误的时候,有的玩了...大条了,现在获取文件不能通过File file = new File(path);拿到路径那么该如何获取?
还是一句话继续走,拿起你的小手继续百度走起,查到google官网对DocumentFile一个说明引起了我的注意,连接如下https://developer.android.google.cn/jetpack/androidx/releases/documentfile?hl=zh-cn
什么鬼?androidx?bug修复?还有一个androidx包的引用?回到项目查看发现,项目引用的DocumentFile是V4包里面的,不会吧google官方的bug还推荐我们使用?那就只能测试一下androidx咯,项目引用替换成androidx发现还是不行,然后继续回到之前说明的bug部分,新的androidx下的DocumentFile引用包修复是1.0.1版本,好吧继续引用一下1.0.1版本测试,果然。可行
厉害了,我的哥。这尼玛我项目是不能转成androidx包引用的,老难题啊,继续深入,想对比一下V4包下面DocumentFile的源码和androidx 1.0.1的源码对比一下,发现比较难找V4下的源码,就直接拿androidx代码到项目替换了V4源码,测试了一波,可行。继续搬...
下面也贴一下androidx下DocumentFile源码的下载地址:
https://download.csdn.net/download/Rookie_or_beginner/12084721
第二个坑: 沙盒设配本来呢,只需要判断api是否小于29,就可以区分是否适配分区的,但是google官方硬是弄了一个requestLegacyExternalStorage暂停沙盒分区使用旧分区的东西出来,那样子单单判断api是否小于29已经不能满足条件了,清单文件里面暂时停用沙盒分区 requestLegacyExternalStorage =true,好吧,适配的时候判Environment.isExternalStorageLegacy()通过返回状态确定是否开启沙盒分区,然后我测试了无论清单文件requestLegacyExternalStorage是设置了true或者是false,乃至删除了requestLegacyExternalStorage属性,都是返回false,我擦,又是坑爹啊,难道google推荐的东西都是坑爹么?继续搜索资料找到一篇博客 连接:https://www.jianshu.com/p/418180d7e195
说apk安装时,会根据requestLegacyExternalStorage 属性来同事storage权限变化,我擦,脑子一闪,又是一个坑啊,apk安装的时候就进行权限处理,我擦果断卸载app,重装测试一波果然可以了,代码如下:
public static boolean currenVersionLessThan29(){
boolean flag = true;
//如果本身是大于等于 29 并且开启沙盒 则返回false 走适配沙盒分支
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q &&
!isExternalStorageLegacy()) {
flag = false;
}
return flag;
}
/**
* @return
*/
private static boolean isExternalStorageLegacy(){
return Environment.isExternalStorageLegacy();
}
测试了清单文件添加了没有添加requestLegacyExternalStorage 属性前 Environment.isExternalStorageLegacy()方法获取出来的是false, 添加了requestLegacyExternalStorage = true 之后Environment.isExternalStorageLegacy()获取出来的是true,证明是可以的。但是不能添加之后在删除requestLegacyExternalStorage = true属性,因为Environment.isExternalStorageLegacy()获取出来还是true。
最后还是要感谢写我同事大佬聪,此间适配可是主力军,哈哈。希望能帮助到后面来排队挖坑的朋友哈