Android JNI 在C++多线程调用Java的回调函数

java 接口定义:

java 复制代码
public interface Callback {
    void onResult(int status, String message);
}

java 设置回调:

java 复制代码
public class Sample {
    static {
        System.loadLibrary("sample_core_jni");
    }

    public static native int process(long handle, String message);


    public static void onCallback(int status, String message) {
        if (mCallback != null) {
            mCallback.onResult(status, message);
        }
    }

    private static Callback mCallback;

    public static void setCallback(Callback callback) {
        if (callback == null) {
            throw new NullPointerException("callback can not be null");
        }
        mCallback = callback;
    }

// 添加其他native函数
....
}

JNI 注册回调函数:

cpp 复制代码
#include <jni.h>
#include <iostream>
 
// 全局引用,确保JNI环境可以访问
JavaVM *g_VM;
jclass gCallbackClassSample = nullptr;
jmethodID gOnCallbackMethodID = nullptr;


JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = nullptr;
    jint result = -1;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return result;
    }

    //JavaVM是虚拟机在JNI中的表示,等下再其他线程回调java层需要用到
    env->GetJavaVM(&g_VM);

    register_fields(env);

    LOGI("JNI OnLoad result : %d", result);
    return JNI_VERSION_1_6;
}

register_fields(JNIEnv *env) {

//注册Java回调函数所在的类及回调函数
}



int ChatCallback(int status, const char *output) {
    JNIEnv *env;
    bool mNeedDetach = false;
    //获取当前native线程是否有没有被附加到jvm环境中
    int getEnvStat = (*g_VM).GetEnv( (void **)&env, JNI_VERSION_1_6);
    if (getEnvStat == JNI_EDETACHED) {
        //如果没有, 主动附加到jvm环境中,获取到env
        if (g_VM->AttachCurrentThread(&env, NULL) != JNI_OK) {
            LOGE("ChatCallback failed to attach current thread");
        }
        mNeedDetach = JNI_TRUE;
    }
    jString j_out = native_message_to_java_message(env, output);

    if (fields.chat_result_callback != nullptr) {
        env->CallStaticVoidMethod(gCallbackClassSample, gOnCallbackMethodID, (int)status, j_out);
    }
    //释放当前线程
    if(mNeedDetach) {
        g_VM->DetachCurrentThread();
    }
    env = NULL;

    return 0;
}

extern "C"
JNIEXPORT void JNICALL
Java_com_example_yourapp_process(JNIEnv *env, jlong handle, jString message) {

     //
     const char* c_message = ...
     //该函数为异步函数
     int err = Chat(handle, c_message, ChatCallback);
}
相关推荐
谷哥的小弟4 分钟前
Spring Framework源码解析——ApplicationContextInitializer
java·spring·源码
布谷歌7 分钟前
在java中实现c#的int.TryParse方法
java·开发语言·python·c#
cooldream200912 分钟前
当代 C++ 的三大技术支柱:资源管理、泛型编程与模块化体系的成熟演进
开发语言·c++
while(1){yan}18 分钟前
网络基础知识
java·网络·青少年编程·面试·电脑常识
Ulana22 分钟前
计算机基础10大高频考题解析
java·人工智能·算法
黄俊懿29 分钟前
【深入理解SpringCloud微服务】Seata(AT模式)源码解析——@GlobalTransactional注解与@globalLock生效的原理
java·spring cloud·微服务·云原生·架构·系统架构·架构师
Queenie_Charlie33 分钟前
数字去重(set)
数据结构·c++·set
wheelmouse778834 分钟前
一个优雅、通用、零侵入的 CSV 导出工具类(Java 实战)
java·开发语言
cike_y1 小时前
JavaWeb-Request应用与Cookie&[特殊字符]️Session
java·开发语言·安全·java安全
Ayanami_Reii1 小时前
区间不同数的个数-树状数组/线段树/莫队/主席树
数据结构·c++·算法·线段树·树状数组·主席树·莫队