相机开始预览后,多次运行Activity会导致崩溃并重新启动手机

4

我有一个Activity,它打开了Camera并在SurfaceTexture上开始预览。一切都很好,但我注意到如果我反复离开活动并返回它,几次之后,手机会冻结然后重新启动。

我已经将问题缩小到对startPreview的调用。在问题发生之前,我收到两条不祥的日志消息:

01-19 10:20:52.038: E/IMGSRV(22777): :0: __map: Map device memory failed
01-19 10:20:52.038: W/GraphicBufferMapper(22777): registerBuffer(0x70b750) failed -14 (Bad address)

有人见过这种情况吗?这是Galaxy Nexus硬件或Android 4.0的问题吗?如果是,有什么解决方法吗?

注意:我的测试是在Galaxy Nexus上的Android 4.0进行的。

编辑 - 已解决:

结果发现这是由于OpenGL导致的内存泄漏。我能在网上找到的所有示例都使用以下代码来清理OpenGL后的工作。

try { mEgl.eglDestroyContext(mEglDisplay, mEglContext); } catch (Throwable t) {}
try { mEgl.eglDestroySurface(mEglDisplay, mEglSurface); } catch (Throwable t) {}

这会泄露表面,因此在尝试若干次后,会导致OpenGL无法初始化。例如,在Nexus S上尝试32次后将失败,但在LG Optimus上只尝试8次后就会失败。

经过一些试验,我发现以下代码可以解决这个问题:

mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);

注意:在Galaxy Nexus上,我没有得到一个可以向用户显示的漂亮OpenGL错误,它似乎只是在启动预览时崩溃了。我认为这与内存有关,但上述修复方法也解决了这个问题。

你是如何解决这个问题的?在 eglDestroy* 调用之前、之后还是代替它们调用了 eglMakeCurrent() 函数? - Ed Burnette
+Ed Burnette - 在那另外两个调用之前,再加上一行。 - Grimmace
请问您知道在哪里放置这段代码吗?我的意思是“eglDestroy...”。我怎么才能访问mEgl? - Kirill Bubochkin
1个回答

2
android.hardware.Camera类的SDK文档中指出:

重要提示:调用release()方法来释放相机供其他应用程序使用。应用程序应该在onPause()中立即释放相机(并在onResume()中重新打开)。

请确认您的活动是否在onPause()中释放了相机,并在onResume()中重新打开了相机?

如果您发布代码示例,我们将更好地解决您的问题。


是的,我确定release在onPause中被调用,并且在onResume中正确地重新打开。实际上,我可以多次进入和退出Activity(如果不能这样做,我就无法这样做)。 - Grimmace
我没有使用过SurfaceTexture,但我怀疑在onPause()中有一些资源没有被释放。可能是位图或其他与图形相关的内存。 logcat中的错误消息清楚地表明内存不可用。 - mportuesisf
SurfaceTexture有一个名为release()的公共方法,文档中描述为“release()释放所有缓冲区并将SurfaceTexture置于'abandoned'状态。”您在onPause()中调用了吗? - mportuesisf
这是一个很好的观点。我会运行内存跟踪,看看是否有任何未被清理的对象。 - Grimmace
我将您的解决方案标记为正确,因为您对它是内存相关问题的评论引导我找到了解决方案的正确路径。请参见上面关于正在发生的更多详细信息。 - Grimmace
很高兴我能帮上忙,恭喜你找到了问题的真正根本原因。 - mportuesisf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接