存储访问框架 - 如何使用其 URI 附加到已创建的文件?
Storage Access Framework - How to append to a created file using its URI?
使用 post 中的答案,我能够使用 OPEN_CREATE_DOCUMENT 作为文件夹选择器,以便 GDrive 出现在列表中。该答案中的代码创建了一个空文件。现在,我正在尝试 append/write 到该文件。我尝试使用 DocumentFile 和 openFileDescriptor。他们两个都失败了。后者带有拒绝权限异常,表示我需要添加 MANAGE_DOCUMENTS 或
使用 uripermission()。我们不能在清单中使用 MANAGE_DOCUMENTS,因为它是系统许可,而且我还没有找到使用 uripermission() 的方法。这是代码:
var new_file = DocumentsContract.createDocument(context.contentResolver ,path,"audio/mp3",file)
contentresolve.openFileDescriptor(new_file, "w")?.use {
val pathToNewFile = FileOutputStream(it.fileDescriptor)
val inFile = context.openFileInput(file).readBytes()
context.openFileOutput(file, Context.MODE_PRIVATE).use {
pathToNewFile.write(inFile)
}
File(absolutePath + File.separator + file).delete()
}
这是意图:
folderPicker = Intent(Intent.ACTION_CREATE_DOCUMENT)
folderPicker.addFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
or Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
)
folderPicker.setType("vnd.android.document/directory")
startActivityForResult(folderPicker, READ_REQUEST_BY_USER)
这是 activity 结果:
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
super.onActivityResult(requestCode, resultCode, resultData)
if (requestCode == READ_REQUEST_BY_USER && resultCode == Activity.RESULT_OK) {
resultData?.data?.also { uri ->
val takeFlags: Int = folderPicker.flags and (Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
activity!!.contentResolver!!.persistedUriPermissions.forEach {
activity!!.contentResolver!!.releasePersistableUriPermission(it.uri, takeFlags)
}
activity!!.contentResolver!!.takePersistableUriPermission(uri, takeFlags)
val sharedPref = PreferenceManager.getDefaultSharedPreferences(activity?.baseContext)
with (sharedPref.edit()) {
putString("savePathURI", uri.toString())
putString("saveAuthority", uri.authority)
commit()
}
}
}
}
由于这可能需要很长时间才能修复,所以我最终使用了 Google Drive's REST API v3 来满足我的需求。我在我的应用程序菜单中添加了另一个条目,邀请用户选择 google 驱动器路径。
我创建了一个新的 activity,其中包含一个可获取所有文件夹的回收视图。然后我在每个文件夹下添加了一个按钮,允许用户选择它作为 his/hers 所需的文件夹。然后我在单击按钮时将文件夹 ID 保存在 sharedprefences 中。
当需要上传文件时,我创建了一个新的 API create() 请求,并将保存的文件夹 ID 作为即将上传文件的父级。
工作得很好,但我不喜欢这样的事实,我需要在设置中输入第二个条目,而且我需要 3 天时间从头开始编写所有这些代码。
使用
var new_file = DocumentsContract.createDocument(context.contentResolver ,path,"audio/mp3",file)
contentresolve.openFileDescriptor(new_file, "w")?.use {
val pathToNewFile = FileOutputStream(it.fileDescriptor)
val inFile = context.openFileInput(file).readBytes()
context.openFileOutput(file, Context.MODE_PRIVATE).use {
pathToNewFile.write(inFile)
}
File(absolutePath + File.separator + file).delete()
}
这是意图:
folderPicker = Intent(Intent.ACTION_CREATE_DOCUMENT)
folderPicker.addFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
or Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
)
folderPicker.setType("vnd.android.document/directory")
startActivityForResult(folderPicker, READ_REQUEST_BY_USER)
这是 activity 结果:
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
super.onActivityResult(requestCode, resultCode, resultData)
if (requestCode == READ_REQUEST_BY_USER && resultCode == Activity.RESULT_OK) {
resultData?.data?.also { uri ->
val takeFlags: Int = folderPicker.flags and (Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
activity!!.contentResolver!!.persistedUriPermissions.forEach {
activity!!.contentResolver!!.releasePersistableUriPermission(it.uri, takeFlags)
}
activity!!.contentResolver!!.takePersistableUriPermission(uri, takeFlags)
val sharedPref = PreferenceManager.getDefaultSharedPreferences(activity?.baseContext)
with (sharedPref.edit()) {
putString("savePathURI", uri.toString())
putString("saveAuthority", uri.authority)
commit()
}
}
}
}
由于这可能需要很长时间才能修复,所以我最终使用了 Google Drive's REST API v3 来满足我的需求。我在我的应用程序菜单中添加了另一个条目,邀请用户选择 google 驱动器路径。
我创建了一个新的 activity,其中包含一个可获取所有文件夹的回收视图。然后我在每个文件夹下添加了一个按钮,允许用户选择它作为 his/hers 所需的文件夹。然后我在单击按钮时将文件夹 ID 保存在 sharedprefences 中。
当需要上传文件时,我创建了一个新的 API create() 请求,并将保存的文件夹 ID 作为即将上传文件的父级。
工作得很好,但我不喜欢这样的事实,我需要在设置中输入第二个条目,而且我需要 3 天时间从头开始编写所有这些代码。