Reputation: 293
In my app i have recyclerview items, and each item play sound when i click it. Problem is that when i click few items, they all play sounds in the same time until they finish. Lets say i click 10 items, all 10 play sounds in the same time and after some time app get crashed and i get this error: E/MediaPlayer: error (1, -19). I avoid app crashing by implementing automatic release with this code:
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mediaPlayer.release();
}
});
But that's not what i want, it is annoying to hear few sounds in the same time. What i want is to stop previous sound when i click new one, i try to implent mediaplayer stop and release, but without success.
This is the app in google play so you can check by yourself: https://play.google.com/store/apps/details?id=org.pero.androidd.animalSoundsQuiz
Here is my Adapter code where i play sounds. In this code there is part MediaPlayer.OnCompletionListener() where i release sound after sound finish to aviod E/MediaPlayer: error (1, -19) error, but that is not what i want in my app. I want to stop previous sound after i click new one.
import android.content.Context;
import android.media.MediaPlayer;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.pero.androidd.animalsoundsforchildren.R;
import java.util.List;
public class ZivotinjeAdapter extends RecyclerView.Adapter<ZivotinjeAdapter.ViewHolder> {
private List<Zivotinje> mZivotinje;
@Override
public ZivotinjeAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
// Inflate the custom layout
View contactView = inflater.inflate(R.layout.item_zivotinje, parent, false);
// Return a new holder instance
ViewHolder viewHolder = new ViewHolder(contactView);
return viewHolder;
}
@Override
public void onBindViewHolder(ZivotinjeAdapter.ViewHolder viewHolder, int position) {
Zivotinje zivotinjeIme = mZivotinje.get(position);
// Set item views based on the data model
TextView textView = viewHolder.nameTextView;
textView.setText(zivotinjeIme.getmAnimal_name());
//THIS IS WHERE I HANDALE IMAGE VIEW. Using glide for images
//Dohvacamo context svakog views
ImageView slika_source = viewHolder.imageView;
Glide.with(slika_source.getContext())
.load((Integer) zivotinjeIme.getmAnimal_slika())
.into(slika_source);
viewHolder.setItem(mZivotinje.get(position));
}
@Override
public int getItemCount() {
return mZivotinje.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ImageView imageView;
public TextView nameTextView;
private Zivotinje mItem;
public void setItem(Zivotinje item) {
this.mItem = item;
}
public ViewHolder(final View itemView) {
super(itemView);
nameTextView = (TextView) itemView.findViewById(R.id.zivotinjaIme_id);
imageView = (ImageView) itemView.findViewById(R.id.slika_id);
//Handdaling clicks
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final MediaPlayer mediaPlayer = MediaPlayer.create(v.getContext(), mItem.getmSound());
mediaPlayer.start();
//releace media player after sound finish
// BUT I DO NOT WANT TIS, I WANT TO STOP PREVIOUS SOUND WHEN I CLICK NEW ONE
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mediaPlayer.release();
}
});
}
});
}
}
public ZivotinjeAdapter(List<Zivotinje> animals) {
mZivotinje = animals;
}
}
EDIT EDIT EDIT EDIT EDIT EDIT:
I find solution, i do not know is this the smartest way to do it but it works for me fine:
What i done is that i made static media player variable and this way i can access to media player from ViewHolder and stop previous sound when i click new one. Hope it helps.
here is the whole code:
public class ZivotinjeAdapter extends RecyclerView.Adapter<ZivotinjeAdapter.ViewHolder> {
private static MediaPlayer mediaPlayer; //THIS IS THE CHANGE I DONE
@Override
public ZivotinjeAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
// Inflate the custom layout
View contactView = inflater.inflate(R.layout.item_zivotinje, parent, false);
// Return a new holder instance
ViewHolder viewHolder = new ViewHolder(contactView);
return viewHolder;
}
@Override
public void onBindViewHolder(ZivotinjeAdapter.ViewHolder viewHolder, int position) {
Zivotinje zivotinjeIme = mZivotinje.get(position);
// Set item views based on the data model
TextView textView = viewHolder.nameTextView;
textView.setText(zivotinjeIme.getmAnimal_name());
//THIS IS WHERE I HANDALE IMAGE VIEW. Using glide for images
ImageView slika_source = viewHolder.imageView;
Glide.with(slika_source.getContext())
.load((Integer) zivotinjeIme.getmAnimal_slika())
.into(slika_source);
viewHolder.setItem(mZivotinje.get(position));
}
@Override
public int getItemCount() {
return mZivotinje.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ImageView imageView;
public TextView nameTextView;
private Zivotinje mItem;
public void setItem(Zivotinje item) {
this.mItem = item;
}
public ViewHolder(final View itemView) {
super(itemView);
nameTextView = (TextView) itemView.findViewById(R.id.zivotinjaIme_id);
imageView = (ImageView) itemView.findViewById(R.id.slika_id);
//handaling clicks
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.reset();
mediaPlayer.release();
mediaPlayer = null;
}
mediaPlayer = MediaPlayer.create(v.getContext(), mItem.getmSound());
mediaPlayer.start();
}
});
}
}
private List<Zivotinje> mZivotinje;
public ZivotinjeAdapter(List<Zivotinje> animals) {
mZivotinje = animals;
}
}
Upvotes: 3
Views: 8780
Reputation: 4226
You first have to check if there is a sound that is already playing and if there is, you should stop it when the user decides to start a new sound.
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mediaplayer.isPlaying ()) {
if (mediaplayer != null){
mediaplayer.stop ();
}
} else {
if (mediaplayer != null) {
mediaplayer.start ();
}
}
}
});
In setOnCompletionListner
you release the sound if the user listens to the whole sound clip.
mediaplayer. setOnCompletionListner (new MediaPlayer.OnCompletionListner () {
public void OnCompletion (MediaPlayer mediaplayer) {
mediaplayer.release ();
}
});
Upvotes: 5