原生Android C++应用集成ARCore遇SIGINT:Context获取失败问题
解决原生C++ Android应用中ARCore获取Context的崩溃问题
我来帮你排查下这个问题,你代码里的核心问题是调用实例方法时传错了对象,再加上缺少JNI调用的错误检查,导致Context获取失败,最终触发ARCore创建会话时的崩溃。
你的代码里的几个关键错误:
- 实例方法调用参数错误:
getApplicationContext()是Activity的实例方法,必须传入Activity的实例对象(也就是_pAndroidApp->activity->instance),但你传的是_pAndroidApp->activity->clazz——这是jclass类型的类引用,不是实例,直接用它调用实例方法必然导致指针异常。 - 缺少JNI调用的错误检查:你看到的
activityClass是0x0000000000000001,这是无效的jclass引用,说明FindClass或GetObjectClass调用已经失败了,但你没有做任何检查就继续执行后续代码,自然会引发一系列错误。 - 线程附着后的检查缺失:
AttachCurrentThread调用可能失败,但你没有判断返回值,直接使用env也会有风险。
修正后的完整代码(带错误检查)
// 先确保android_app和Activity实例有效 if (!_pAndroidApp || !_pAndroidApp->activity) { // 这里可以加日志输出,比如__android_log_print(ANDROID_LOG_ERROR, "ARCore", "Invalid android_app or activity"); return; } JNIEnv* env = nullptr; // 尝试将当前线程附着到Java虚拟机 int attachResult = _pAndroidApp->activity->vm->AttachCurrentThread(&env, nullptr); if (attachResult != 0 || !env) { // __android_log_print(ANDROID_LOG_ERROR, "ARCore", "Failed to attach thread to VM"); return; } jobject activityInstance = _pAndroidApp->activity->instance; if (!activityInstance) { // __android_log_print(ANDROID_LOG_ERROR, "ARCore", "Invalid activity instance"); _pAndroidApp->activity->vm->DetachCurrentThread(); return; } // 获取Activity的类引用,用GetObjectClass更可靠(基于实例获取类) jclass activityClass = env->GetObjectClass(activityInstance); if (!activityClass) { // __android_log_print(ANDROID_LOG_ERROR, "ARCore", "Failed to get activity class"); _pAndroidApp->activity->vm->DetachCurrentThread(); return; } // 获取getApplicationContext方法的ID,注意方法签名要完全匹配 jmethodID getContextMethod = env->GetMethodID(activityClass, "getApplicationContext", "()Landroid/content/Context;"); if (!getContextMethod) { // __android_log_print(ANDROID_LOG_ERROR, "ARCore", "Failed to get getApplicationContext method ID"); env->DeleteLocalRef(activityClass); _pAndroidApp->activity->vm->DetachCurrentThread(); return; } // 调用实例方法获取Context,第一个参数必须是Activity实例 jobject contextObj = env->CallObjectMethod(activityInstance, getContextMethod); if (!contextObj) { // __android_log_print(ANDROID_LOG_ERROR, "ARCore", "Failed to get application context"); env->DeleteLocalRef(activityClass); _pAndroidApp->activity->vm->DetachCurrentThread(); return; } // 尝试创建ARCore会话 ArStatus sessionStatus = ArSession_create(env, contextObj, &ar_session_); if (sessionStatus != AR_SUCCESS) { // __android_log_print(ANDROID_LOG_ERROR, "ARCore", "Failed to create AR session, status: %d", sessionStatus); } // 释放JNI局部引用,避免内存泄漏 env->DeleteLocalRef(activityClass); env->DeleteLocalRef(contextObj); // 注意:如果是在android_app的回调线程(比如APP_CMD_INIT_WINDOW)中,线程已经被框架附着,不要手动Detach! // 只有你自己创建的新线程,才需要在使用完后调用DetachCurrentThread // _pAndroidApp->activity->vm->DetachCurrentThread();
额外注意事项:
- 关于线程Detach:如果你的代码是在
android_app的系统回调线程中执行的(比如处理窗口初始化、输入事件的线程),这个线程已经被Android框架自动附着到Java虚拟机了,不要手动调用DetachCurrentThread,否则会导致崩溃。只有你自己创建的独立线程,才需要在使用完JNI后手动Detach。 - 简化Context获取:其实ARCore的
ArSession_create可以直接接收Activity实例作为Context,你可以跳过getApplicationContext()这一步,直接传activityInstance进去,这样更简单也减少出错概率。 - JNI签名匹配:一定要确保方法签名完全正确,比如
getApplicationContext()的签名是()Landroid/content/Context;,如果写错一个字符,GetMethodID就会返回NULL。
内容的提问来源于stack exchange,提问作者Tobias
相关产品推荐
相关产品推荐

