写点什么

2,ndk 开发教程

用户头像
Android架构
关注
发布于: 刚刚

static JNINativeMethod gMethods[] = {......{"native_init","()V",(void *)android_media_MediaScanner_native_init},......//注册 JNINativeMethod 数组 int register_android_media_MediaScanner(JNIEnv *env){//调用 AndoridRuntime 的 registerNativeMethods 函数,第二个参数表明是 Java 中哪个类 return AndoridRuntime::registerNativeMethods(env,"android/media/MediaScanner",gMethods,NELEM(gMethods));}}


AndroidRunTime 类提供了一个 registerNativeMethods 函数来完成注册工作,下面来看 registerNativeMethods 的实现


initAndroidRuntime::registerNativeMethods(JNIEnv* env,const char* classNmae,const JNINativeMethod* gMethods,int numMethods){//调用 jniRegisterNativeMethods 函数完成注册 return jniRegisterNativeMethods(env,className,gMeghods,numMethods);}


其中 jniRegisterNativeMethods 是 Android 平台中为了方便 JNI 使用而提供的一个帮助函数,其代码如下所示:


int jniRegisterNativeMethods(JNIEnv* env,const char* classNmae,const JNINativeMethod* gMethods,int numMethods){jclass classzz;clazz = (*env)->FindClass(env,className);......//实际上调用 JNIEnv 的 RegisterNatives 函数完成注册的 if((*env)->RegisterNatives(env,clazz,gMethods,numMethods)<0){return -1;}return 0;}


其实动态注册的工作,只用两个函数就能完成。


/**


  • env 指向一个 JNIEnv 结构体,它非常重要,后面会讨论它。classname 为对应的 Java 类名,由于 JNINativeMethod 中使用的函数名并非全路径名,所以要指明是哪个类。*/jclass clazz = (*env)->FindClass(env,classNmae);//调用 JNIEnv 的 RegisterNatives 函数,注册关联关系。(*env)->RegisterNatives(env,clazz,gMethods,numMethods);


所以在自己的 JNI 层代码中使用这种弄方法,就可以完成动态注册了。这些动态注册的函数在什么时候和什么地方被调用呢?


当 Java 层通过 System.loadLibrary 加载完 JNI 动态库后,紧接着会查找该库中一个叫 JNI_Onload 的函数。如果有,就调用它,而动态注册的工作就是在这里完成的。


所以,如果想使用动态注册方法,就必须实现 JNI_Onload 函数,只有这个函数中才有机会完成动态注册的工作。静态注册的方法则没有这个方法,但建议大家也实现这个 JNI_OnLoad 函数,因为有一些初始化工作是可以在这里做的。


那么,libmedia_jni.so 的 JNI_OnLoad 函数是在哪里实现的额呢?由于多媒体系统很多地方都使用了 JNI,所以把它放到了 android_media_MediaPlayer.cpp 中了,代码如下


jint JNI_OnLoad(JavaVM* vm, void* /* reserved /){//该函数的第一个参数类型为 JavaVM,这可是虚拟机在 JNI 层的代表,每个 Java 进程只有一个 JavaVMJNIEnv env = NULL;jint result = -1;


if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {ALOGE("ERROR: GetEnv failed\n");goto bail;}assert(env != NULL);


if (register_android_media_ImageWriter(env) != JNI_OK) {ALOGE("ERROR: ImageWriter native registration failed");goto bail;}//动态注册 MediaScanner 的 JNI 函数 if (register_android_media_ImageReader(env) < 0) {ALOGE("ERROR: ImageReader native registration failed");goto bail;}....../* success -- return valid version number */result = JNI_VERSION_1_4;bail:return result;}


JNI 层代码中一般要包含 jni.h 这个头文件。Andorid 源码中提供了一个帮助头文件 JNIHelp.h,它内部其实就包含了 jni.h,所有我们在自己的代码中直接包含这个 JNIHelp.h 即可

数据类型转换

Java 数据类型分为基本数据类型和引用数据类型两种,JNI 层也是


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


区别对待这二者的。先来看基本数据类型的转换。



用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
2,ndk开发教程