Văn Quyết
Văn Quyết

Reputation: 2526

Not able to catch the IllegalStateException of MediaPlayer

My code looks like this:

MediaPlayer mp = new MediaPlayer();
mp.setDataSource( "http://.../abc.mp3" );
mp.setOnPreparedListener( ... mp.start(); ... );
mp.prepareAsync();

Real code has checked if mp is prepared before it starts. Mostly it works fine. But sometimes (if weak connection) it still encounters this error:

MediaPlayer: Error (-38,0)
MediaPlayerNative: start called in state 0, mPlayer(0x7424863b40)

So, I decided to catch it:

try {
    mp.start();
} catch (IllegalStateException e) {
    Toast.makeText(...).show();
} catch (Throwable e) {
    Toast.makeText(...).show();
}

But this code does not work, I cannot catch any exception, and that error still displayed in log cat.

Upvotes: 0

Views: 139

Answers (2)

Văn Quyết
Văn Quyết

Reputation: 2526

I've tried hard to find out what is wrong. And I found that I didn't release the media players when the activity stops. Because the media players are still located in memory so after an exact number of times I restart the activity, the new media players cannot load. And in another activity I use SoundPool, it also cannot load more streams.

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

    for (int i = 0; i < mediaPlayerMap.size(); i++) {
        int key = mediaPlayerMap.keyAt(i);
        MediaPlayer mp = mediaPlayerMap.get(key);
        if (mp != null) {
            mp.release();
            mp = null;
        }
    }
}

Logcat:

E/AudioFlinger: no more track names available
E/AudioFlinger: createTrack_l() initCheck failed -12; no control block?
E/AudioTrack: AudioFlinger could not create track, status: -12
E/SoundPool: Error creating AudioTrack

Refs:

SoundPool error: no more track names available

https://groups.google.com/forum/#!msg/android-platform/tyITQ09vV3s/jwNdyI2-7iYJ

Upvotes: 0

Aaron
Aaron

Reputation: 3894

You should use prepare instead of prepareAsync if you intend to call start immediately afterward. You get IllegalStateException because it may be out-of-sync when you call start, as it prepares asynchronously and has not finished the transaction yet.

According to prepareAsync:

Prepares the player for playback, asynchronously. After setting the datasource and the display surface, you need to either call prepare() or prepareAsync(). For streams, you should call prepareAsync(), which returns immediately, rather than blocking until enough data has been buffered.

And prepare:

Prepares the player for playback, synchronously. After setting the datasource and the display surface, you need to either call prepare() or prepareAsync(). For files, it is OK to call prepare(), which blocks until MediaPlayer is ready for playback.

Again, prepare allows you to call start immediately because it runs synchronously. However, there may be other cases that can throw IllegalStateException, please refer to its valid and invalid states.

Upvotes: 1

Related Questions