Creating a writeable DocumentFile from URI

廉价感情. 提交于 2020-01-24 19:44:05

问题


I'm trying to adapt a File-based document system to something using DocumentFile in order to allow external storage read/write access on API >= 29.

I get the user to select the SD card root using Intent.ACTION_OPEN_DOCUMENT_TREE, and I get back a Uri as expected, which I can then handle using:

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

I can browse successfully through the external storage contents up to the selected root. All good.

But what I need to be able to do is write an arbitrary file in the chosen (sub)folder, and that's where I'm running into problems.

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

Except on the openOutputStream() call I get:

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

That's slightly confusing to me, but the "file not found" part suggests I might need to create the blank output file first, so I try that, like:

    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);

I get a 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)

Which doesn't make sense to me, since the tree should be writeable.

For what it's worth, the Uri I get back from Intent.ACTION_OPEN_DOCUMENT_TREE looks like this:

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

Interestingly, when I use that Uri to create a DocumentFile object to browse, using documentFile = DocumentFile.fromTreeUri(context, uri), then documentFile.getURI().toString() looks like:

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

i.e., it's had something appended to the end of it.

Then, I descend into what should be a writeable folder (like "Download"), and try creating a writeable file as described above. The "Download" folder gets the Uri:

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

and the Uri I'm using for toPath, above, is then:

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

which leads to the problems described previously trying to create it.

I haven't actually found any decent information about writing an arbitrary file under Storage Access Framework restrictions.

What am I doing wrong? Thanks. :)


回答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();

Use createFile() for a writable file.



来源:https://stackoverflow.com/questions/59189631/creating-a-writeable-documentfile-from-uri

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!