Android NDK JNI C++ <10> android .so中JNI_OnLoad函数

前面介绍了那个结构体,为这一篇文章做了铺垫,这一篇进一步介绍so在整个加载过程中的流程.

当android的VM(虚拟机)调用System.LoadLibrary函数去加载.so文件时,首先会调用JNI_OnLoad函数。

这个函数有两个功能:

1. 告诉VM,该C组件使用哪一个版本的JNI。如果so文件没有使用JNI_OnLoad,则VM默认c组件使用最老的jni 1.1的版本。由于新版本的jni有许多新的功能,如果是默认1.1最老的版本的话,则不能使用新功能。

---------

是不是应该在JNI_OnLoad中设置版本号?如果JNI_OnLoad中没有这个过程,是不是还是没有发挥作用?

(透过返回值来设置,例如return JNI_VERSION_1_4;)

2. c组件的开发者可以在JNI_OnLoad这里进行c组件的一些初始化的工作。因为在加载so文件时,首先会去调用这个JNI_OnLoad函数

 

与JNI_OnLoad 对应的有 JNI_OnUnload.

JNI_OnUnload做对应的清理工作。

 

==============

在实际的项目,经常会有从android 上层透过jni调用c组件的code,或者在c组件中透过jni调用android上层的code。

要实现这两个目的,就要搞清楚系列的流程。

一 先总结从android 上层透过jni调用c组件的流程

   有两种方法。

二 在c组件中透过jni调用android上层

 

====

IP 3088项目的jni部分流程

jni_onLoad 调用

TcMediaEngineRegisterNativeMethods(venv);  //实现从android 上层透过jni调用c组件的code

TcMediaEngineRegisterNativeMethods中调用

TcMediaEngineResolveJavaClass(env);   //在c组件中透过jni调用android上层的code。

 

TcMediaEngineRegisterNativeMethods的具体实现

1.定义 本地方法 和 上层方法 的映射表

static JNINativeMethod sMethods[] =
{
    {"Init", "()I",(void *)native_media_engine_core_Init},
    {"Stop", "()I",(void *)native_media_engine_core_stop},
    {"Echo", "(I)I",(void *)native_media_engine_core_echo},
    {"StartTone","(I)I",(void *)native_media_engine_core_starttone},
    {"StopTone","()I",(void *)native_media_engine_core_stoptone},
    {"setVideoWindowId","(Ljava/lang/Object;)V",(void *)native_media_engine_core_set_video_windowid},
    {"setVideoPreviewWindowId","(Ljava/lang/Object;)V",(void *)native_media_engine_core_set_video_preview_windowid},
    {"PlayDTMF", "(IC)I",(void *)native_media_engine_core_play_dtmf},
    {"StopDTMF", "(I)I",(void *)native_media_engine_core_stop_dtmf},
    {"SetRingFile", "(Ljava/lang/String;)V",(void *)native_media_engine_core_set_ringing_file},
    {"SetRingbackFile", "(Ljava/lang/String;)V",(void *)native_media_engine_core_set_ringback_file},
    {"MuteMIC", "(I)V",(void *)native_media_engine_core_mute_mic},
    {"SetAGC", "(I)V",(void *)native_media_engine_core_set_agc},
    {"SetJitterBuffer", "(II)V",(void *)native_media_engine_core_set_jitterbuffer},
    {"SetVideoSize", "(II)V",(void *)native_media_engine_core_set_videosize},
    {"SetPlaybackGain", "(F)V",(void *)native_media_engine_core_set_play_gain},    
      {"GetVideoDevice", "()I",(void *)native_media_engine_core_get_video_device},   
    {"SetVideoDevice", "(I)V",(void *)native_media_engine_core_set_video_device},
        {"UpdateVideoCamera" , "()V",(void *)native_media_engine_core_update_video_camera},
};

2 做初始化工作

const char* classPathName="com/tecom/v2ware/MediaEngineCoreManager";

int iSize=sizeof(sMethods)/sizeof(sMethods[0]);

3. 通过jni 环境变量找到上层对应的java class

clazz = env->FindClass(classPathName);
    if(!clazz)
    {
        ME_LOGE("'%s' is not found.", classPathName);
        return;
    }

4. 透过jni 环境变量 注册本地方法

 

if(env->RegisterNatives(clazz,sMethods,iSize) < 0)
{
     ME_LOGE("TcMediaEngineRegisterNativeMethods failed for '%s'", classPathName);
     return ;
}

 

 

TcMediaEngineResolveJavaClass 的具体实现

1. 透过jni环境变量找到 java 类

theclass = env->FindClass(AndroidApi5WrapperPath);

 

2. 透过jni环境变量和上一步得到的class ,进一步得到要调用的方法

jmethodID method = env->GetStaticMethodID(theclass ,"selectNearestResolutionAvailable", "(III)[I");

 

3. 透过jni环境变量和上一步得到的method ,调用方法

jobject resArray = env->CallStaticObjectMethod(helperClass, method, ((AndroidWebcamConfig*)d->webcam->data)->id, d->requestedSize.width, d->requestedSize.height);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值