Media Player keeps crashing – Android

Issue

I have this mediaplayer that starts the music as soon as I started the program

val mediaPlayer: MediaPlayer = MediaPlayer.create(this, R.raw.cant_let_go)
mediaPlayer.prepare()
mediaPlayer.start()

Also, I have a recyclerview so when I clicked a new song, it will play the new song.

  adapter = RVDiffAdapter(object : RVDiffAdapter.OnAdapterListener {
      override fun onCLick(name: String, rawId:Int) {
          Toast.makeText(applicationContext, name, Toast.LENGTH_SHORT).show()

          Log.d("XXX", "name $name")
          Log.d("XXX", "rawId $rawId")

          mediaPlayer?.stop()
          mediaPlayer?.reset()
          mediaPlayer?.release() 
          val mediaPlayer: MediaPlayer = MediaPlayer.create(applicationContext, rawId)
          mediaPlayer.start()}

The first click works fine, but on the second click I got the following error and crashed the program:

 java.lang.IllegalStateException
        at android.media.MediaPlayer._reset(Native Method)
        at android.media.MediaPlayer.reset(MediaPlayer.java:2243)
        at musicplayer.cs371m.musicplayer.MainActivity$onCreate$2.onCLick(MainActivity.kt:114)
        at musicplayer.cs371m.musicplayer.RVDiffAdapter.onBindViewHolder$lambda-0(RVDiffAdapter.kt:70)
        at musicplayer.cs371m.musicplayer.RVDiffAdapter.$r8$lambda$4-sW8793PxY9Wjx6EFGiUJ-Whxk(Unknown Source:0)
        at musicplayer.cs371m.musicplayer.RVDiffAdapter$$ExternalSyntheticLambda0.onClick(Unknown Source:4)
        at android.view.View.performClick(View.java:7455)
        at android.view.View.performClickInternal(View.java:7432)
        at android.view.View.access$3700(View.java:835)
        at android.view.View$PerformClick.run(View.java:28810)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7842)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)

Below is my adapter just in case needed

class RVDiffAdapter(private val listener: OnAdapterListener)
    : ListAdapter<SongInfo,
        RVDiffAdapter.ViewHolder>(Diff())
{

    // ViewHolder pattern holds row binding
    inner class ViewHolder(val songRowBinding : SongRowBinding)
        : RecyclerView.ViewHolder(songRowBinding.root) {
        init {
            songRowBinding.root.setOnClickListener {

            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val songBinding = SongRowBinding.inflate(LayoutInflater.from(parent.context),
            parent, false)
        return ViewHolder(songBinding)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {

        val item = getItem(position)
        val songBinding = holder.songRowBinding
        songBinding.rowText.text = item.name
        songBinding.rowText2.text = item.time

        songBinding.rowText.setOnClickListener {
            listener.onCLick(item.name, item.rawId)
        }

    interface OnAdapterListener {
        fun onCLick(name:String, rawId:Int)
    }


    class Diff : DiffUtil.ItemCallback<SongInfo>() {
        // Item identity
        override fun areItemsTheSame(oldItem: SongInfo, newItem: SongInfo): Boolean {
            return oldItem.hashCode() == newItem.hashCode()
        }
        // Item contents are the same, but the object might have changed
        override fun areContentsTheSame(oldItem: SongInfo, newItem: SongInfo): Boolean {
            return oldItem.name == newItem.name
                    && oldItem.rawId == newItem.rawId
                    && oldItem.time == newItem.time
        }
    }
}

What did I do wrong here? Cause from Logcat I can see the id of the musicplayer.

Edit1: I am guessing it has to do with the stop, reset, and release the media player. Because after I comment those I got no error. However, I am playing multiple songs in the background which I don’t want.

Solution

Instead of creating new mediaplayer instance on every click, i’d try something like this:

adapter = RVDiffAdapter(object : RVDiffAdapter.OnAdapterListener {
      override fun onCLick(name: String, rawId:Int) {
          Toast.makeText(applicationContext, name, Toast.LENGTH_SHORT).show()

          Log.d("XXX", "name $name")
          Log.d("XXX", "rawId $rawId")

          mediaPlayer?.stop()
          mediaPlayer?.reset()
          mediaPlayer?.setDataSource(getDataFromResource(rawId)) //You must do this somehow
          mediaPlayer?.prepare()
          mediaPlayer?.start()
}

You can check the state diagram from documentation: https://developer.android.com/reference/android/media/MediaPlayer.html

Answered By – nsko

Answer Checked By – Cary Denson (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *