JNI在子线程中调用Java方法回传数据

场景:在JNI中需要一直不断的读取某个文件,开启了一条线程,当读取数据到的时候需要在线程中向java返回数据。

实现步骤:

一、当so库加载的时候,在c的实现文件记录一个全局的JavaVM

static JavaVM *g_jvm = NULL;
//当加载.so库时该方法会被VM自动调用,每个*.so库只能有一个这个入口,即使没有定义的也会有一个默认的方法,
jint JNI_OnLoad(JavaVM* vm, void* reserved){
    g_jvm=vm;//获取一个全局的VM指针
    LOGD("so库加载成功了........>>>>");
    return JNI_VERSION_1_6;
}

二、开启线程,并记录全局变量

//打开hid文件
JNIEXPORT jint JNICALL Java_com_HidUtil_startRead
  (JNIEnv *env, jobject jobj)
 {

    HidCallback *hid_callback = new HidCallback(g_jvm, env, env->NewGlobalRef(jobj));
    env->GetJavaVM(&g_jvm);//保存全局变量
    is_reading = 1;

    if(!read_thread){
       int err = pthread_create(&read_thread, NULL, read_data, hid_callback);
       //注意上面的第4个参数hid_callback,由于子线程中不能直接访问主线程中的变量,这里
       //专门搞了一个hid_callback变量,HidCallback里面保存了jvm,当前对象jobj等变量,当
       //需要调用java方法的时候,我们可以通过HidCallback找到java对象,然后调用之
       return 1;
    }
    return 0;
}

三、在线程中调用java方法

void *read_data(void *data)
{

    HidCallback *hid_callback = (HidCallback *) data;//在线程中拿到jvm java对象等
    JNIEnv *env;
    //让当前线程与虚拟机联系起来,否则java虚拟机是无法感知C中创建的线程
    g_jvm->AttachCurrentThread(&env, 0);
    
    ......
    jbyteArray jbarray = env->NewByteArray(read_size - 1);
    env->SetByteArrayRegion(jbarray, 0, read_size - 1,((jbyte*) buf)+1);
    env->CallVoidMethod(hid_callback->jobj, hid_callback->jmid, jbarray);
    .......

    g_jvm->DetachCurrentThread();

}

四、HidCallback的实现:

头文件:

#pragma once
#ifndef JNITHREAD_WLLISTENER_H
#define JNITHREAD_WLLISTENER_H

#include <jni.h>

class HidCallback {

public:

    JavaVM* jvm;//java虚拟机
    _JNIEnv *jenv;//native线程env对象
    jobject jobj;//全局对象
    jmethodID jmid;//java 方法id,可以根据实际情况创建多个。

public:

    HidCallback(JavaVM* vm, _JNIEnv *jenv, jobject obj);
    ~HidCallback();
};


#endif //JNITHREAD_WLLISTENER_H


实现文件部份:


#include "hid-callback.h"
#include <android/log.h>

#define LOGD(FORMAT,...) __android_log_print(ANDROID_LOG_DEBUG,"ywl5320",FORMAT,##__VA_ARGS__);
#define LOGE(FORMAT,...) __android_log_print(ANDROID_LOG_ERROR,"ywl5320",FORMAT,##__VA_ARGS__);

HidCallback::HidCallback(JavaVM *vm, _JNIEnv *env, jobject obj) {
    jvm = vm;
    jenv = env;
    jobj = obj;
    jclass clz = env->GetObjectClass(jobj);
    if(!clz)
    {
        LOGE("get jclass wrong");
        return;
    }
    jmid = env->GetMethodID(clz, "onReadData", "([B)V");
    if(!jmid)
    {
        LOGE("get jmethodID wrong");
        return;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值