1

HELP PLEASE !!

I'm using media player in recycler view and the problem is when different item's play buttons are clicked they all play at the same time. How can I stop the previous audio and start the new audio ?

Here is the adapter code:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>  {
    final MediaPlayer mediaPlayer = new MediaPlayer();


 public void onBindViewHolder(@NonNull MyAdapter.ViewHolder viewHolder, int position) {
        try {
            mediaPlayer.reset();
            mediaPlayer.setDataSource(item.get(position).getAudio());
            mediaPlayer.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }

viewHolder.play.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mediaPlayer.isPlaying()) {
                        mediaPlayer.pause();
                        viewHolder.play.setImageResource(R.drawable.play);

                } else {
                    mediaPlayer.start();
                    viewHolder.play.setImageResource(R.drawable.pause);
                }

I suppose one answer is using flag. but I don't know how to implement it.

Zain
  • 37,492
  • 7
  • 60
  • 84
ghazalia
  • 63
  • 3
  • 9

2 Answers2

1

There are multiple audios that play at the same time because there are multiple instances of the MediaPlayer object, because it's instantiated on every call to the onBindViewHolder(); i.e. each row of the RecyclerView will have a unique object.

To fix this, you need to use only a single object for all the audio, so transfer the

final MediaPlayer mediaPlayer = new MediaPlayer();

To be a direct field to the adapter class.

UPDATE:

Now change the logic of play button click

public void onBindViewHolder(@NonNull MyAdapter.ViewHolder viewHolder, int position) {

    viewHolder.play.setOnClickListener(new View.OnClickListener() {
        @Override
            public void onClick(View view) {
            
                if (mediaPlayer.isPlaying()) {
                    mediaPlayer.stop();
                    mediaPlayer.release();
                    viewHolder.play.setImageResource(R.drawable.play);
                } 
                
                try {
                    mediaPlayer.reset();
mediaPlayer.setDataSource(item.get(position).getAudio());
                    mediaPlayer.prepare();
                    mediaPlayer.start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                
                viewHolder.play.setImageResource(R.drawable.pause);
                            
            }
        }

}

UPDATE 2:

Try to transfer the play button code to the ViewHolder instead of the onBindViewHolder, and instead of the position, use getAbsoluteAdapterPosition()

public static class ViewHolder extends RecyclerView.ViewHolder {

    //.....
    
    public ViewHolder(View itemView) {
        super(itemView);
        play = itemView.findViewById(...);
        
        play.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
            
                // ..... Add the mediaPlayer code
                                
            }
        }
    }

}
Zain
  • 37,492
  • 7
  • 60
  • 84
0

This is a problem of double instantiation of MediaPlayer() class. What you have to do is to make an object class like this:

import android.media.MediaPlayer
import android.net.Uri
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

object MusicObject {

    private lateinit var mediaPlayer: MediaPlayer
    private val executor: ExecutorService = Executors.newCachedThreadPool()
    private var flag = 0
    private var musicName = ""
    private var musicID = 1
    private var musicUri: Uri? = null

    // Function to play music
    fun playMusic(mp: MediaPlayer,name: String,ID: Int,Uri: Uri) {
        if (flag > 0) {
            pauseMusic()
        }
        flag++
        musicName = name
        musicID = ID
        musicUri = Uri
        mediaPlayer = mp
        executor.execute {
            mediaPlayer.start()
        }
    }

    // Function to play currently playing music again
    fun playMusicAgain() {
        executor.execute {
            mediaPlayer.start()
        }
    }

    // Function to pause music
    fun pauseMusic() {
        mediaPlayer.pause()
    }

    // Function to stop music
    fun stopMusic() {
        if (mediaPlayer.isPlaying) {
            mediaPlayer.stop()
        }
    }

    fun getMediaPlayer(): MediaPlayer {
        return mediaPlayer
    }
}

And call this class to play and pause the music.

To play music:

MusicObject.playMusic(MediaPlayer.create(this, songUri), idOfMusic, songID, songUri)

To pause music:

MusicObject.pauseMusic()
Ashique Bava
  • 2,486
  • 2
  • 9
  • 21