一、Android存储权限
Android存储权限是指应用程序可以访问设备存储空间和SD卡上的文件。
在Android系统中,将存储权限划分为:READ_EXTERNAL_STORAGE
、WRITE_EXTERNAL_STORAGE
。
READ_EXTERNAL_STORAGE
是指访问设备存储空间和SD卡上的文件的权限;WRITE_EXTERNAL_STORAGE
是指向设备存储空间和SD卡上写入文件的权限。
二、Android存储权限申请
在Android6.0及以上版本中,应用程序需要在运行时动态获取权限,否则将无法获取存储空间和SD卡上的文件。在申请权限前,需要先检查权限是否已经被授予,然后再申请权限。
以下是检查和申请SD卡权限的代码示例:
// 检查权限是否已经被授予 if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // 申请权限 ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, requestCode); } else { // 已经授予权限,可以进行操作 }
三、Android存储权限授权
当应用程序发起存储空间或者SD卡上的文件读或写请求时,会弹出授权对话框,询问用户是否授权该操作。
在用户做出授权选择后,会回调函数onRequestPermissionsResult
,可以在该函数中处理用户的授权选择。
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case REQUEST_CODE_STORAGE: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 用户已经授予权限,可以进行操作 } else { // 用户拒绝授权,无法进行操作 Toast.makeText(MainActivity.this, "无法获取存储权限,操作无法完成", Toast.LENGTH_LONG).show(); } break; } }
四、Android存储权限源码分析
在Android系统中,存储权限授权的具体实现是在PackageManagerService
中,该类实现了应用程序管理服务,提供了应用程序安装、卸载、权限管理等功能。
存储权限的授权过程是通过该服务中的grantPermissionsLPw
方法实现的。在该方法中,会先对应用程序的权限进行验证,然后再向用户发起授权请求。
private boolean grantPermissionsLPw(PackageParser.Package pkg, boolean replace, int userId, int[] gpFlags, String[] grantedPermissions, LongSparseArraypermsState) { // 先验证权限是否合法 final boolean allowedSig = checkPackageSignature(pkg); // ... // 获取对应权限后,向用户发起授权请求 if (delta != 0) { int flags = ((delta & PackageManager.FLAG_PERMISSION_REQUESTED) != 0) ? 0 : PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT; if (DEBUG_INSTALL) { Slog.d(TAG, "Auto-granting " + p.perm.info.getName() + " permission to default"); } p.granted = true; IntArray userIds = p.userId == UserHandle.USER_ALL ? pkg.getIntArrayInstallDuring() : new IntArray(); userIds.add(p.userId); if (!grantRuntimePermissionsLPw(pkg, p.perm, flags, allowedSig, userIds.toArray(), gpFlags, permsState)) { return false; } changed = true; } // ... return true; }
五、Android获取存储权限
在获取存储权限前,需要先检查应用程序是否已经被授予了相应的权限。
以下是检查存储权限和获取存储权限的示例代码:
// 检查权限是否已经被授予 if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // 申请权限 ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, requestCode); } else { // 已经授予权限,可以进行操作 } // 获取存储权限 Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); Uri uri = Uri.fromParts("package", context.getApplicationContext().getPackageName(), null); intent.setData(uri); context.startActivity(intent);
六、Android 11 存储权限
在Android11及以上版本中,存储权限的授权方式发生了变化:
- 应用程序不能访问外部存储中其他应用程序的存储空间。
- 应用程序只能在应用自己的私有目录中创建文件,无法在外部存储中创建文件。
- 应用程序需要在清单文件中声明访问外部存储空间的权限,否则不能获取外部存储权限。
以下是在Android11以上版本中获取存储权限的示例代码:
if (Environment.isExternalStorageManager()) { // 已经授予访问外部存储权限,可以进行操作 } else { Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); Uri uri = Uri.fromParts("package", context.getApplicationContext().getPackageName(), null); intent.setData(uri); context.startActivity(intent); }
七、Android 13 存储权限
在Android13中,存储权限的授权方式发生了进一步的变化:
- 应用程序需要在清单文件中声明
MANAGE_EXTERNAL_STORAGE
权限才能申请访问外部存储空间的权限。 - 如果应用程序未在清单文件中声明该权限,则无法使用申请访问外部存储空间的权限。
以下是在Android13版本中获取存储权限的示例代码:
// 检查是否授权访问外部存储空间 if (Environment.isExternalStorageManager()) { // 已经授权访问外部存储空间,可以进行操作 } else { Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); Uri uri = Uri.fromParts("package", context.getApplicationContext().getPackageName(), null); intent.setData(uri); context.startActivity(intent); }
八、Android存储数据的方法选取
在Android系统中,存储数据的方法有很多种,包括以下几种:
- 文件系统:通过文件系统读写文件。
- Shared Preferences:通过SharedPreferences保存数据。
- SQLite数据库:通过SQLite数据库保存数据。
- Content Providers:通过Content Providers共享数据。
- 网络存储:通过网络存储数据。
根据实际需求,选取相应的数据存储方式。