Android SAF,无法复制文件,未设置 FLAG_SUPPORTS_COPY [英] Android SAF, cannot copy file, FLAG_SUPPORTS_COPY not set

查看:48
本文介绍了Android SAF,无法复制文件,未设置 FLAG_SUPPORTS_COPY的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 DocumentsContract.copyDocument(ContentResolver, Uri, Uri) 但是这不起作用,android 返回错误Failed to复制文档".

I'm trying to copy a document with the SAF framework in Android by using DocumentsContract.copyDocument(ContentResolver, Uri, Uri) however this doesn't work, android returns error "Failed to copy document".

通过缩小问题的范围,该文档上的 FLAG_SUPPORTS_COPY 关闭(根据 DocumentsContract.Document#COLUMN_FLAGS)(COLUMN_FLAGS 值是十进制的 326).所以这解释了错误.

By narrowing the issue down, the FLAG_SUPPORTS_COPY is off on that document (according to DocumentsContract.Document#COLUMN_FLAGS) (COLUMN_FLAGS value is 326 in decimal). So this explains the error.

但是允许移动文档(标志 FLAG_SUPPORTS_MOVEon)并且在调用 DocumentsContract.moveDocument(ContentResolver, Uri, Uri, Uri) 时确实移动了文件)

However moving the document is allowed (flag FLAG_SUPPORTS_MOVE is on) and file is really moved when calling DocumentsContract.moveDocument(ContentResolver, Uri, Uri, Uri)

已通过 Intent.ACTION_OPEN_DOCUMENT_TREE

为什么文档的 FLAG_SUPPORTS_COPY 设置为 false?我错过了什么吗?

Why is the FLAG_SUPPORTS_COPY set to false for the Document ? Am I missing something ?

注意:我相信我满足了这篇文章中的要求https://stackoverflow.com/a/58147682/15401262

Note: I believe I fullfill the requirements from this post 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(), docFilesToProcess[i].getParentFile().getUri(), "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 提供程序来实现任何可选功能.您应该检查该功能是否受支持,如果不支持,您应该制定可行的后备计划.

In general, you cannot ever rely on any SAF provider to implement any optional feature. You should check whether the feature is supported, and you should have a viable fallback plan for when it is not.

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 这样的东西可能能够在设备和服务器上分别执行复制,而不是在设备上复制它然后必须上传整个再次发送到服务器.

It's important to give the provider a chance to do it, because something like Google Drive may be able to perform the copy separately on the device and on the server, instead of copying it on the device and then having to upload the whole thing to the server again.

这篇关于Android SAF,无法复制文件,未设置 FLAG_SUPPORTS_COPY的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆