0
点赞
收藏
分享

微信扫一扫

2,Android研发岗面试复盘总结

西风白羽 2022-01-21 阅读 68

//定义一个JNINativeMethod数组,其成员就是MediaScanner(MS)中所有native函数的一一对应关系。
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进程只有一个JavaVM
JNIEnv
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层也是区别对待这二者的。先来看基本数据类型的转换。

JavaNative类型符号属性字长
booleanjboolean无符号8位
bytejbyte无符号8位
charjchar无符号8位
shortjshot有符号16位
intjint有符号16位
longjlong有符号64位
floatjfloat有符号32位
doublejdouble有符号64位


short|jshot|有符号|16位
int|jint|有符号|16位
long|jlong|有符号|64位
float|jfloat|有符号|32位
double|jdouble|有符号|64位

举报

相关推荐

0 条评论