Android stopping the previous mediaplayer? - java

I have 3 toggle buttons. I had it working that when clicked it would play a sound and the button would toggle to "stop". when the sound is finished it would toggle back to "play" If you click "stop" while it is playing the sound will stop and toggle back.
However my problem is that if I click two buttons and they both were playing I could not stop the previous one. This is because I could not access the previous mediaPlayer only the current. Here is my current attempt, any help would be great, thanks!
#Override
public void onClick(View v)
{
int soundFile = 0;
switch (v.getId())
{
case (R.id.btnSound1):
soundFile = R.raw.sound1;
break;
case (R.id.btnSound2):
soundFile = R.raw.sound2;
break;
case (R.id.btnSound3):
soundFile = R.raw.sound3;
break;
}
final ToggleButton button = (ToggleButton) findViewById(v.getId()); //gets current button
MediaPlayer media = (MediaPlayer) button.getTag(); //gets mediaPlayer object stored in button
if(button.getTag().equals(null)) //only runs this once, if the mediaPlayer stored object is null (doesn't exist)
{
media = getMedia(soundFile);
button.setTag(media); //set the new media object to the buttons tag
media.start();
media.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) //when sound is over
{
button.setChecked(true); //set back to play
mp.release();
}
});
button.setOnCheckedChangeListener(new OnCheckedChangeListener(){ //when clicked
#Override
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked)
{
if(button.isChecked()) // if stop toggle clicked
{
button.setChecked(true); // set to play
MediaPlayer media = (MediaPlayer) button.getTag();
media.release(); //stop the sound
}
else if(!button.isChecked()) //if play toggle clicked
{
MediaPlayer media = (MediaPlayer) button.getTag();
media.start(); //play the sound
button.setChecked(false); //set to stop
}
}
});
}
}
public MediaPlayer getMedia(int sound)
{
MediaPlayer mediaPlayer = MediaPlayer.create(getBaseContext(), sound);
mediaPlayer.setVolume(100,100); //sets the volume to max
return mediaPlayer;
}

Related

Android media player not working as expected

I am very new to android just started with Android currently referring the below code from past 2 days, not able to fix the issue.
Code:
https://github.com/quocnguyenvan/media-player-demo
Issue: Let's say we 4 Songs in the ListView when we click on the first song play it for some time and pause it without clicking on stop.
As soon as we click on the second song the first song starts playing we cannot play the second song unless we click on stop of the first song How to solve this issue.
The issue with code not able to figure out and fix it.I have referred many posts before posting on StackOverflow but could not make it, any suggestion or guidance is highly appreciated.
Problematic code:
// play music
viewHolder.ivPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(flag){
mediaPlayer = MediaPlayer.create(context, music.getSong());
flag = false;
}
if(mediaPlayer.isPlaying()) {
mediaPlayer.pause();
viewHolder.ivPlay.setImageResource(R.drawable.ic_play);
} else {
mediaPlayer.start();
viewHolder.ivPlay.setImageResource(R.drawable.ic_pause);
}
}
});
// stop
viewHolder.ivStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!flag) {
mediaPlayer.stop();
mediaPlayer.release();
flag = true;
}
viewHolder.ivPlay.setImageResource(R.drawable.ic_play);
}
});
These are the steps I used for playing song you can try to sync with my steps to resolve the error.
private void initMembers() {
//initialize the members here
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//media prepare
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(final MediaPlayer mediaPlayer) {
//media player prepared
togglePlayPausePlayer();
}
});
//media completion
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(final MediaPlayer mediaPlayer) {
//handle the media play completion
handleOnCompletionLogic();
}
});
}
after that whenever I try to play the song. I call this method.
public void playMusic(final MusicModel musicModel) {
//here play the music with data in below
try {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();
}
mMediaPlayer.reset();
mMediaPlayer.setDataSource(musicModel.getUrl());
mMediaPlayer.prepareAsync();
} catch (IOException | IllegalStateException exp) {
exp.printStackTrace();
showMessage(getString(R.string.error_unable_play));
}
}
above resets the playing song and prepare the player for another song.
and OnPreparedListener it calls the togglePlayPausePlayer() which play and pause the song accordingly.
private void togglePlayPausePlayer() {
//here handle the logic for play and pause the player
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
setPlayAndPause(false);
} else {
mMediaPlayer.start();
setPlayAndPause(true);
}
}
The key is we initialize the player and set an onPrepareListener for the media player to get prepared and then play the song, which will check if it's playing then it will stop and else it will play.
hope this may help you.
For on click on ListView you need to reset the media player, change the data source and start playing with new song.
mp.reset();
mp.setDataSource("song you selected from ListView");
mp.prepare();
mp.start();

Wait for text to speech and music to complete before registering next onClick

I have several buttons that respond to an onClick. When the buttons are pressed, it triggers a text to speech that says the name of the button and some music that corresponds to the button. However, the app glitches because you can press a different button while the music and text to speech for one button are still running. Is there a way to wait for the text to speech and music to stop playing before allowing another click? Any help would be greatly appreciated!! Thanks a lot!!!
public void onClick(View view) {
Resources res = getResources();
Button btn = (Button) view;
final TextView tv = (TextView) findViewById(R.id.color_text);
textViewString = tv.getText().toString();
switch (view.getId()) {
case R.id.green_button:
String greenString = res.getString(R.string.Green);
tv.setText(greenString);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
tts.speak(greenString, TextToSpeech.QUEUE_FLUSH, null);
} else {
tts.speak(greenString, TextToSpeech.QUEUE_FLUSH, null, null);
}
MediaPlayer green = MediaPlayer.create(this, R.raw.green);
green.start();
break;
case R.id.red_button:
String redString = res.getString(R.string.Red);
tv.setText(redString);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
tts.speak(redString, TextToSpeech.QUEUE_FLUSH, null);
} else {
tts.speak(redString, TextToSpeech.QUEUE_FLUSH, null, null);
}
MediaPlayer red = MediaPlayer.create(this, R.raw.red);
red.start();
break;
It seems that you must invoke tts.shutdown() in onClick() and then create the other tts object.
public void onClick(View view) {
tts.shutdown();
tts = new TextToSpeech(context, listener)
/* your code */
}
you can put if statement that checks if tts object is playing , tts.isSpeaking() return boolean true if speaking.

Toggle VideoView's audio with a Button

I am using a videoView to play a video.
bVideoView = (VideoView) findViewById(R.id.bVideoView);
bVideoView.setVideoPath(videoPath);
Now I have a button,
audioToggle = (Button) findViewById(R.id.audioToggle);
Then I have the Button's OnClickListener
private static int aux = 0;
private AudioManager mAudioManager;
audioToggle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bVideoView.start();
mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
if(aux % 2 == 0){
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 50, 0);
aux++;
} else {
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
aux++;
}
}
});
Now with this OnClickListener I am perfectly able to toggle the audio to mute and unmute when it is clicked each time. However I want something like this,
On the first click the videoView should start.
When I keep pressing the button the audio must mute.
When I release the button the audio must unmute.
I have been trying a lot and failing in some or the other way. Please help.
Do you mean:
The first time I hold the button, the video should play.
While I'm holding the button the audio must be heard.
When I release the button, the audio must be muted.
When I press and hold the button again, the audio must be heard again.
Then what you therefore need is not an OnClickListener but rather an OnTouchListener
What happens under the hood is that your OnClickListener is always called after you release your finger. Using View.OnTouchListener you can dispatch events when you press (you mean touch and hold) and release.
See http://developer.android.com/reference/android/view/View.OnTouchListener.html
Here's a sample snippet:
private static int aux = 0;
private AudioManager mAudioManager;
audioToggle.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent e) {
bVideoView.start();
mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
switch(e.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 50, 0);
break;
case MotionEvent.ACTION_UP:
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
break;
}
return true;
}
}
Finally, I don't recommend controlling the system's volume. Use a MediaPlayer.OnPreparedListener instead, get the VideoView’s MediaPlayer and then play around with its volume.
Edit:
Here's another sample snippet:
private MediaPlayer bVideoViewMP;
bVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
// Fetch a reference
bVideoViewMP = mp;
}
});
audioToggle.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent e) {
bVideoView.start();
switch(e.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
bVideoViewMP.setVolume(0.75f, 0.75f);
break;
case MotionEvent.ACTION_UP:
bVideoViewMP.setVolume(0, 0);
break;
}
return true;
}
}
These should be placed either on your fragment's onViewCreated() or on your activity's onCreate() method before the VideoView has been fully prepared.

android media player unresponsive

This is my code, I tried ti build simple application that plays a song whenever I click one button (clicking twice will play the song a new from the beginning) & stop playing when another button is pushed.
I wanted that when the user put the activity in the background the media player will "save its state" - continue playing/not playing - and when the activity returns to the foreground the interaction will remain the same.
Instead it works fine until I put the activity in the background (then it keeps playing/not playing) but when I return it back it seems like "a new media player object was created" and if I click play while the song is played, it starts to play the song from the beginning simultaneously with the previous one, and clicking stop - stopping only the new "instance" of the song. Like I loose connection with the media player after the activity is in the background.
what could be the problem?
public class MainActivity extends ActionBarActivity {
private MediaPlayer mediaPlayer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button buttonStart = new Button(this);
Button buttonStop = new Button(this);
buttonStart.setText(R.string.button_start_text);
buttonStop.setText(R.string.button_stop_text);
buttonStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startPlaying();
}
});
buttonStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stopPlaying();
}
});
ViewGroup layout = (ViewGroup) findViewById(R.id.mainLayout);
layout.addView(buttonStart);
layout.addView(buttonStop);
}
void startPlaying(){
stopPlaying();
mediaPlayer = MediaPlayer.create(this,R.raw.dreams);
mediaPlayer.start();
}
void stopPlaying(){
if (mediaPlayer != null){
try {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.reset();
mediaPlayer.release();
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
I changed the code also, like this (now there are 3 buttons: play, stop, pause:
void startPlaying(){
if (mediaPlayer == null) {
mediaPlayer = MediaPlayer.create(this, R.raw.dreams);
}
mediaPlayer.start();
}
void stopPlaying(){
if (mediaPlayer != null){
try {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.prepare();
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
void pausePlaying(){
if (mediaPlayer != null) mediaPlayer.pause();
}
but still same behaviour.
Some insight I got:
before the user place the activity in the background the member mediaPlayer is some constructed android object.
when the activity returns to the foregound mediaPlayer is null.
Why is this?
Maybe I got wrong the idea of activity but I thought it keeps its members with their values during its life cycle.
Your are creating and destroying your mediaplayer everytime. Try to create two methods for pause and resume/start like that.
below you can find the code that is working fine for me. I am developing a game that starts a main theme when the activity loads. Each time the activity resumes, the media player continue to play the song at the paused position. I override onDestroy() to stop, onResume to start/resume and onPause() to pause when the activity goes Background.
public MediaPlayer mp=null;
#Override
protected void onDestroy() {
if (mp!=null)
mp.stop();
super.onStop();
}
#Override
protected void onResume() {
super.onResume();
if (mp==null){
self=this;
Thread thMusic= new Thread(new Runnable(){
public void run(){
mp= MediaPlayer.create(self,R.raw.dizzy );
mp.start();
}
});
thMusic.start();
}
else
mp.start();
}
#Override
protected void onPause() {
if (mp!=null)
mp.pause();
super.onPause();
}
i hope this will help you.
http://developer.android.com/guide/components/activities.html
Saving activity state gives a detailed information that could explain what happened.
In short when activity is in the background it might be killed and created again by OS when user navigate it back to foreground.
onSaveInstanceState() should be implemented unless only UI objects are restored
but not class members

MediaPlayer keep playing even button disabled

I tried most of options avialable on stackoverflow, could you please help me!
I have a button which plays MediaPlayer instance when clicked, but the problem if I click double-click or clicked during playing media it will play two times even i set the button.setEnable(false) and button.setClickable(false), below is the code in Main.java, and I have set in xml android:onClick="playMedia"
MediaPlayer playMedia;
private void playGeneric(MediaPlayer mp, int name, Button button) {
button.setEnabled(false);
button.setClickable(false);
mp = MediaPlayer.create(this, name);
mp.start();
while (mp.isPlaying()) {
}
mp.stop();
mp.release();
mp = null;
button.setEnabled(false);
button.setClickable(false);
}
// play the Media
public void playMedia(View button) {
playGeneric(Media, R.raw.Media, (Button) findViewById(R.id.button1));
}
thanks a lot
1- You should have a single (preferably static) MediaPlayer instance per your activity/service
2- This loop while (mp.isPlaying()) is extremely bad practice, you just need to listen to the appropriate event
3- Before creating a new MediaPlayer instance you have to check that if the current one is not null then stop and release it
To solve your code you can do the following:
1- Let your class implements OnCompletionListener and override the method onCompletion(MediaPlayer mp) to be notified when the MediaPlayer finished and clean the resources (but you need to clean it as well when your activity/service get destroyed)
2-
static MediaPlayer playMedia;
private void playGeneric(MediaPlayer mp, int name, Button button) {
button.setEnabled(false);
button.setClickable(false);
if(mp !=null){
mp.stop();
mp.release();
}
mp = MediaPlayer.create(this, name);
mp.start();
}
#Override
public void onCompletion(MediaPlayer mp) {
mp.release();
playMedia = null;
button.setEnabled(true);
button.setClickable(true);
}

Categories