Reputation: 4045
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?
Upvotes: 5
Views: 2923
Reputation: 811
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 (e.g. 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:
The best approach is a combination of 2 and 3.
Upvotes: 2
Reputation: 211
Instead of
Remove a call to
MediaPlayer.stop()
beforerelease()
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.
Upvotes: 1
Reputation: 733
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.
Upvotes: 5
Reputation: 10368
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.
Upvotes: 0