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

JNI访问ContactsContract$Data的EXTRA_ADDRESS_BOOK_INDEX字段报错求助

问题分析与解决方案

嘿,这个问题的核心原因其实很简单——你找错了常量所属的类!

咱们来拆解一下:

  • 你成功访问的VISIBLE_CONTACTS_ONLY确实是android.provider.ContactsContract$Data(也就是ContactsContract.Data内部类)的静态字段,所以你的JNI代码找对了类,自然能正常工作。
  • 但EXTRA_ADDRESS_BOOK_INDEX这个常量并不属于ContactsContract.Data内部类,它是外层android.provider.ContactsContract类的静态成员!你错误地在ContactsContract$Data类里查找这个字段,导致GetStaticFieldID返回了无效的fieldID,后续调用GetStaticObjectField就会触发JNI错误崩溃。

修正后的JNI代码

把查找的类改成android.provider.ContactsContract就可以解决问题了:

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
    JNIEnv* env = nullptr;
    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return JNI_ERR; // 处理获取环境失败的情况
    }

    // 注意这里的类是外层的ContactsContract,不是内部类Data
    jclass clazz = env->FindClass("android/provider/ContactsContract");
    if (clazz == nullptr) {
        return JNI_ERR; // 处理找不到类的情况
    }

    jfieldID fieldID = env->GetStaticFieldID(clazz, "EXTRA_ADDRESS_BOOK_INDEX", "Ljava/lang/String;");
    if (fieldID == nullptr) {
        env->DeleteLocalRef(clazz);
        return JNI_ERR; // 处理找不到字段的情况
    }

    jobject field = env->GetStaticObjectField(clazz, fieldID);
    // 这里可以添加对field的使用逻辑,比如转换成C字符串等

    env->DeleteLocalRef(clazz);
    env->DeleteLocalRef(field); // 记得释放局部引用,避免内存泄漏
    return JNI_VERSION_1_6;
}

额外建议

  • 永远不要忽略JNI调用的返回值检查!比如FindClass、GetStaticFieldID都可能返回nullptr,提前处理这些情况可以避免莫名其妙的崩溃,也方便调试。
  • 记得释放JNI局部引用,尤其是在JNI_OnLoad这种生命周期较长的方法里,防止内存泄漏。

补充一下你遇到的报错信息:
java_vm_ext.cc:534] JNI DETECTED ERROR IN APPLICATION: static jfieldID 0x6fd191b0 not valid for class java.lang.Class<android.provider.ContactsContract$Data>
这个报错其实已经提示你了:你拿到的fieldID对于ContactsContract$Data类是无效的,本质就是因为这个字段根本不在这个类里。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:39:53