Android11以上无法访问Android/data目录的解决方法
本文从Sky233’s Blog复制过来
前言
我最近在开发一个Android项目的时候,需要用到这个权限访问某个文件,但我在网络上没有找到一个很好且易懂的解决方法,因此写了这篇博文。
思路
在Android上有一个叫做SAF(Storage Access Framework)的储存访问框架
而这个框架的访问权限较高,可以直接访问Android/data目录
因此可以通过这个方式来访问Android/data目录
仅需通过这个框架来获取Android/data目录的权限即可访问目录
获取访问权限
如果手机安卓版本为Android10的时候,可以在AndroidManifest.xml中添加下列代码
android:requestLegacyExternalStorage="true"
以此禁用分区存储,但这在Android11及以上版本不起作用
所以需要使用SAF访问框架
REQUEST_CODE_FOR_DIR是一个int变量,为一个固定的数,用于回调
在onActivityResult回调方法中加入下列代码
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Uri uri;
if (requestCode == REQUEST_CODE_FOR_DIR && (uri = data.getData()) != null) {
getContentResolver().takePersistableUriPermission(uri, data.getFlags() & (
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION));
}
}
并合适的地方调用下面的代码
@RequiresApi(api = Build.VERSION_CODES.O)
public static void startFor(Activity activity) {
Uri uri = Uri.parse("content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fdata");
DocumentFile documentFile = DocumentFile.fromTreeUri(activity, uri);
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.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);
assert documentFile != null;
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, documentFile.getUri());
activity.startActivityForResult(intent, REQUEST_CODE_FOR_DIR);
}
这时会发现这样一个界面
当用户点击下方按钮时便会回调,并保存权限,以便下次使用
权限获取的部分到这里为止
读写文件
Google官方提供了一个工具类库Documentfile
我们可以通过这个类来操作文件,例如查看文件是否存在,删除文件和浏览目录
下面是添加类的方法
dependencies {
...
implementation 'androidx.documentfile:documentfile:1.0.1'
}
要使用这个库,我们需要创建一个uri,我这里提供一个方法可以转换path为uri
public static Uri pathToUri(String path) {
return Uri.parse("content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fdata/document/primary%3A" +path.replace("/storage/emulated/0/", "").replace("/", "%2F"));
}
通过这个方法,我们可以很快的转换为uri,我们这时可以操作文件了
例如删除文件:
DocumentFile documentFile = DocumentFile.fromSingleUri(this,Uri);
documentFile.delete();
但我们还是没有读写文件,因此我们需要另外一种方法,
例如我需要读取在Android/data目录下的某个txt文件
我只需要这样写:
String string = "";
InputStream inputStream = null;
try {
inputStream = context.getContentResolver().openInputStream( pathToUri(path););
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
FileInputStream fileInputStream = (FileInputStream) inputStream;
int length = fileInputStream.available();
byte[] buffer = new byte[length];
fileInputStream.read(buffer);
string = new String(buffer, 0, length, "UTF-8");
fileInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
总结
在Android11以上访问Android/data目录还是很简单的
Documentfile的用法可以参考Google的官方文档
用法也是比较简单,因为我的项目用不到太多,所以我就只研究了这点
希望能对你有帮助(/ω\)
相关文章
- 一个Java程序员对2011年的回顾
- 大数据发展历程
- Android高级进阶之路【一】Android中View绘制流程浅析
- 可信服务管理(Trusted Service Manager)介绍
- GIS应用|快速开发REST空间分析服务
- 未来十年微软长盛不衰的两项战略
- 领域驱动设计模式的收益与挑战
- cocos 3.0 一键打包android平台应该注意的细节
- 数智化时代,驱动企业转型升级的“三驾马车”是什么?
- 基于MINA构建高性能的NIO应用
- 使用Rainbond实现离线环境软件交付
- 工作流引擎 jBPM 5.2 发布
- 微信小程序Minium自动化测试(三)
- 桌面应用抢先体验,这次有点料!
- 甲骨文Java专利遭拒 起诉Android侵权受挫
- 云计算的应用领域及发展前景
- Java效率真的很低吗?Android为何要采用?
- Android高级进阶之路【二】十分钟彻底弄明白 View 事件分发机制
- 庖丁解牛之-Android平台RTSP|RTMP播放器设计
- 手机直付,超级方便