问题描述
我正在尝试使用 DocumentsContract.copyDocument(ContentResolver,Uri,Uri) 在 Android 中使用 SAF 框架复制文档,但这不起作用,android 返回错误“无法复制文档”。
通过缩小问题的范围,该文档上的 FLAG_SUPPORTS_copY
关闭(根据 DocumentsContract.Document#COLUMN_FLAGS)
(COLUMN_FLAGS 值是十进制的 326)。所以这解释了错误。
但是允许移动文档(标志 FLAG_SUPPORTS_MOVE
on)并且在调用 DocumentsContract.moveDocument(ContentResolver,Uri)
已通过 Intent.ACTION_OPEN_DOCUMENT_TREE
授予对文档树(驱动器的根目录和 DCIM 文件夹)的访问权限
为什么文档的 FLAG_SUPPORTS_copY
设置为 false?我错过了什么吗?
注意:我相信我满足了这篇文章中的要求https://stackoverflow.com/a/58147682/15401262
谢谢
代码(java)
// docFilesToProcess if of type "DocumentFile[]" and contains "regular files,like images" (not directories).
// Create destination dir
Uri destUri = DocumentsContract.createDocument(this.getContentResolver(),docFilesToProcess[i].getParentFile().getUri(),DocumentsContract.Document.MIME_TYPE_DIR,"destDir");
Log.i("M","destUri: "+ destUri.toString());
// Create document
Uri docToMove = DocumentsContract.createDocument(this.getContentResolver(),"text/plain","text");
Log.i("M","docToMove: "+ docToMove.toString());
// copy document
DocumentsContract.copyDocument(this.getContentResolver(),docToMove,destUri);
I/M: destUri: content://com.android.externalstorage.documents/tree/primary%3ADCIM/document/primary%3ADCIM%2FdestDir
I/M: docToMove: content://com.android.externalstorage.documents/tree/primary%3ADCIM/document/primary%3ADCIM%2Ftext.txt
W/DocumentsContract: Failed to copy document
java.lang.UnsupportedOperationException: copy not supported
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:172)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140)
at android.content.ContentProviderProxy.call(ContentProviderNative.java:658)
at android.content.ContentResolver.call(ContentResolver.java:2042)
at android.provider.DocumentsContract.copyDocument(DocumentsContract.java:1442)
at com.example.exifthumbnailadder.MainActivity.addThumbs(MainActivity.java:1036)
at java.lang.reflect.Method.invoke(Native Method)
持久权限请求
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.addFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION
| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
| Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
解决方法
一般来说,您永远不能依赖任何 SAF 提供程序来实现任何可选功能。您应该检查该功能是否受支持,如果不支持,您应该制定可行的后备计划。
ContentResolver cr = getContentResolver();
if((flags & FLAG_SUPPORTS_MOVE) == FLAG_SUPPORTS_MOVE)
Uri newDoc = DocumentsContract.copyDocument(cr,docToCopy,destDir);
else {
Uri newDoc = DocumentsContract.createDocument(cr,destDir,mimeType,name);
manuallyCopyBytes(docToCopy,newDoc);
}
给提供商一个机会去做这件事很重要,因为像 Google Drive 这样的东西可能能够在设备和服务器上分别执行复制,而不是在设备上复制它然后必须上传整个再次发送到服务器。