Android文件管理多版本适配

32 阅读2分钟

一:前言

随着Google对于隐私管理越来越严格,存储沙盒、动态权限、分区存储等设计陆续推出,Android11之后文件访问API有了明显的变化,现根据不同Android版本做适配,获取内部存储根目录。

二:版本变化

Android版本targetVersion说明
Android 6.023(Marshmallow)增加动态权限,在使用的地方再申请READ_EXTERNAL_STORAGE权限,同意之后即可访问
Android 1130(R)提出了分区存储概念,需要申请MANAGE_EXTERNAL_STORAGE权限,需要跳转到手机系统设置,让客户手动打开权限才可访问
Android 1231(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版本适配