0

I have a Kotlin app. I'm trying to pick audio from a device. Here is how I get audio file:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == 111 && resultCode == Activity.RESULT_OK && data != null) {
            fileData = data.data!!
            newAudio = fileData
        }
    }

The problem is here:

val file = File(newAudio?.path!!)
val requestFile = RequestBody.create(MediaType.parse("audio/mpeg"), file)
val bodyFile = MultipartBody.Part.createFormData("file", file.name, requestFile)

RetrofitService().uploadAudio(bodyFile).enqueue(object : Callback<Any> {
    @SuppressLint("LogNotTimber")
    override fun onFailure(call: Call<Any>, t: Throwable) {
        d("#Error", "${t.message}")
        mainContent.visibility = VISIBLE
        newAudioProgressBar.visibility = GONE

        Toast.makeText(requireContext(), t.message, Toast.LENGTH_SHORT).show()
    }

    @SuppressLint("LogNotTimber")
    override fun onResponse(call: Call<Any>, response: Response<Any>) {
        navHostFragment.findNavController().navigate(R.id.myAudiosFragment)
        Toast.makeText(requireContext(), "Audio uploaded successfully!", Toast.LENGTH_SHORT).show()
    }
})

I get in logcat: D/#Error: /document/primary:Music/Track28.mp3: open failed: ENOENT (No such file or directory). The file exists because I pick it from my device. I suppose that something's wrong with this path. I'm stuck with this. Help please. Why is it?

  • We discussed this extensively [here](https://stackoverflow.com/q/67623167/115145). **A `Uri` is not a file**, yet you are treating it as one. Get rid of `val file = File(newAudio?.path!!)`. Replace `RequestBody.create(MediaType.parse("audio/mpeg"), file)` with [an `InputStreamRequestBody` implementation](https://stackoverflow.com/a/56308643/115145). – CommonsWare May 22 '21 at 18:02
  • @CommonsWare, yes, but I still can't get the content type. I get a string but I need content type. – Daniil Andreev May 22 '21 at 18:10
  • @CommonsWare, and what should I put in uri (Uri type) in InputStreamRequestBody? – Daniil Andreev May 22 '21 at 18:12
  • "I still can't get the content type" -- you could [call `getType()` on a `ContentResolver`](https://developer.android.com/reference/android/content/ContentResolver#getType(android.net.Uri)), passing in your `Uri`. Or, call `DocumentFile.fromSingleUri()`, passing in your `Uri`, then call `getType()` on the `DocumentFile` that you get back. "what should I put in uri (Uri type) in InputStreamRequestBody?" -- the `Uri` that came in the `Intent` in `onActivityResult()`. You call that `fileData` in your code. – CommonsWare May 22 '21 at 18:17
  • When I call get type and pass ```newAudio``` I get ```Type mismatch: inferred type is String? but MediaType was expected```. – Daniil Andreev May 22 '21 at 18:20
  • [`getType()` on a `ContentResolver` takes a `Uri`](https://developer.android.com/reference/android/content/ContentResolver#getType(android.net.Uri)). In the code in your question, `newAudio` is not a `Uri`. `fileData` is a `Uri`. So, you wind up with `val type = requireContext().getContentResolver().getType(fileData)`. – CommonsWare May 22 '21 at 18:24
  • @CommonsWare, newAudio equals data.data, so it is fileData, but it isn't working. – Daniil Andreev May 22 '21 at 18:37
  • @CommonsWare, it's not the problem with Uri, it's a problem with getType, it gives a string, but must be mediaType. – Daniil Andreev May 22 '21 at 18:38
  • Correct. `getType()` returns a `String`. In the code in your question, you are converting a `String` to a `MediaType` via `MediaType.parse("audio/mpeg")`. You can do the same thing using other strings. For example, you could use `MediaType.parse(requireContext().getContentResolver().getType(fileData))`. – CommonsWare May 22 '21 at 18:42

0 Answers0