android11怎么访问data目录,android的data文件夹

作者:GrayMonkey链接:https://www.jianshu.com/p/d02bc6266198声明:本文已获GrayMonkey授权发表,转发等请联系原作者授权
前言Android R上分区存储的限制得到进一步加强,无论APP的targetsdkversion是多少,都将无法访问Android/data和Android/obb这二个应用私有目录 。这无疑对会部分APP的业务场景及用户体验造成冲击,典型的如下
文件管理类软件:微信、QQ传输的文件无法展示给用户以便捷使用垃圾清理类软件:清理缓存功能受阻“你有你的张良计,我有我的过墙梯” , 现市面上文件管理类软件(如MT管理器)已解决上述系统限制,本文将浅析其实现方案,并主要分析以下2个问题:
SAF是通过何种方式访问文件系统的,MediaStore API ? File API ? Native Code ?SAF为何能访问Android/data目录实现方案其实现方案很简单,就是通过Intent ACTION_OPEN_DOCUMENT_TREE,启动SAF让用户授权访问Android/data目录,属于官方公开的方法 。
前提是APP的targetsdkversion要小于30 。

android11怎么访问data目录,android的data文件夹

文章插图
摘自官方文档
android11怎么访问data目录,android的data文件夹

文章插图
摘自官方文档
文档链接:
https://developer.android.com/about/versions/11/privacy/storage#file-directory-restrictionshttps://developer.android.com/training/data-storage/shared/documents-files#grant-access-directory基本使用通过Intent启动SAF授权界面 , 注意URI的百分号编解码(:和/),别随意替换,否则SAF无法导航到Android/data目录@TargetApi(26)private void requestAccessAndroidData(Activity activity){try {Uri uri = Uri.parse("content://com.android.externalstorage.documents/document/primary:Android/data");Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, uri);//flag看实际业务需要可再补充intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION| Intent.FLAG_GRANT_WRITE_URI_PERMISSION| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);activity.startActivityForResult(intent, 6666);} catch (Exception e) {e.printStackTrace();}}
android11怎么访问data目录,android的data文件夹

文章插图
授权申请
在用户同意授权后,持久化uri权限(否则关机重启或授权界面finish后 , APP就无权限访问了),并只能通过DocumentFile进行业务操作 , File API操作是无效的 , 此授权只是授权uri操作,并未授权文件系统,后续章节有说明 。implementation "androidx.documentfile:documentfile:1.0.1"@Overrideprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);switch (requestCode) {case 6666:if (resultCode == Activity.RESULT_OK) {//persist urigetContentResolver().takePersistableUriPermission(data.getData(),Intent.FLAG_GRANT_READ_URI_PERMISSION| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);//now use DocumentFile to do some file opDocumentFile documentFile = DocumentFile.fromTreeUri(this, data.getData());DocumentFile[] files = documentFile.listFiles();......}break;default:break;}}注意这个授权用户是可以撤回的 , 通过点击应用信息界面的存储,就会看到撤回界面,所以业务需要去动态判断 public boolean isGrantAndroidData(Context context) {for (UriPermission persistedUriPermission : context.getContentResolver().getPersistedUriPermissions()) {if (persistedUriPermission.getUri().toString().equals("content://com.android.externalstorage.documents/tree/primary:Android/data")) {return true;}}return false;}
android11怎么访问data目录,android的data文件夹

文章插图
授权撤回
拓展通过前面二个章节,已经介绍了实现方案的基本使用,下面就该分析本文的亮点内容了