Home > Blockchain >  How to use file picker in Android 11
How to use file picker in Android 11

Time:11-30

In my application I want user can open file picker and select file.
I write below codes, but after clicking up upload show me error and application crashed!
But below of android 11 everything is OK and not any problem!
I write below codes in Activity:

class AddMaangramActivity : BaseActivity() {

    private lateinit var requestBody: RequestBody
    private val multiPart by lazy {
        MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("_method", "post")
    }
    private lateinit var resultIntent: ActivityResultLauncher<Intent>
    private var uploadFile: File? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        _binding = ActivityAddMaangramBinding.inflate(layoutInflater)
        setContentView(binding.root)

    //Open file picker
        item2ImgLay.setOnClickListener { openFilePicker() }

        //Activity result
        resultIntent = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == Activity.RESULT_OK) {
                val data = result.data
                data?.let {
                    val uri = it.data
                    uri?.let { itUri ->
                        binding.coverImg.load(itUri)
                        uploadFile = File(getRealPathFromURIWithProvider(this, itUri))
                    }
                }
            }
        }

        //Upload
        uploadBtn.setOnClickListener {
            //File
            val fileName = URLEncoder.encode(uploadFile?.absolutePath, "UTF-8")
            val reqFile = uploadFile?.asRequestBody("multipart/form-data".toMediaTypeOrNull())
            multiPart.addFormDataPart("file", fileName, reqFile!!)
            val filePart = MultipartBody.Part.createFormData("file", fileName, reqFile)
            body.file = filePart
            //Submit
            requestBody = multiPart.build()
    }

    }

    private fun openFilePicker() {
        var intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
        intent.addCategory(Intent.CATEGORY_OPENABLE)
        intent.type = "*/*"
        val type: Array<String> = arrayOf("image/*", "video/*")
        intent.putExtra(Intent.EXTRA_MIME_TYPES, type)
        intent = Intent.createChooser(intent, "Choose file")
        resultIntent.launch(intent)
    }
}

Error message:

java.io.FileNotFoundException: : open failed: ENOENT (No such file or directory)
        at libcore.io.IoBridge.open(IoBridge.java:492)
        at java.io.FileInputStream.<init>(FileInputStream.java:160)
        at okio.Okio__JvmOkioKt.source(JvmOkio.kt:182)
        at okio.Okio.source(Unknown Source:1)
        at okhttp3.RequestBody$Companion$asRequestBody$1.writeTo(RequestBody.kt:167)
        at okhttp3.MultipartBody.writeOrCountBytes(MultipartBody.kt:157)
        at okhttp3.MultipartBody.writeTo(MultipartBody.kt:93)
        at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.kt:202)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
        at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
        at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:517)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:923)
        Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@7b44291, Dispatchers.IO]
    Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
        at libcore.io.Linux.open(Native Method)
        at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
        at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
        at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
        at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7542)
        at libcore.io.IoBridge.open(IoBridge.java:478)

Also, I added this line android:requestLegacyExternalStorage="true" to manifest in application tag! again show me error

How can I fix it?

CodePudding user response:

You use ACTION_OPEN_DOCUMENT to let the user pick a file.

For that you do not need any permission or request legacy of any kind.

You are blaming the filepicker. But ACTION_OPEN_DOCUMENT gives you a nice uri. That all works ok.

The trouble only starts where to mess around with the uri: uploadFile = File(getRealPathFromURIWithProvider(this.

Awfull. Dont do such nasty things. Use the uri directly to upload the choosen file.

Has nothing to do with scoped storage too.

  • Related