简体   繁体   中英

How do I create files when all I have is an uri of a directory? (Persistable permission for the directory was granted by the Android user.)

I am trying to write and read files that are also visible and editable from a PC when the android device is connected to it via USB. These files might be created through the PC connection.

To achieve this I'm trying to take a persistable URI permission to a directory, and then create or read the files in that directory.

I am in the "proof of concept" phase.

Inside the MainActivity OnCreate method I have the following code:

startActivityForResult(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
    flags = Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
}, GET_PERSISTABLE_PERMISSION)

When I start te app, the directory picker pops up and I'm able to select a directory.

In MainActivity I also have:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if (requestCode == GET_PERSISTABLE_PERMISSION && resultCode == Activity.RESULT_OK) {
        val uri = data?.data!!
        val contentResolver = applicationContext.contentResolver
        val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
        contentResolver.takePersistableUriPermission(uri, takeFlags)

        val tmpFile = File(uri.path, "debugTestFile.txt")
        tmpFile.createNewFile()
        tmpFile.appendText("árvíztűrő tükörfúrógép\r\n")
    }
    super.onActivityResult(requestCode, resultCode, data)
}

Things I've tried:

  • uri.toString() instead of uri.path
  • flags = Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION when creating the intent
  • giving different directories on the Android device in the Downloads, Music, DCIM folders, when prompted by Android

Despite my best efforts, the tmpFile.createNewFile() line throws an exception with "No such file or directory" message.

    Process: hu.ibcs.android.scan, PID: 17309
    java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { dat=content://com.android.externalstorage.documents/tree/primary:Music/GVtest flg=0xc3 }} to activity {hu.ibcs.android.scan/hu.ibcs.android.scan.MainActivity}: java.io.IOException: No such file or directory
        at android.app.ActivityThread.deliverResults(ActivityThread.java:4846)
        at android.app.ActivityThread.handleSendResult(ActivityThread.java:4887)
        at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2017)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7397)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)
     Caused by: java.io.IOException: No such file or directory
        at java.io.UnixFileSystem.createFileExclusively0(Native Method)
        at java.io.UnixFileSystem.createFileExclusively(UnixFileSystem.java:317)
        at java.io.File.createNewFile(File.java:1008)
        at hu.ibcs.android.scan.MainActivity.onActivityResult(MainActivity.kt:106)
        at android.app.Activity.dispatchActivityResult(Activity.java:8135)
        at android.app.ActivityThread.deliverResults(ActivityThread.java:4839)

Big thanks to @blackapps for the suggestions!

I changed the code in MainActivity.onCreate to:

startActivityForResult(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE), GET_PERSISTABLE_PERMISSION)

and the code in MainActivity to:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if (requestCode == GET_PERSISTABLE_PERMISSION && resultCode == Activity.RESULT_OK) {
        val uri = data?.data!!
        val contentResolver = applicationContext.contentResolver
        val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
        contentResolver.takePersistableUriPermission(uri, takeFlags)

        val pickedDir = DocumentFile.fromTreeUri(this, uri)
        val tmpFile = pickedDir.createFile("text/csv", "debugTestFile")
        val out: OutputStream? = getContentResolver().openOutputStream(tmpFile!!.uri)
        out?.write(("\uFEFF" + "árvíztűrő tükörfúrógép\r\n").toByteArray()) // adding BOM to the start for Excel to recognize utf8
        out?.close()
    }
    super.onActivityResult(requestCode, resultCode, data)
}

It's working and it looks like I can move on from here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM