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.
CodePudding user response:
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