Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Approaches to Android MediaPlayer state mismatch error on isPlaying()?

Tags:

java

android

I'm trying to figure out how to address the Android MediaPlayer's "state mismatch" error which is occasionally thrown during audio playback when I try to pause.

As discussed in this question, there is a known issue with the Android MediaPlayer occasionally throwing an error on a call to isPlaying()

The result is a call to pause() or isPlaying() causes the MediaPlayer to stop responding to requests until it is reset.

Here's a log from when this error occurs:

I/MusicPlaybackService﹕ I got a pause message
E/MediaPlayer[Native]﹕ internal/external state mismatch corrected

Here's a github bug with more details related to this issue.

My current solution is incredibly ugly:

/**
 * Pause the currently playing song.
 */
private synchronized void pause() {
    try{
        // this is a hack, but it seems to be the most consistent way to address the problem
        // this forces the media player to check its current state before trying to pause.
        int position = mp.getCurrentPosition();
        mp.seekTo(position);
        mp.start();
        mp.pause();
    } catch (Exception e){
        Log.w(TAG, "Caught exception while trying to pause ", e);
    }
    updateNotification();
}

My theory is that the MediaPlayer loses track of its own state, and calling start() and seekTo() before pausing will force the MediaPlayer to reset its concept of its own state.

This solution is hacky and appears to be causing other issues.

Google appears to have marked the open issue for this behavior as Obsolete.

I'm testing this on an LG G3 running android 5.0.1.

Thus my question is: What should I do about this? Is there a better way to force the MediaPlayer to check its own state before pausing?

like image 652
T.D. Smith Avatar asked Aug 23 '15 16:08

T.D. Smith


1 Answers

Here's the best solution I've been able to come up with. It appears to address the issue with pausing, and hasn't caused any unintended side effects:

private synchronized void pause() {
    // Sometimes the call to isPlaying can throw an error "internal/external state mismatch corrected"
    // When this happens, I think the player moves itself to "paused" even though it's still playing.
    try{
        // this is a hack, but it seems to be the most consistent way to address the problem
        int position = mp.getCurrentPosition();
        mp.stop();
        mp.prepare();
        mp.seekTo(position);
    } catch (Exception e){
        Log.w(TAG, "Caught exception while trying to pause ", e);
    }
}

This solution forces a reset of the state machine without resetting the entire media player, and without calling play.

Annotated state machine for reference:

enter image description here

like image 74
T.D. Smith Avatar answered Sep 21 '22 03:09

T.D. Smith