一:前言
随着Google对于隐私管理越来越严格,存储沙盒、动态权限、分区存储等设计陆续推出,Android11之后文件访问API有了明显的变化,现根据不同Android版本做适配,获取内部存储根目录。
二:版本变化
Android版本 | targetVersion | 说明 |
---|---|---|
Android 6.0 | 23(Marshmallow) | 增加动态权限,在使用的地方再申请READ_EXTERNAL_STORAGE权限,同意之后即可访问 |
Android 11 | 30(R) | 提出了分区存储概念,需要申请MANAGE_EXTERNAL_STORAGE权限,需要跳转到手机系统设置,让客户手动打开权限才可访问 |
Android 12 | 31(S) | 同时拥有 MANAGE_EXTERNAL_STORAGE 权限和 QUERY_ALL_PACKAGES 权限(例如文件管理应用)的应用可以使用 getManageSpaceActivityIntent() 将用户转到其他应用的自定义空间管理活动 |
三:实施方案
3.1 Android 6.0 (Marshmallow)
// 1.AndroidManifest配置权限申明
<manifest ...>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application ...
//2.判断是否有READ_EXTERNAL_STORAGE权限
if (PackageManager.PERMISSION_GRANTED == ActivityCompat
.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE)) {
//已授权
} else {
//未授权
}
}
//3.未授权的情况下,弹框让客户同意隐私弹框(权限申请可以使用三方库,比原生的方式好用,本次演示使用原生方式)
ActivityCompat.requestPermissions(activity, String[] permissions, REQUEST_CODE));
//4.客户同意或拒绝后回调
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == REQUEST_CODE) {
for (int i = 0; i < permissions.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
//已授权
} else {
//未授权
}
}
}
}
//5.获取内部存储根目录
Environment.getExternalStorageDirectory()
3.2 Android 11 (R)
3.3 Android 12 (S)
在 Android 12(API 级别 31)及更高版本中,同时拥有 MANAGE_EXTERNAL_STORAGE 权限和 QUERY_ALL_PACKAGES 权限(例如文件管理应用)的应用可以使用 getManageSpaceActivityIntent() 将用户转到其他应用的自定义空间管理活动。
//1.基于6.0动态权限流程,申请MANAGE_EXTERNAL_STORAGE权限
//需要判断版本,否则低版本会崩溃
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// 判断是否授权
if (!Environment.isExternalStorageManager()) {
// 跳转到系统应用设置,需要客户手动授权
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
intent.data = Uri.fromParts("package", context.packageName, null)
context.startActivity(intent)
}
}
四: 问题
4.1 Environment.getExternalStorageDirectory()获取到内部存储的根目录之后,rootFile.listFiles()只能看到目录,看不到文件(txt、png等)
答:Android 11及以上只申请了READ_EXTERNAL_STORAGE,需要根据当前Android版本适配