Storage Access Framework - How to append to a crea

2019-07-29 06:49发布

问题:

Using the answer in this post, I was able to use OPEN_CREATE_DOCUMENT as a folder picker in order for GDrive to appear in the list. The code in that answer creates an empty file. Now, I'm trying to append/write to that file. I tried using DocumentFile and openFileDescriptor. Both of them are failing. The latter with a permission denial exception saying that I need to add MANAGE_DOCUMENTS or use uripermission(). We cant use MANAGE_DOCUMENTS in the manifest since its a system permission and I haven't found a way to use the uripermission(). Here is the code:

 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()
        }

This is the intent:

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)

And this is the activity result:

            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()
                    }
                }
            }
        }

回答1:

Since this can take forever to get fixed, I ended up using Google Drive's REST API v3 in order to meet my needs. I added another entry in my app's menu inviting the user to choose a google drive path.

I created a new activity with a recyclerview which fetches all folders. I then added a button under each folder which allows the user to choose it as his/hers desired folder. I then save the folder ID in the sharedprefences on button click.

When the time comes to upload the file, I create a new API create() request and I use the saved folder id as the parent of the soon to be uploaded file.

Works pretty well but I didn't like the fact that I needed a second entry in the settings and that I needed 3 days to code all this from scratch.