简体   繁体   中英

android MediaPlayer NullPointerException

It's a bit difficult for me to troubleshoot this because I'm getting this via a crash report from someone else's android device, I have no way to ask them questions, and I've never seen it happen on my own android devices.

The crash reports says it's Android 4.1.2 and the stack trace is:

java.lang.NullPointerException
at android.media.MediaPlayer$EventHandler.handleMessage(MediaPlayer.java:2102)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5021)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
at dalvik.system.NativeStart.main(Native Method)

Unfortunately the android source code at grepcode.com doesn't seem to match up with those line numbers, so I'm not sure which thing is null.

I don't know what the user was doing when this happens, so I don't know if this happens while music or sound effects are playing or if it happens on destroy or what. I sort of suspect that it may happen during destroy. I have the following code in the activity's onDestroy method:

public void onDestroy() {
    synchronized(curPlayers) {
        for(List<MediaP> ms : curPlayers.values()) {
            synchronized(ms) {
                for(MediaP m : ms) {
                    synchronized(m) {
                        m.m.stop();
                        m.m.release();
                    }
                }
            }
        }
        curPlayers.clear();
    }
}

private static class MediaP {
    private MediaP(MediaPlayer m) {
        this.m = m;
    }

    private MediaPlayer m;
    private boolean wasPlaying = false;
}

Is there something in there that I should be doing?

Remove a call to MediaPlayer.stop() before release() . We have seen a lot of similar crashes on Nexus 4, 5, 7, 10 and Moto X. You can read more here NullPointerException in MediaPlayer$EventHandler.handleMessage

As far as I understand, at one point they switched to sending messages from stop() , and if you get unlucky enough, your release() will nullify an object right after they check that it is not null and try to call its method.

Hank and Dmitry have this almost right, but it's best to use a combined approach.

The race condition is between the internal MediaPlayer event handler and reset()/release() on Android KitKat and Lollipop releases. release() creates a race condition with all event handlers (eg onCompletion), while reset() only has a race with playback state messages. (start(), pause(), stop(), onCompletion(), onInfo() also post internal playback state messages). The NPE happens if reset()/release() is called while handling these message after the null checks but before the dereference.

To avoid this, you could:

  1. never call reset() or release(). This is not acceptable as each MediaPlayer object must be released().
  2. only call reset() or release() from an event handler (eg onCompletion, onError, etc.). This avoids the race, but is not acceptable by itself as you may need to call reset()/release() outside of an event.
  3. When calling reset()/release() outside of an event, call stop() if the media player is not stopped (eg playing or paused) to trigger the internal message and a known steady state, then wait some eg 50msec before calling release(). This is basically Hank's suggestion.

The best approach is a combination of 2 and 3.

Instead of

Remove a call to MediaPlayer.stop() before release()

I add a Thread.sleep(50) before release() and resolve this exception. It seems not only stop() will be bothered by the nullifying of release() , some other event handlers like OnCompletionListener have this problem too.

Given your specific situation, I think the target device might be running with a self-made firmware image.

The media player might be customized and not correctly programmed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM