自律光 2021-06-08 17:42 采纳率: 100%
浏览 1538
已采纳

安卓11如何读取data目录下的文件?

 

  • 写回答

1条回答 默认 最新

  • 东海一闲人 2021-06-09 10:08
    关注

    来源:https://www.zhihu.com/question/420023759

    1.申请android/data的访问权限

    使用intent 跳转系统文件管理器到 android/data 并同意你的应用访问这个文件夹

    这里是代码

     Uri uri1 = Uri.parse("content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fdata");
                    Intent intent1 = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
                    intent1.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
                            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                            | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
                            | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
                    intent1.putExtra(DocumentsContract.EXTRA_INITIAL_URI, uri1);
                    startActivityForResult(intent1, 11);

    这里的url 是我自己在旧安卓使用文件管理器选择android/data返回的uri 同理 传递这个uri 给文件管理器 自然也会跳转到这文件夹 如果不传递uri 系统文件管理器仍然无法显示 android/data

    修改:这里的uri 在后续我发现在部分安卓11 无法正常跳转了 以下是解决方法

    使用DocumentFile.fromTreeUri这个方法 获得DocumentFile对象 然后再获取他的uri 传进去就行了 这样就能正常跳转uri 了

    如果授权完成 会是这样

    后续的检测是否授权android/data 就自行查看谷歌文档吧

    2.使用uri 访问 android/data 的文件

    如果你现在有一个文件的path 那么这样做可以转为可以访问的uri

    String[] paths = path.replaceAll("/storage/emulated/0/Android/data", "").split("/");
            StringBuilder stringBuilder = new StringBuilder("content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fdata/document/primary%3AAndroid%2Fdata");
            for (String p : paths) {
                if (p.length() == 0) continue;
                stringBuilder.append("%2F").append(p);
            }
            return Uri.parse(stringBuilder.toString());

    这个uri 是android/data里的文件的uri 那么现在你可以使用DocumenFile 访问这个文件

    具体的DocumentFile 用法可以谷歌下

    3.使用ContentResolver 访问文件

    如果你的对象是一个文件夹 并且你想要访问这文件夹的文件 那么可以使用ContentResolver.query这个方法

    DocumentsContract.buildChildDocumentsUriUsingTree(dirUri, DocumentsContract.getDocumentId(dirUri));

    使用这个把uri 转为 resolver 可处理的uri

    然后使用 query查询

    resolver.query(childrenUri, new String[]{DocumentsContract.Document.COLUMN_DOCUMENT_ID}, null, null, null);

    主要是为了获取DocumentId 用于获取子文件的uri

    这个方法是SQL 的方法 当然就可以使用SQL 的语句 可以自行谷歌这个文档

    这里是获取子文件的uri

    while (cursor.moveToNext()) {
                String documentId = cursor.getString(0);
                Uri uri = DocumentsContract.buildDocumentUriUsingTree(dirUri, documentId);
    }

    如果可以的话我建议 在此之前判断 resolver.query 返回的 cursor 对象是否是null

    这样子我们就再次获取了子文件的uri 了

    那么DocumentFile 就能再次派上了用场

    DocumentFile documentFile1=DocumentFile.fromSingleUri(context,uri);

    DocumentFile 为我们提供了判断是否是 文件夹 文件的方法

    如果是文件夹我们可以再次执行这样得循环 如果是文件 我们可以获取大小等

    由于清浊并不需要读取文件内容和修改内容 所以这两个怎么做 我并没有做了 当然谷歌的文档说了可以使用I/O 读取 就跟普通的File 操作没区别了到这

    4.末

    这种方法并不是新方法 只是在安卓11 可以用罢了 早在之前读取联系人等 就是用的这种方法 安卓5.0开始就有了这种读取方法 不过这种方法目前就我看来有一点问题 速度缓慢 容易出现问题 具体问题我已经遇到 在某种情况下会抛出各种exception 给你 当然就需要你catch 一下了

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上
  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来