【发布时间】:2013-08-26 19:46:08
【问题描述】:
我知道这是一个常见问题,但是此堆栈跟踪显示其他问题。您可以看到,即使在 surfaceCreated 内部调用了 setDisplay(holder),它仍然会抛出 IllegalArgumentException。这也不是罕见的例外,昨天在约 3,000,000 次剪辑视图中发生了约 125,000 次。我可以向您保证,mCurrentPlayer 也已正确初始化。
表面创建:
@Override
public void surfaceCreated(SurfaceHolder holder) {
mIsSurfaceCreated = true;
mCurrentPlayer.setDisplay(holder);
}
表面销毁:
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsSurfaceCreated = false;
// Could be called after player was released in onDestroy.
if (mCurrentPlayer != null) {
mCurrentPlayer.setDisplay(null);
}
}
堆栈跟踪:
java.lang.IllegalArgumentException: The surface has been released
at android.media.MediaPlayer._setVideoSurface(Native Method)
at android.media.MediaPlayer.setDisplay(MediaPlayer.java:660)
at com.xxx.xxx.view.VideoPlayerView.surfaceCreated(VideoPlayerView.java:464)
at android.view.SurfaceView.updateWindow(SurfaceView.java:543)
at android.view.SurfaceView.access$000(SurfaceView.java:81)
at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:169)
at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:590)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1644)
at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2505)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:4945)
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:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
关于其他可能出现问题的任何想法? SurfaceHolder 是否可能会破坏后台线程上的表面,然后等待主线程(当前由 surfaceCreated 占用)完成它的块,然后才能在主线程上调用 surfaceDestroyed(我什至不认为锁可以修)?还有什么?
更新 -- 在深入挖掘之后,我发现了导致“表面已被释放”为 thrown 的原因:
哪些引用android_view_Surface_getSurface可以找到here:
这是我缺乏 C++ 知识的痛处,它看起来像是试图锁定表面,如果不能,返回的表面将是 null。一旦返回为null,IllegalArgumentException 将被抛出。
【问题讨论】:
-
您是否在后台线程上进行任何渲染?你的surfaceDestroyed的实现是什么? (请注意,surfaceDestroyed 的文档说:“如果您有一个直接访问表面的渲染线程,则必须确保该线程在从该函数返回之前不再接触表面。”。)
-
没有背景渲染,
Surface仅供MediaPlayer用于显示视频。一旦mp.setDisplay(surface)被调用,我就不会接触表面。我也用 surfaceDestroyed 更新了我的帖子。注意根据android_media_MediaPlayer.cpp,如果jsurface是null这个异常不会抛出。 -
你能分享这个项目吗?问题很可能不在您显示的代码中,而是在应用程序的其他部分。
-
手机从锁定状态恢复时是否可能出现问题?
-
我过去在使用 Android VideoViews/MediaPlayers 时遇到过类似的问题。事实证明,底层的 SurfaceView 正在收集垃圾。我通过向 MediaPlayer 添加一个 onPreparedLister 来解决它,然后在我使用它时在我的类中持有对它的显式引用。也许这会有所帮助。
标签: android android-mediaplayer surfaceholder