You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

原生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();

额外注意事项:

  1. 关于线程Detach:如果你的代码是在android_app的系统回调线程中执行的(比如处理窗口初始化、输入事件的线程),这个线程已经被Android框架自动附着到Java虚拟机了,不要手动调用DetachCurrentThread,否则会导致崩溃。只有你自己创建的独立线程,才需要在使用完JNI后手动Detach。
  2. 简化Context获取:其实ARCore的ArSession_create可以直接接收Activity实例作为Context,你可以跳过getApplicationContext()这一步,直接传activityInstance进去,这样更简单也减少出错概率。
  3. JNI签名匹配:一定要确保方法签名完全正确,比如getApplicationContext()的签名是()Landroid/content/Context;,如果写错一个字符,GetMethodID就会返回NULL。

内容的提问来源于stack exchange,提问作者Tobias

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:30:16