繁体   English   中英

android MediaPlayer NullPointerException

[英]android MediaPlayer NullPointerException

我有点难以对此进行故障排除,因为我是通过其他人的Android设备的崩溃报告得到的,我无法向他们提问,而且我从未在自己的Android设备上看到它。

崩溃报告说它是Android 4.1.2,堆栈跟踪是:

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)

不幸的是,grepcode.com上的android源代码似乎与这些行号不匹配,所以我不确定哪个是null。

当发生这种情况时,我不知道用户正在做什么,所以我不知道这是在音乐或声音效果正在播放时发生,还是在发生破坏时发生了什么。 我有点怀疑它可能在毁灭期间发生。 我在activity的onDestroy方法中有以下代码:

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;
}

那里有什么我应该做的吗?

release()之前删除对MediaPlayer.stop()的调用。 我们在Nexus 4,5,7,10和Moto X上看到了很多类似的崩溃。你可以在MediaPlayer $ EventHandler.handleMessage中阅读更多NullPointerException

据我所知,有一次他们切换到从stop()发送消息,如果你不够运气,你的release()会在检查到它不为空并尝试调用其方法后立即使对象无效。

汉克和德米特里几乎没有这个,但最好采用综合方法。

竞争条件介于Android KitKat和Lollipop版本上的内部MediaPlayer事件处理程序和reset()/ release()之间。 release()使用所有事件处理程序(例如onCompletion)创建竞争条件,而reset()仅具有回放状态消息的竞争。 (start(),pause(),stop(),onCompletion(),onInfo()也发布内部回放状态消息)。 如果在空检查之后但在取消引用之前处理这些消息时调用了reset()/ release(),则会发生NPE。

为避免这种情况,您可以:

  1. 永远不要调用reset()或release()。 这是不可接受的,因为必须释放每个MediaPlayer对象()。
  2. 只从事件处理程序调用reset()或release()(例如onCompletion,onError等)。 这可以避免竞争,但是它本身是不可接受的,因为您可能需要在事件之外调用reset()/ release()。
  3. 在事件之外调用reset()/ release()时,如果媒体播放器没有停止(例如播放或暂停)以调用内部消息和已知的稳定状态,则调用stop(),然后等待一些例如50毫秒,然后再调用release ()。 这基本上是汉克的建议。

最好的方法是2和3的组合。

代替

release()之前删除对MediaPlayer.stop()的调用

我在release()之前添加了一个Thread.sleep(50) release()并解决了这个异常。 似乎不仅stop()会被release()的无效所困扰,其他一些像OnCompletionListener这样的事件处理程序也会OnCompletionListener这个问题。

鉴于您的具体情况,我认为目标设备可能正在运行自制的固件映像。

媒体播放器可能是自定义的,未正确编程。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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