使用ArCore时Session.update()触发段错误(SIGSEGV)崩溃
问题原因
崩溃的核心原因是ArCore Session的初始化线程与GL线程不匹配:
- 你在主线程(
onViewCreated)创建了Session,但GLSurfaceView的Renderer方法(onSurfaceCreated、onDrawFrame)运行在独立的GL线程中。 - ArCore Session需要与使用它的OpenGL上下文绑定,跨线程操作会导致Session无法正确关联GL上下文,最终在
session.update()时触发空指针访问(SIGSEGV)。 - 额外问题:
GL_TEXTURE_EXTERNAL_OES类型纹理不支持MIPMAP,你设置的GL_LINEAR_MIPMAP_LINEAR过滤模式会导致OpenGL状态错误,加剧崩溃风险。
解决方案
1. 将Session初始化移至GL线程
把Session的创建、配置逻辑移到onSurfaceCreated方法中(该方法在GL线程执行,确保Session与当前GL上下文绑定)。
2. 修正纹理过滤模式
移除MIPMAP相关的过滤设置,改用GL_LINEAR适配GL_TEXTURE_EXTERNAL_OES纹理。
3. 增加Session空值判断
在生命周期方法中判断Session是否已初始化,避免空指针调用。
修改后的完整代码
class MainFragment : Fragment(R.layout.fragment_main), GLSurfaceView.Renderer { private lateinit var surfaceView: GLSurfaceView private var session: Session? = null // 改为可空类型 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) surfaceView = view.findViewById(R.id.surface_view) surfaceView.setRenderer(this) surfaceView.renderMode = GLSurfaceView.RENDERMODE_CONTINUOUSLY // 移除主线程中的Session初始化代码 } override fun onResume() { super.onResume() session?.resume() } override fun onPause() { super.onPause() session?.pause() } override fun onDestroy() { super.onDestroy() session?.close() session = null // 清理资源 } override fun onSurfaceCreated(gl: GL10, cfg: EGLConfig) { GLES20.glClearColor(1f, 1f, 1f, 1f) // 在GL线程初始化Session val arSession = Session(requireContext()) val config = Config(arSession) arSession.configure(config) this.session = arSession val texture = intArrayOf(-1) GLES20.glGenTextures(1, texture, 0) if (texture[0] < 0) { throw Exception("Failed to Create OpenGL texture") } GLES20.glActiveTexture(GLES20.GL_TEXTURE0) GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texture[0]) GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE) GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE) // 修正为GL_LINEAR,适配EXTERNAL_OES纹理 GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR) GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR) GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0) arSession.setCameraTextureName(texture[0]) } override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) { GLES20.glViewport(0, 0, width, height) } override fun onDrawFrame(gl: GL10) { GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) session?.update() // 空值安全调用 } }
额外说明
- 手动EGL线程能正常运行,是因为你在同一个线程中完成了Session初始化、GL上下文创建和ArCore操作,线程上下文匹配。
- 确保设备已安装ArCore服务,且相机权限已正确授予(可在
onViewCreated中添加权限申请逻辑)。
内容的提问来源于stack exchange,提问作者user12653758
相关产品推荐
相关产品推荐

