how to copy file and get Uri (with read permisssion) using android ResultLauncher in android 11

Issue

trying to get file(PDF) form internal storage to upload on server with the help of Android ResultLauncher API, getting Uri in result but I am unable to read that Uri. When trying to copy that file to my app’s scope directory with the help of result Uri, getting permission error on contentResolver.openInputStream(uri). this is the error:

Permission Denial: reading com.android.providers.media.MediaDocumentsProvider uri <my file uri>  requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs

How can I copy file in app’s scope directory? This is my ResultLauncher:

singleTypeResultLauncher 
            fragment.registerForActivityResult(ActivityResultContracts.GetContent()){
                    result ->
                result?.let{
                    val tempUri  Uri.parse(it.toString().replace("%3A", ":"))

                    val path  createCopyAndReturnRealPath(fragment.requireContext(), tempUri)
                }
            }

this is how I am launching:

singleTypeResultLauncher.launch("application/pdf")

this is method in with app is crashing:

crashing on val inputStream  contentResolver.openInputStream(uri)

fun createCopyAndReturnRealPath(context: Context, uri: Uri): String? {
        val contentResolver  context.contentResolver ?: return null
        val mimeType  getMimeType(context, uri).getSafe()
        val fileExt  "." + mimeType.substring(mimeType.indexOf('/') + 1)
        val filePath: String  (context.dataDir.absolutePath + File.separator
                + System.currentTimeMillis())
        val file  File(filePath)
        try {
            file.parentFile.mkdirs()
            file.createNewFile()
            val inputStream  contentResolver.openInputStream(uri) ?: return null //crashing here
            val outputStream: OutputStream  FileOutputStream(file)
            val buf  ByteArray(1024)
            var len: Int
            while (inputStream.read(buf).also { len  it } > 0) outputStream.write(buf, 0, len)
            outputStream.close()
            inputStream.close()
        } catch (ignore: IOException) {
            return null
        }
        return file.absolutePath
    }

using provider paths:

<paths>
    <external-path
        name"external"
        path"." />
    <external-files-path
        name"external_files"
        path"." />
    <cache-path
        name"cache"
        path"." />
    <external-cache-path
        name"external_cache"
        path"." />
    <files-path
        name"files"
        path"." />
</paths>

Solution

I am unable to read that Uri

You are not trying to read that Uri. You are trying to read a different Uri:

val tempUri  Uri.parse(it.toString().replace("%3A", ":"))

Replace that with:

val tempUri  it

…or, just remove tempUri entirely and use it directly.

trying to get file(PDF) form internal storage to upload on server

Note that you do not necessarily need to copy the content to upload it.

Answered By – CommonsWare

Leave a Comment