我正在尝试使js File-based 文
档系统适应某种js DocumentFile 用
途,以便允许外部存储对API> = 29的读/写访问。
我让用户使用来选择SD卡根目录js Intent.ACTION_OPEN_DOCUMENT_TREE ,
然后js Uri 按
预期方式返回a ,然后可以使用来处理:
```js
getContentResolver().takePersistableUriPermission(resultData.getData(), Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
我可以成功浏览外部存储内容直至所选根目录。都好。
但是我需要做的是在选择的(子)文件夹中写入一个任意文件,这就是我遇到问题的地方。
```js
DocumentFile file = DocumentFile.fromSingleUri(mContext, Uri.parse(toPath));
Uri uri = file.getUri();
FileOutputStream output = mContext.getContentResolver().openOutputStream(uri);
除了js 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);
我得到了```js java.io.IOException:
```js
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)
这对我来说没有意义,因为树应该是可写的。
对于它的价值,js Uri 我
从下面js Intent.ACTION_OPEN_DOCUMENT_TREE 看
起来像这样:
content://com.android.externalstorage.documents/tree/0B07-1910%3A
有趣的是,当我使用Uri来创建DocumentFile要浏览的对象时,使用documentFile = js DocumentFile.fromTreeUri(context, uri) ,
则js documentFile.getURI().toString() 如
下所示:
content://com.android.externalstorage.documents/tree/0B07-1910%3A/document/0B07-1910%3A
即,它的末尾附加了一些内容。
然后,我进入应为可写文件夹的位置(如“下载”),并尝试如上所述创建可写文件。“下载”文件夹获取js Uri :
content://com.android.externalstorage.documents/tree/0B07-1910%3A/document/0B07-1910%3ADownload
然后js Uri 我
在js toPath 上
面用于的是:
content://com.android.externalstorage.documents/tree/0B07-1910%3A/document/0B07-1910%3ADownload/Testing.tmp
这会导致前面描述的尝试创建它的问题。
在Storage Access Framework限制下,我实际上尚未找到有关写入任意文件的任何体面信息。
我究竟做错了什么?谢谢。:)
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
遇到这个问题,看起来你已经正确地获取了对外部存储的读写权限,并且能够浏览文件系统。问题在于尝试在特定目录下创建文件时遇到了“Read-only file system”错误,即使你已经获得了写入权限。这可能是由于几个原因造成的:
路径处理问题:确保toPath
变量正确指向你想要创建文件的具体位置,并且格式无误。从你的描述来看,你似乎是在尝试使用一个表示文件夹的Uri来创建新文件,而不是直接指向一个具体的文件名。确保你在调用createFile
方法时,传递的是目标文件的名称,而非文件夹路径。
权限问题:尽管你已经通过takePersistableUriPermission
获取了权限,但某些Android版本或设备可能对特定目录(如"Download")有额外的安全限制。确认SD卡上的目标目录确实允许应用写入。你可以尝试在不同的目录下创建文件,看是否能成功,以排除特定目录的问题。
使用DocumentFile API:你提到使用了DocumentFile.fromSingleUri
和DocumentFile.fromTreeUri
,但在创建文件时应该直接利用DocumentFile
类的方法。正确的做法是先通过fromTreeUri
获取到根目录的DocumentFile
实例,然后使用其方法来创建子文件或目录,而不是手动拼接Uri字符串。
修正后的代码示例:
// 获取根目录的DocumentFile实例
DocumentFile root = DocumentFile.fromTreeUri(mContext, Uri.parse("content://com.android.externalstorage.documents/tree/0B07-1910:"));
// 导航到你想要的子目录,例如"Download"
DocumentFile downloadFolder = root.findFile("Download");
if (downloadFolder == null) {
// 如果"Download"不存在,则尝试创建它
downloadFolder = root.createDirectory("Download");
}
// 在"Download"目录下创建文件
String fileName = "Testing.tmp";
DocumentFile newFile = downloadFolder.createFile("*/*", fileName); // "*/*" 表示任意MIME类型
if (newFile != null) {
// 文件创建成功,现在可以打开输出流写入数据
OutputStream output = mContext.getContentResolver().openOutputStream(newFile.getUri());
if (output != null) {
// 写入数据到output...
output.close();
}
} else {
// 创建文件失败
}
这段代码首先通过树状Uri获取根目录的DocumentFile
实例,然后查找或创建"Download"目录,并在其中创建文件。这样可以避免手动处理Uri字符串导致的错误,并确保操作符合Storage Access Framework的要求。