JNI|在子线程中获得JNIEnv|AttachCurrentThread

15 篇文章 1 订阅

转自: https://blog.csdn.net/stefzeus/article/details/6792518  

A JNI interface pointer (JNIEnv*) is passed as an argument for each native function mapped to a Java method, allowing for interaction with the JNI environment within the native method.This JNI interface pointer can be stored, but remains valid only in the current thread. Other threads must first call AttachCurrentThread()to attach themselves to the VM and obtain a JNI interface pointer. Once attached, a native thread works like a regular Java thread running within a native method. The native thread remains attached to the VM until it callsDetachCurrentThread() to detach itself.[3]

void Call_Back_Invoke( void *user,int notify_id, unsigned int param )
{
    bool  isAttacked = false;
    JNIEnv* env;
    if(NULL == jni_tmpc.g_JVM)
    {
        LOGE("g_JVM == NULL");
        return ;
    }
    int status = (jni_tmpc.g_JVM)->GetEnv((void **) &env, jni_tmpc.g_JNI_VERSION);
 
    if(status < 0) {
        LOGD("callback_handler:failed to get JNI environment assuming native thread"); 
        status = jni_tmpc.g_JVM->AttachCurrentThread(&env, NULL);
        if(status < 0) {
           LOGE("callback_handler: failed to attach current thread");
            return;
        }
        isAttacked = true;
    }
 
    switch( notify_id )
    {
       case...
         ...
    }    
    if(isAttacked) 
    {
        (jni_tmpc.g_JVM)->DetachCurrentThread();
    }    
    LOGE("jni Call_Back_Invoke(1) notify_id = %d",notify_id );
}

 

补充:

PlatinumMedia中的实例代码:

NPT_Result MediaRenderer::DoJavaCallback(int type, const char *param1,
                                         const char *param2,
                                         const char *param3) {
    if (g_vm == NULL) {
        LOGE("g_vm = NULL!!!");
        return NPT_FAILURE;
    }
    int status;
    JNIEnv *env = NULL;
    bool isAttach = false;
    status = g_vm->GetEnv((void **) &env, JNI_VERSION_1_6);
    if (status != JNI_OK) {
        status = g_vm->AttachCurrentThread(&env, NULL);
        if (status < 0) {
            LOGE("MediaRenderer::DoJavaCallback Failed: %d", status);
            return NPT_FAILURE;
        }
        isAttach = true;
    }
    jstring jParam1 = NULL;
    jstring jParam2 = NULL;
    jstring jParam3 = NULL;
    jclass inflectClass = g_callbackClass;
    jmethodID inflectMethod = g_callbackMethod;
    if (inflectClass == NULL || inflectMethod == NULL) {
        goto end;
    }
    jParam1 = env->NewStringUTF(param1);
    jParam2 = env->NewStringUTF(param2);
    jParam3 = env->NewStringUTF(param3);
    env->CallStaticVoidMethod(inflectClass, inflectMethod, type, jParam1, jParam2, jParam3);
    env->DeleteLocalRef(jParam1);
    env->DeleteLocalRef(jParam2);
    env->DeleteLocalRef(jParam3);
    end:
    if (env->ExceptionOccurred()) {
        env->ExceptionDescribe();
        env->ExceptionClear();
    }
    if (isAttach) {
        g_vm->DetachCurrentThread();
    }
    return NPT_SUCCESS;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Android开发中,我们可以利用JNI技术来创建线程并进行数据的回调操作。以下是具体的步骤: 1. 在Java层编写一个调用JNI方法的类,其中定义了一个用于回调的接口,例如`MyCallback`。 2. 在JNI层编写一个与Java中定义的接口对应的C函数,可以命名为`callbackFromNative`。 3. 在JNI层创建一个线程,在线程中进行数据处理,并通过调用`callbackFromNative`函数来回调数据给Java层。 4. 在Java层实现回调接口的方法,即在回调方法中处理JNI传递给Java层的数据。 下面是具体的实现步骤: 首先,在Java层创建一个调用JNI方法的类,例如`NativeCallbackUtil`,其中定义了一个回调接口`MyCallback`: ```java public class NativeCallbackUtil { public interface MyCallback { void onCallback(String data); } public static native void startThread(MyCallback callback); } ``` 然后,在JNI层实现回调函数`callbackFromNative`和创建线程的方法`startThread`: ```c++ #include <jni.h> #include <pthread.h> static JavaVM* g_jvm = nullptr; static jobject g_callback = nullptr; extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { g_jvm = vm; return JNI_VERSION_1_6; } extern "C" JNIEXPORT void JNICALL Java_com_example_NativeCallbackUtil_startThread(JNIEnv *env, jobject instance, jobject callback) { g_callback = env->NewGlobalRef(callback); pthread_t thread; pthread_create(&thread, nullptr, [](void*)->void* { JNIEnv* env; g_jvm->AttachCurrentThread(&env, nullptr); jclass callbackClass = env->GetObjectClass(g_callback); jmethodID callbackMethod = env->GetMethodID(callbackClass, "onCallback", "(Ljava/lang/String;)V"); for (int i = 0; i < 10; ++i) { // 数据处理... jstring data = env->NewStringUTF("Hello from native"); env->CallVoidMethod(g_callback, callbackMethod, data); env->DeleteLocalRef(data); } g_jvm->DetachCurrentThread(); return nullptr; }, nullptr); } ``` 最后,在Java层实现回调接口的方法: ```java public static void onCallback(String data) { Log.d(TAG, "Received data from native: " + data); } public static void main(String[] args) { NativeCallbackUtil.startThread(() -> onCallback("Hello from Java")); } ``` 这样,我们就实现了在JNI层创建线程并回调数据给Java层的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值