MediaPlayer throwing IllegalStateException when calling onStop() - android

I have an AlertDialog, which stops playing a sound when I have clicked, but on some devices it appears that calling onStop() throws an IllegalStateException, but why?
If the dialog is up, that means the sound is playing, so it should be a case where the audio is not playing.
I surrounded it with a try catch for now, but what would cause this?
alert.setPositiveButton("YES", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
try{
mp.stop(); //error
mp.reset();
mp.release();
}catch(Exception e){
Log.d("Nitif Activity", e.toString());
}
v.cancel();
popupMessage();
finish();
}
});

Checking mp != null prevents a NullPointerException but the IllegalStateException can't be caused by that.
The reason you get that error is that the player is in a state where it can't stop(). If you have a look at the state-diagram at the top of the MediaPlayer documentation you can see that stop can only be called after the player is in the Prepared state. The next possibility is that you have already called release() or reset() which will also result in that error.
You can call stop() only in Prepared, Started, Paused, PlaybackComplete or Stopped state. All other states produce that error.
So you either do prepareAsync() and the user hits the button before your player is prepared or you have code that releases or resets the player before you hit the button.

I guess you might be nulling your instance before executing these lines.
When I got this error I check for null first.
if (mp != null) {
try {
mp.stop(); //error
mp.reset();
mp.release();
} catch(Exception e){
Log.d("Nitif Activity", e.toString());
}
}

Apparently mp isn't initialized, Dev Resource;
Try adding:
if(mp != null)

Checking mp!=null prevents when it is null, but your mediaplayer never goes null.
just add mp=null; where you are doing mp.stop();

Related

Releasing Media Player while preparing is causing app to freeze

I have two activities a main activity which has Recyclerview and a detailedActivity which is launched every time the user clicks on one of the items of the Recyclerview. The detailedActivity has a mediaplayer component that is being created everytime a detailedActivity is created. Now in the onDestroy method I always free the resources taken by the mediaPlayer by this code:
#Override
protected void onDestroy() {
if (mMediaPlayer != null) {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();}
mMediaPlayer.release();
mMediaPlayer=null;
}
super.onDestroy();
}
The app freezes for a while every time I click the back button while the mediaplayer is still preparing. The message that I get in the logcat is this:
I/Choreographer: Skipped 112 frames! The application may be doing too much work on its main thread.
So this freezing only happens if I destroyed the activity while it is preparing but if it is already in the prepared state it won't happen. I use prepreAsync to fetch the media from the internet.
Thanks. Any help is highly appreciated. I have been stuck in this problem for days!
OK. I've kind of worked around the problem. I am writing this for anyone who might encounter the same situation as I did. I made two boolean flags in the scope of the class like this:
boolean prepared = false;
boolean cancel = false;
After that in the onpreapred method I set prepared to true.
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
prepared = true;
}
});
In the onDestroy method I check whether the mediaplayer is already prepared or not if prepared I release it from the method its self.
#Override
protected void onDestroy() {
if (mMediaPlayer != null) {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();
}
if (prepared) {
mMediaPlayer.release();
mMediaPlayer = null;
}
cancel = true;
}
super.onDestroy();
}
Otherwise, I set cancel to true and implement on OnBufferingUpdateListener interface and override its method and release the mediaplayer from there.
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
if (cancel) {
mp.reset();
mp.release();
mMediaPlayer = null;
Log.i("msg", " mp released");
}
}
Try to remove rechecking if mediaplayer is running or not.
#Override
protected void onDestroy() {
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
}
super.onDestroy();
}
If it still happens, try to remove checking mediaplayer in your onDestroy().
-- UPDATE --
This could be related with this bug:
https://code.google.com/p/android/issues/detail?id=959
This could be a help:
Android MediaPlayer reset freezes UI

Getting a ringtone to only loop once in mediaPlayer

So basically I use a Spinner widget and pass it the RingtoneManager Picker action, the user then selects their ringtone. Then I call onActivityResult() and get the uri for the ringtone.
Finally I pass the uri to another activity where I have a alarm setup to go off after a specific amount of time.
THE PROBLEM >>> when I get the uri for the ringtone in the 2nd activity and let mediaPlayer play it, It...it doesn't stop. No matter WHAT I try.
This is the 2nd activity and the mediaPlayer that never stops.
Uri ringtone;
ringtone = Uri.parse(musixType);
//mMediaPlayer.setDataSource(DisplayNotification.this, ringtone);
mMediaPlayer = MediaPlayer.create(DisplayNotification.this, ringtone);
mMediaPlayer.start();
mMediaPlayer.setVolume(100, 100);
}
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
while (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}
}
});
How do I get it to stop #.#
Edit:
Could the reason it doesn't stop playing be that it is a ringtone from the RingtoneManager? I don't know why this would matter but I'm grasping at straws at this point.
Edit:
Is there a way to specify a certain length of time for mediaPlayer to run and disregard the data passed to it?
did you use MediaPlayer.setLooping method
use mMediaPlayer.setLooping(false);
Since you're not calling setLooping(true); on your mMediaPlayer referenced object, looping should not be the issue here as default is set false. Make sure you're not actually calling this piece of code multiple times from outside. Put a Log line before mMediaPlayer = MediaPlayer.create(DisplayNotification.this, ringtone); and see how many times it gets logged.
use this
mMediaPlayer.setLooping(true);
I had this problem too and solved it like this:
player.setDataSource(this, ringtone);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.prepareAsync();
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(final MediaPlayer mp) {
myHandler.postDelayed(new Runnable() {
#Override
public void run() {
mp.stop();
mp.release();
}
}, mp.getDuration()); <-- Make a postDelayed runnable that has the duration of the file as its cut off. Once the song plays, it will stop the mediaPlayer.
mp.start();
}
});

How to stop media player properly , android

I have created a list of songs on click on the song i am able to play the song using MedaiPlayer. While one song is playing if the user clicks another song then i am stopping the media player and starting the player again. But I am getting illegalstateexception in reset(). Here is the code where I am getting the exception. How to stop a player properly? also why am i getting this exception. How to avoid it?
public void stopPlayer() {
try {
if (player != null) {
// Log.e("Trying to Stop "," Player ");
player.stop();
player.release();
player.reset();// causes IllegalstateException
player = null;
}
} catch (Exception e) {
player = null;
playerStatus = false;
e.printStackTrace();
}
}
try this :
player.reset();
player.release();
and also have a look at media player state diagram.
If you want to play again ,then use player.reset(),
player.release() means that it releases the player object so you have to re-intialise the player. So first you use reset() and then release(). release() is used when your player object no longer working. When your activity destroys release() method to be used for good practice.
Whenever you want to stop it:
if(player!=null)
{
if(player.isPlaying())
player.stop();
player.reset();//It requires again setDataSource for player object.
}
Whenever your player no longer to be needed:
if(player!=null)
{
if(player.isPlaying())
player.stop();
player.reset();//It requires again setDataSource for player object.
player.release();
player=null; // fixed typo.
}
Though the accepted answer works, This is a better way to achieve the task
private void stopSong() {
if(mediaPlayer!=null) {
if(mediaPlayer.isPlaying()) {
mediaPlayer.reset();// It requires again setDataSource for player object.
mediaPlayer.stop();// Stop it
mediaPlayer.release();// Release it
mediaPlayer = null; // Initialize it to null so it can be used later
}
}
}
Are you planning on reusing the player again, or are you done with the player? If you're done with the player, call release() and not reset(). If you plan on reusing the player, call reset() and not release().
reset() resets the player to its uninitialized state.
release() frees all resources associated with the player.
The Media Player State Diagram shows, and also states:
Calling stop() stops playback and causes a MediaPlayer in the Started, Paused, Prepared or PlaybackCompleted state to enter the Stopped state.
Once in the Stopped state, playback cannot be started until prepare() or prepareAsync() are called to set the MediaPlayer object to the Prepared state again.
That means, that after calling stop(), we should call prepare() on the same audio file if we wish to play it again. Otherwise calling start() again won't do anything.
As prepare() might throw exception, we should wrap it in a try-catch block, like this:
public void stopAudio(View view) {
mplayer.stop();
try {
mplayer.prepare();
} catch (IOException e) {
Log.e("stopAudio", "Unable to prepare() mplayer after stop()", e);
}
}

Mediaplayer stop is not working

I have got a MediaPlayer object as class attribute.
MediaPlayer mp;
Then I use them in my onCreate method -
mp = MediaPlayer.create(getApplicationContext(), R.raw.num1);
mp.start();
Then I try to stop it from one of my buttons clicklistener like this -
btnBack = (Button) findViewById(R.id.btn1);
btnBack.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
stopSound();
startActivity(new Intent(Five.this, Four.class));
finish();
}
});
}
public void stopSound(){
if (mp != null) {
mp.release();
mp.stop();
}
}
but the stop does not work.
What am i doing wrong?
You've already released the MediaPlayer instance. It's gone. You can't call stop() on it after you release it. If you plan to resume the sound, just remove the release() call. If you want to destroy the MediaPlayer (e.g. create a new one later with MediaPlayer.create()), remove the stop() call. You should read over this documentation pretty thoroughly; the MediaPlayer class is pretty complex. You need to understand the different states and when you can and cannot call certain methods.
In some android versions, just some ones, i had a similar issue in one app streamming radio, it worked it with:
try{
if(mp!=null && mp.isPlaying()){
mp.stop();
}
mp.release();
mp=null;
mp = new MediaPlayer(); //I needed this, maybe you dont hac
}catch(Exception e){
e.printStackTrace();
System.out.println("I can't believe you get here !");
}
you can't call release before stop
have a look at the lifecycle here http://developer.android.com/reference/android/media/MediaPlayer.html

Android: Mediaplayer stop / start playing raw resource

It now plays on first press, stops on second press or press of another sound button. If I let a sound play through I can restart it or play another sound on a single press.
My goal is for the second press of the same button to stop it, but the press of a new button to just start the new sound instead of first press of new button stopping the old sound, second press starting the new sound.
I can see why it does what it does now but am not sure how to make it work the way I want.
public void playSound(int input){
if (mp!=null && mp.isPlaying()) {
mp.stop();
mp.reset();
} else{
if (mp!=null){
mp.reset();
mp.release();
}
mp = MediaPlayer.create(Soundboard.this, input);
mp.start();
}
}
This block of code:
if (mp!=null){
mp.reset();
mp.release();
}
will never be executed. mp can only be null at this point, as it is in the else block of an if (mp != null) test. This suggests that there is a flaw in your thinking regarding the use of this method.
If a sound has played through and you press the button, then this code will execute:
mp.release();
mp = null;
Since mp was not null, the else block doesn't execute and no new sound is played. When the button is pressed a second time, mp is now null and the else block gets executed, creating a new MediaPlayer and playing the sound.

Categories

Resources