Android11分区存储下调用moveDocument移动DocumentFile报无效URI错误
问题原因
该问题确实是Uri生成环节导致的。DocumentsContract.moveDocument 属于SAF框架下的接口,要求传入的所有Uri(源Uri、源父目录Uri、目标父目录Uri)都必须是SAF体系下的content://类型Uri,你通过DocumentFile.fromFile(outputFolder).getUri()得到的是file://开头的Uri,SAF的ContentProvider无法识别该类型的Uri,因此直接抛出IllegalArgumentException异常。
可行解决方案
- 方案1:直接使用Java IO操作实现移动
你目标目录是Context.getExternalMediaDirs返回的应用专属目录,本身已拥有读写权限,如果源DocumentFile对应的文件你也有直接读写权限,直接使用File的renameTo方法,或者先复制流再删除源文件实现移动,完全不需要调用SAF接口,兼容性最好。 - 方案2:将目标目录转换为SAF认可的
content://类型Uri
因为目标目录处于外部媒体分区,你可以通过MediaStore查询对应路径的content://Uri:
Uri targetContentUri = null; Cursor cursor = getContentResolver().query( MediaStore.Files.getContentUri("external"), new String[]{MediaStore.Files.FileColumns._ID}, MediaStore.Files.FileColumns.DATA + "=?", new String[]{outputFolder.getAbsolutePath()}, null ); if (cursor != null && cursor.moveToFirst()) { long id = cursor.getLong(0); targetContentUri = MediaStore.Files.getContentUri("external", id); cursor.close(); }
拿到targetContentUri之后再传入moveDocument方法即可。
- 方案3:跨Document Provider场景的通用兼容方案
moveDocument仅支持同一个文档提供方下的Uri移动,如果源文件Uri和目标Uri不属于同一个提供方,接口本身就不支持移动,此时直接打开源DocumentFile的输入流,在目标目录创建新文件写入流,写入完成后删除源文件,等效实现移动逻辑。
内容的提问来源于stack exchange,提问作者Nicola Beghin
相关产品推荐
相关产品推荐

