0

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.

Aniruddh Parihar
  • 3,072
  • 3
  • 21
  • 39
Văn Quyết
  • 2,384
  • 14
  • 29
  • _"and that error still displayed in log cat"_ The exception is thrown because of that error, not the other way around. So you're not going to get rid of the error log by catching the exception. – Michael Nov 21 '18 at 09:25
  • @Michael But I still can't catch that error – Văn Quyết Nov 21 '18 at 09:31

2 Answers2

1

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.

Aaron
  • 3,764
  • 2
  • 8
  • 25
  • I've tried both `prepare` and `prepareAsync`. They worked fine in most time. But sometimes did not (rarely). And I would like to handle these case – Văn Quyết Nov 21 '18 at 09:26
  • Understood, `prepare` then `start` should work fine, but there are also other cases that can throw `IllegalStateException`, please refer https://developer.android.com/reference/android/media/MediaPlayer#Valid_and_Invalid_States and check your code again. :) – Aaron Nov 21 '18 at 09:35
  • Thank you. I forgot to release the media players when the activity stops. And this error occurred after an exact number of times I restart the activity – Văn Quyết Nov 24 '18 at 06:07
0

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

Văn Quyết
  • 2,384
  • 14
  • 29