1

Here is my source code

private MediaPlayer mP;

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mP = MediaPlayer.create(getApplicationContext(),R.raw.nintendo);
}

@Override
protected void onResume() {

    super.onResume();
    try {

        mP.prepareAsync();
    } catch (IllegalStateException e) {

        e.printStackTrace();
    }
    mP.setOnPreparedListener(new OnPreparedListener() {

        @Override
        public void onPrepared(MediaPlayer mp) {

            mP.seekTo(0);
            mP.start();
        }
    });
}

@Override
protected void onPause() {

    super.onPause();
    mP.stop();
    mP.release();
}

Here is what I get in Logcat when i try running this enter image description here enter image description here

Line 64: mP.stop();

This Logcat output occurs when i do this following sequence, Launch -> Homescreen->Go back to app -> Homescreen

Now I know that the IllegalStateException occurs when you try to do an invalid state change. From, http://developer.android.com/reference/android/media/MediaPlayer.html, I know that a valid state change would be from "start to stop" or "stop to stop". I thought the logic I have in my code represents a valid state change though(from start in onPause to stop/release in onPause). I debugged a bit further and realized that after i went to the homescreen and back to the app, onPrepared was not getting called.... I didn't understand this either because I called mP.prepareAsync() before hand(asynchronous to avoid blocking this main ui thread) before hand. Shouldn't onPrepared be triggered after all the sound resources have been gathered?

I checked out a few other threads Couldn't be this one Android Media Player because I constructed the MediaPlayer fine. And again here android MediaPlayer not playing mp3 file didn't address my issue because I constructed the MediaPlayer fine and it played the sound the first time i launched the app.

Does anyone see an issue with this code?

Community
  • 1
  • 1
committedandroider
  • 8,711
  • 14
  • 71
  • 126

1 Answers1

1

Firstly, don't call prepareAsync() on a MediaPlayer you've created using MediaPlayer.create(), as prepare() is taken care of for you.

From the docs:

http://developer.android.com/reference/android/media/MediaPlayer.html

MediaPlayer.onCreate()...

Convenience method to create a MediaPlayer for a given resource id. On success, prepare() will already have been called and must not be called again.

Since you're releasing your MediaPlayer in onPause(), if you want to play again in onResume(), you're going to have to create a new MediaPlayer using MediaPlayer.onCreate().

I suggest that you simply don't release the MediaPlayer in onPause(), call mP.pause() instead of mP.stop(), and then you don't have to worry about recreating/preparing the MediaPlayer in onResume().

Here's an example:

private MediaPlayer mMediaPlayer;
private boolean mIsPrepared;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mMediaPlayer = MediaPlayer.create(this, R.raw.raw1);
    mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mp) {
            mIsPrepared = true;
        }
    });
}

@Override
protected void onResume() {
    super.onResume();

    if (mMediaPlayer != null && mIsPrepared) {
        mMediaPlayer.seekTo(0);
        mMediaPlayer.start();
    }
}

@Override
protected void onPause() {
    super.onPause();

    if(mMediaPlayer!=null && mIsPrepared){
        mMediaPlayer.pause();
    }
}
Tim Malseed
  • 6,003
  • 6
  • 48
  • 66
  • So once you release(release resources associated with MediaPlayer), you can't prepare it to play again? – committedandroider Dec 01 '14 at 00:30
  • I chose to release in inPause because of this line in the docs "r. In particular, whenever an Activity of an application is paused (its onPause() method is called), or stopped (its onStop() method is called), this method should be invoked to release the MediaPlayer object, unless the application has a special need to keep the object around." Oh so I do have a special need to keep it around - to play it again – committedandroider Dec 01 '14 at 00:31
  • If you're using MediaPlayer.create(context, rawRes) then no - you can't 'prepare it again' AFAIK. If you've created your MediaPlayer by other means, you can call prepare().. You would have to create the media player, pass it a dataSource (an asset file descriptor pointing to your raw resource), and then prepare it. Then if you stop & release it later, you can pass it a new datasource and prepare it again. But you would effectively just be recreating it anyway. – Tim Malseed Dec 01 '14 at 00:37
  • I don't know if what you're doing would fall under that 'special need' to keep the MediaPlayer object around. If you want the playback to stop when the activity is paused, then I don't see why you can't release the MediaPlayer and recreate it later. Probably the easiest way to handle all this would be to put your create() code into onResume instead of onCreate - creating and playing a new MediaPlayer every time onResume is called - and destroying it onPause(). – Tim Malseed Dec 01 '14 at 00:39
  • To me, recreating each time just wastes too much memory on the heap – committedandroider Dec 01 '14 at 18:28
  • Sorry this is kinda unrelated but how much time did it take for you to develop the Shuttle Music Player? – committedandroider Dec 01 '14 at 18:30