zoukankan      html  css  js  c++  java
  • Android jni c/c++线程通过CallVoidMethod调用java函数出现奔溃问题

    最近在移植网络摄像机里的p2p库到android平台,需要用到jni,最近在c线程了调用java函数的时候
    出现一个问题,假如在同一个线程调用java函数是没问题的,但在一个c线程了调用java函数就出现奔
    溃问题,下面就直接贴c线程里调用java函数的流程代码吧:

    步骤1. 我这里的应用是,java处理视频播放,在java层写需要调用的函数,例如:

    private void recvData(String devid, byte[] data, int nDataType, int nLen){
          Log.i(TAG, "recv id:"+devid+", type:"+nDataType+", len:"+nLen);
    }

    步骤2. 在native-lib.cpp中jni层代码如下(注意这是c++代码):

    JavaVM* local_JavaVM = NULL;
    jobject j_obj = NULL;
    jmethodID j_mid = NULL;
    JNIEXPORT void JNICALL Java_com_p2p_test_MainActivity_InitP2P (JNIEnv *env, jobject jobj) {    
        jclass clazz = env->GetObjectClass(jobj);
        j_obj = env->NewGlobalRef(jobj);//**这里是关键**
        //jclass clazz = env->GetObjectClass(jobj);//之前是这样写,一直导致奔溃
        j_mid = env->GetMethodID(clazz, "recvData", "(Ljava/lang/String;[BII)V");
        if(j_mid == NULL)
        {
            LOGE("Error GetMethodID");
        }
    }
    
    jint JNI_OnLoad(JavaVM* vm, void* reserved)
    {
        LOG("JNI_OnLoad");
        local_JavaVM = vm ;
    
       JNIEnv* env = 0;
        jint ret = -1;
    
       if (vm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK)
        {
            LOGE("JNI_OnLoad error");
            goto onLoadError;
        }
    
        ret = JNI_VERSION_1_6;
    
        onLoadError:
        return ret;
    }

    步骤3.我这里的应用p2p在收到视频流数据的时候,需要将视频数据传送到java层,例如其他c文件xxxxx.c收到视频数据,在调用CallVoidMethod可以调用java函数(注意这是c代码)。

    extern jmethodID j_mid ;
    extern jobject j_obj ;
    extern JavaVM* local_JavaVM;
    JNIEnv *env;
    **//这是一个线程**
    void dataRecvThread()
    {    
        int ret = 0;
        int status = (*local_JavaVM)->GetEnv(local_JavaVM, (void **)&(env), JNI_VERSION_1_6);
        if(status < 0)
        {
            status = (*local_JavaVM)->AttachCurrentThread(local_JavaVM, &(env), NULL);//**这是关键地方**
            if(status < 0)
            {
                return NULL;
            }
            ret= 1;
        }
    
       ..............//接受视频代码省略
       if(j_obj != NULL && j_mid != NULL)
        {                
                int nDataType = data.frameType;
                int nLen = data.len;
                jstring jdevid = (*env)->NewStringUTF(env, "ARD1W45LKUYHAAAA1E");
                jbyteArray jbuff = (*env)->NewByteArray(env, nLen);
                (*env)->CallVoidMethod(env, j_obj , j_mid , jdevid, jbuff, nDataType, nLen);
                (*env)->DeleteLocalRef(env, jbuff);
                (*env)->DeleteLocalRef(env, jdevid);
         }
         .............//代码省略
    
        if(ret)
        {
            (*local_JavaVM)->DetachCurrentThread(local_JavaVM);
        }
    }

    这样就可以成功调用了

  • 相关阅读:
    ASP.NET Core 基于JWT的认证(二)
    ASP.NET Core 基于JWT的认证(一)
    C#数据Encrypt加密Encrypt解密的算法使用--非对称算法RSACryptoServiceProvider
    C#数据Encrypt加密Encrypt解密的算法使用
    C# 实现winform自动悬浮
    测试winform自动悬浮
    C#实现图像拖拽以及锚点缩放功能
    C# Microsoft.Office.Interop.Owc11 导出excel文件
    Docker修改daemon.json后无法启动的问题
    Kubernetes命名空间
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/10596767.html
Copyright © 2011-2022 走看看