2

我正在尝试使File基于 - 的文档系统适应使用的东西DocumentFile,以便允许对 API >= 29 的外部存储读/写访问。

我让用户使用 选择SD卡根目录Intent.ACTION_OPEN_DOCUMENT_TREE,然后按预期返回 a Uri,然后可以使用以下方法处理:

    getContentResolver().takePersistableUriPermission(resultData.getData(),
                            Intent.FLAG_GRANT_READ_URI_PERMISSION
                            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

我可以成功浏览外部存储内容,直到选定的根目录。都好。

但是我需要做的是在所选(子)文件夹中写入一个任意文件,这就是我遇到问题的地方。

    DocumentFile file = DocumentFile.fromSingleUri(mContext, Uri.parse(toPath));
    Uri uri = file.getUri();
    FileOutputStream output = mContext.getContentResolver().openOutputStream(uri);

除了openOutputStream()我接到的电话:

java.io.FileNotFoundException: Failed to open for writing: java.io.FileNotFoundException: open failed: EISDIR (Is a directory)

这让我有点困惑,但“找不到文件”部分表明我可能需要先创建空白输出文件,所以我尝试这样做,例如:

    DocumentFile file = DocumentFile.fromSingleUri(mContext, Uri.parse(toPath));
    Uri uri = file.getUri();
    if (file == null) {
        return false;
    }
    if (file.exists()) {
        file.delete();
    }
    DocumentFile.fromTreeUri(mContext, Uri.parse(getParentPath(toPath))).createFile("", uri.getLastPathSegment());
    FileOutputStream output = mContext.getContentResolver().openOutputStream(uri);

我得到一个java.io.IOException

    java.lang.IllegalStateException: Failed to touch /mnt/media_rw/0B07-1910/Testing.tmp: java.io.IOException: Read-only file system
    at android.os.Parcel.createException(Parcel.java:2079)
    at android.os.Parcel.readException(Parcel.java:2039)
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:188)
    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.createDocument(DocumentsContract.java:1327)
    at androidx.documentfile.provider.TreeDocumentFile.createFile(TreeDocumentFile.java:53)
    at androidx.documentfile.provider.TreeDocumentFile.createFile(TreeDocumentFile.java:45)

这对我来说没有意义,因为树应该是可写的。

对于它的价值,Uri我从Intent.ACTION_OPEN_DOCUMENT_TREE看起来像这样回来:

content://com.android.externalstorage.documents/tree/0B07-1910%3A

有趣的是,当我使用它Uri来创建DocumentFile要浏览的对象时,使用documentFile = DocumentFile.fromTreeUri(context, uri),然后documentFile.getURI().toString()看起来像:

content://com.android.externalstorage.documents/tree/0B07-1910%3A/document/0B07-1910%3A

即,它的末尾附加了一些东西。

然后,我进入应该是可写文件夹(如“下载”),并尝试如上所述创建可写文件。“下载”文件夹获取Uri

content://com.android.externalstorage.documents/tree/0B07-1910%3A/document/0B07-1910%3ADownload

然后Uri我使用的 fortoPath是:

content://com.android.externalstorage.documents/tree/0B07-1910%3A/document/0B07-1910%3ADownload/Testing.tmp

这会导致前面描述的问题,试图创建它。

实际上,我还没有找到任何关于在存储访问框架限制下编写任意文件的体面信息。

我究竟做错了什么?谢谢。:)

4

1 回答 1

1
Uri uri = uri obtained from ACTION_OPEN_DOCUMENT_TREE

String folderName = "questions.59189631";

DocumentFile documentDir = DocumentFile.fromTreeUri(context, uri);

DocumentFile folder = documentDir.createDirectory(folderName);

return folder.getUri();

对可写文件使用 createFile()。

于 2019-12-05T14:25:23.183 回答