Reputation: 2526
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
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
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