androidkotlinpdfuriandroid-contentprovider

Save File Selected from ACTION_OPEN_DOCUMENT to Variable or Create Copy to Local Storage


The Objective: Have the user select a pdf document, stored in Environment.DIRECTORY_DOWNLOADS, to merge with another programmatically created pdf.

What I've Tried:

  1. Saving the uri returned from ACTION_OPEN_DOCUMENT and getting File from this. However, the uri being stored is from the Content Provider content://com.android.providers.media.documents/document/document%3A1000013540 and not the format I expected so when I try to get the file from it, I get a "Does Not Exist" error.

  2. Copying the selected file from ACTION_OPEN_DOCUMENT to the downloads directory. I get a "No such file or directory" error with this.

         createTxtLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
    
         if (result.resultCode == Activity.RESULT_OK) {
             val uri: Uri? = result.data?.data
             val resolver = requireContext().contentResolver
             val outDest = FileOutputStream(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS  + "/Test.pdf"))
             val fi = FileInputStream(uri?.path)
             val origin = BufferedInputStream(fi)
             val out = BufferedOutputStream(outDest)
             try {
                 origin.copyTo(out, 1024)
                 println("hope this works")
             } catch (e: IOException) {
                 println("error output stream")
             }
         }
     }
    

Can anyone please provide assistance on what the correct way to do this is? I've been stuck for a couple days now.


Solution

  • To get an InputStream on a Uri that you got from ACTION_OPEN_DOCUMENT, call openInputStream() on a ContentResolver.

    Please bear in mind that ACTION_OPEN_DOCUMENT (and the rest of the Storage Access Framework) are not limited to the filesystem, so there is no way to convert a Uri to a File. Even if the Uri does point to something on the filesystem, you might not have rights to access it via the filesystem but do by using the Uri with ContentResolver.