I am trying to implement a RecyclerView
with audio messages and playing those audio files. Previously I was stuck on a problem when I was changing play and pause image on ImageButton
, so I found this solution and changed my code accordingly. But now I am facing another issue. Whenever I play the audio , the image changes to pause and when I click this button again, it gives me an error: pause called in state 8
. I know what is causing the problem, but cannot figure out the solution.
Here is my onBindViewHolder :
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((MyChatMediaViewHolder) holder).bindData(mChats.get(position), position);
}
Here is my MyChatMediaViewHolder
class :
private class MyChatMediaViewHolder extends RecyclerView.ViewHolder {
private TextView txtUserAlphabet, timer;
private ImageView play;
private SeekBar seekBar;
ProgressBar progressBar;
RelativeLayout media_chat;
Chat chat = null;
public MyChatMediaViewHolder(View itemView) {
super(itemView);
play = (ImageView) itemView.findViewById(R.id.play);
seekBar = (SeekBar) itemView.findViewById(R.id.seekbar);
txtUserAlphabet = (TextView) itemView.findViewById(R.id.text_view_user_alphabet);
progressBar = (ProgressBar) itemView.findViewById(R.id.progressUpdate);
media_chat = (RelativeLayout) itemView.findViewById(R.id.chat_media);
timer = (TextView) itemView.findViewById(R.id.timer);
Log.e("TAG111", "bindData: ");
play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
isPlay = !isPlay;
//Handling for background selection state changed
int previousSelectState=mSelectedItemPosition;
mSelectedItemPosition = getAdapterPosition();
//notify previous selected item
notifyItemChanged(previousSelectState);
//notify new selected Item
notifyItemChanged(mSelectedItemPosition);
}
});
}
public void bindData(Chat chat, int currentPosition) {
this.chat = chat;
MediaPlayer mediaPlayer = new MediaPlayer();
MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
try {
mediaPlayer.setDataSource(chat.mediaUrlLocal);
metaRetriever.setDataSource(chat.mediaUrlLocal);
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
String duration =
metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long dur = Long.parseLong(duration);
String seconds = String.valueOf((dur % 60000) / 1000);
String minutes = String.valueOf(dur / 60000);
String out = minutes + ":" + seconds;
timer.setText(out);
if(currentPosition == mSelectedItemPosition) {
Log.e("pause", "bindData: " + mediaPlayer.isPlaying());
if(isPlay) {
mediaPlayer.start();
play.setImageResource(android.R.drawable.ic_media_pause);
} else {
mediaPlayer.pause();
play.setImageResource(android.R.drawable.ic_media_play);
}
} else {
play.setImageResource(android.R.drawable.ic_media_play);
}
}
}
The problem here I think is : new MediaPlayer
instance gets created every time
play button is clicked, so when I try to pause , a new media player is again created which was never started.
So the question is : Where should I create the new MediaPlayer instance?
First of all your RecyclerView.Adapter
's purpose is to inflate your view, you shouldn't write your business logic here.
Second you should use only one instance of media player. You should initialize your media player inside your Activity
or Fragment
.
Create an interface implement in your Activity
or Fragment
and pass its reference to your adapter. Whenever you want to play audio you will use your interface to delegate your audio file path or stream to Activity
or Fragment
, reset or release your media player and play your audio.