0

I'm creating a kotlin app that reads an audio file from external storage from a device. However when I try to read it I get fileNotFoundException. Here is my code:

val file = File(newAudio!!)
val inputStream = context?.contentResolver?.openInputStream(Uri.fromFile(file))
val requestFile = RequestBody.create(MediaType.parse("audio/mpeg"), inputStream?.readBytes())

newAudio equals intent's path (URI). Why is this happening?

EDIT: Here is how I get newAudio and send it to ViewModel:

  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!!
            newAudioViewModel!!.sendNewAudio(fileData)
            navHostFragment.findNavController().navigate(R.id.newAudioInfoFragment)
        }
    }

Then I get it from ViewModel like this:

newAudioViewModel!!.getNewAudio().observe(viewLifecycleOwner, Observer<Uri?> { audio ->
    newAudio = audio?.path
})

  • A `Uri` is not a file. The path is meaningless. An answer on the duplicate question points to three implementations of an `InputStreamRequestBody` (two in Kotlin) that can work with a `Uri` directly. – CommonsWare May 20 '21 at 15:15
  • @CommonsWare, I know that URI is not a file. By I create file with this Uri. – Daniil Andreev May 20 '21 at 15:21
  • "By I create file with this Uri" -- sorry, I do not know what that means. If you are getting a `FileNotFoundException`, `newAudio` is not pointing to some path that your app can read. And "intent's path (URI)" suggests that you are not creating a file, but instead are getting a `Uri` from some `Intent`, such as `ACTION_CREATE_DOCUMENT`. Your question does not show where `newAudio` comes from or what "intent's path (URI)" refers to. – CommonsWare May 20 '21 at 15:29
  • @CommonsWare, I'm sorry, this is a typo. I meant that I take ```Uri``` like this ```File(Uri)```. – Daniil Andreev May 20 '21 at 15:33
  • @CommonsWare, I don't want to create a new file. I want to take an existing one parse it and send to my server. – Daniil Andreev May 20 '21 at 15:44
  • "I know that URI is not a file" -- not according to your code. You are calling `getPath()` on a `Uri`, then passing that to the `File` constructor. That will not work, so stop doing that. Instead, have `newAudio` be a `Uri`. Then, use any of the `InputStreamRequestBody` implementations linked to from the answer on the duplicate question instead of `RequestBody.create()`. – CommonsWare May 20 '21 at 15:49
  • @CommonsWare, I don't quite understand. In the duplicate question, he uses FileUtils. When I try to put without getPath I still get fileNotFoundException. – Daniil Andreev May 20 '21 at 15:54
  • Read [the answer on the duplicate question](https://stackoverflow.com/a/56308643/115145). Then read [this blog post](https://commonsware.com/blog/2020/07/05/multipart-upload-okttp-uri.html), and [this blog post](https://cketti.de/2020/05/23/content-uris-and-okhttp/), both of which are linked to from that answer. They explain the need for an `InputStreamRequestBody` to replace `RequestBody.create()`, and they provide two separate implementations of the concept. – CommonsWare May 20 '21 at 16:02
  • Then, in your code, get rid of `Uri.fromFile()`. Use the `Uri` that you get from your `onActivityResult()` with an `InputStreamRequestBody` to create a `RequestBody` that can work with the `Uri` that you received. – CommonsWare May 20 '21 at 16:03
  • @CommonsWare, please can you provide a code example? – Daniil Andreev May 20 '21 at 16:06
  • Both blog posts contain sample code, and both link to sample projects. – CommonsWare May 20 '21 at 16:09
  • @CommonsWare, I use retrofit2 – Daniil Andreev May 20 '21 at 16:25
  • Retrofit2 is based on OkHttp. `RequestBody` comes from OkHttp. – CommonsWare May 20 '21 at 16:26
  • @CommonsWare, it still isn't working. Even when I put ```newAudio.path``` in ```openInputStream```. – Daniil Andreev May 20 '21 at 19:57
  • @CommonsWare, how can I get content type? – Daniil Andreev May 21 '21 at 07:00
  • Pass the `Uri` that you received in `onActivityResult()` to `getType()` on a `ContentResolver`. – CommonsWare May 21 '21 at 10:42

0 Answers0