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.