存储访问框架 - 如何使用其 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 天时间从头开始编写所有这些代码。