Android 11代码实现文件夹间文件移动的权限获取问题
Android 11 (API 32) 文件移动权限问题解决方案
核心问题分析
Android 11 开始强制启用分区存储,原有的 WRITE_EXTERNAL_STORAGE 权限在 API 29+ 完全失效;MANAGE_EXTERNAL_STORAGE 作为特殊权限,无法通过普通权限弹窗请求,必须引导用户到系统设置手动授予。同时你的权限校验逻辑未适配 Android 11+ 的权限规则,导致即便用户授予旧权限,仍会出现权限拒绝错误。
步骤1:修正权限配置与请求逻辑
1.1 更新 AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" /> <!-- 适配 Android 11+ 的全存储访问权限,添加tools:ignore避免IDE警告 --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> <application <!-- Android 11+ 下 requestLegacyExternalStorage 无效,直接移除 --> ...> </application> </manifest>
1.2 适配权限校验方法
private static final int REQUEST_EXTERNAL_STORAGE = 1001; private static final int REQUEST_MANAGE_STORAGE = 1002; public static void verifyStoragePermissions(Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // Android 11+ 检查全存储访问权限 if (!Environment.isExternalStorageManager()) { Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); Uri uri = Uri.fromParts("package", activity.getPackageName(), null); intent.setData(uri); activity.startActivityForResult(intent, REQUEST_MANAGE_STORAGE); } } else { // Android 10及以下检查传统存储权限 int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); if (permission != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions( activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_EXTERNAL_STORAGE ); } } }
步骤2:优化文件移动代码
优先使用 File.renameTo() 方法(同一存储设备内移动效率远高于流复制),失败时再降级到流复制方案:
// 用File对象封装路径,避免字符串拼接错误 File inputFile = new File(inputPath, "file.txt"); File outputDir = new File(outputPath); // 创建目标目录 if (!outputDir.exists()) { boolean isDirCreated = outputDir.mkdirs(); Log.i("mkdirs result", String.valueOf(isDirCreated)); } File outputFile = new File(outputDir, "file.txt"); // 尝试快速移动 boolean isMoved = inputFile.renameTo(outputFile); if (!isMoved) { // 移动失败时用流复制 try (FileInputStream in = new FileInputStream(inputFile); FileOutputStream out = new FileOutputStream(outputFile)) { byte[] buffer = new byte[1024]; int readLen; while ((readLen = in.read(buffer)) != -1) { out.write(buffer, 0, readLen); } // 复制完成后删除原文件 inputFile.delete(); } catch (IOException e) { e.printStackTrace(); } }
关键注意事项
MANAGE_EXTERNAL_STORAGE是敏感权限,Google Play 仅允许文件管理器、备份类等特定类型应用使用该权限,非此类应用建议改用分区存储合规方案(如将文件放在应用专属目录)。- Android 11+ 下
requestLegacyExternalStorage="true"完全失效,无需保留。
内容的提问来源于stack exchange,提问作者Josh Hunter
相关产品推荐
相关产品推荐

