Android 10使用Files.move重命名文件遇权限拒绝异常求助
Android 10下Files.move重命名文件权限拒绝问题解决
问题根源
Android 10引入的Scoped Storage机制会限制外部存储访问,即便配置了requestLegacyExternalStorage=true,也可能因为权限申请不完整、无效权限干扰、Files.move参数缺失等原因触发权限拒绝。
分步解决
1. 删除无用权限
Manifest里的READ_INTERNAL_STORAGE和WRITE_INTERNAL_STORAGE是针对系统内部存储的权限,对外部存储操作完全无效,直接移除:
<!-- 删掉这两行无效权限 --> <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
2. 确认Legacy存储配置位置
requestLegacyExternalStorage=true必须放在<application>标签内声明,写在Manifest根节点不会生效:
<application ... android:requestLegacyExternalStorage="true" <!-- android:requestRawExternalStorageAccess="true" 仅Android 13+需要,Android 10可忽略 --> > ... </application>
3. 动态申请存储权限
Android 6.0及以上版本,仅在Manifest声明权限不够,必须动态申请WRITE_EXTERNAL_STORAGE:
// 先检查权限是否已授予 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // 弹出权限申请对话框 ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 1001 // 自定义请求码 ) }
注意:必须等用户同意权限后,再执行文件重命名操作。
4. 修复Files.move调用逻辑
默认情况下,若目标文件已存在,Files.move会报错,添加REPLACE_EXISTING选项可覆盖已有文件,同时确保路径合法:
try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // 添加覆盖选项,避免目标文件存在时操作失败 Files.move(src, dest, StandardCopyOption.REPLACE_EXISTING) } println("Renaming succeeded") } catch (e: IOException) { e.printStackTrace() }
5. 额外检查项
- 确认
songItem.realUri是纯文件路径(如/storage/emulated/0/Music/xxx.mp3),而非content://开头的内容Uri; - 若目标路径的父目录不存在,需先创建目录:
val destParent = dest.parent if (destParent != null && !Files.exists(destParent)) { Files.createDirectories(destParent) }
修改后的完整权限配置
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> <application ... android:requestLegacyExternalStorage="true"> ... </application>
内容的提问来源于stack exchange,提问作者UserAndroidDeveloper
相关产品推荐
相关产品推荐

