JNI_OnLoad方法和RegisterNatives方法的结合可以做到更佳方便的注册你的jni方法。
1.在C/C++文件中实现JNI_OnLoad方法。如下:
jint JNI_OnLoad(JavaVM* pVm, void* reserved) {
//your method...
<span style="white-space:pre"> </span>return JNI_VERSION_1_6;
}
(一定要返回版本号,之前看别人博客时看到的,至于为什么,我也不清楚,猜测是C/C++方法中为了标记该方法的调用结果吧)。
2.赋值JNINativeMethod数组。JNINativeMethod是用来描述jni方法的结构。
typedef struct {
const char* name;
const char* signature;
void* fnPtr;
} JNINativeMethod;
name :java中native方法名。
signature :java中name 方法的参数和返回值的描述。
fnPtr :java中name方法在C/C++中的具体实现的方法指针。
3.在JNI_OnLoad中调用RegisterNatives方法,进行注册native方法。
下面是一段代码具体实现的例子:
jint JNI_OnLoad(JavaVM* pVm, void* reserved) {
JNIEnv* env;
if ((*pVm)->GetEnv(pVm, (void **)&env, JNI_VERSION_1_6) != JNI_OK) {
return -1;
}
JNINativeMethod nm[8];
nm[0].name = "naInit";
nm[0].signature = "(Ljava/lang/String;)I";
nm[0].fnPtr = (void*)naInit;
nm[1].name = "naSetSurface";
nm[1].signature = "(Landroid/view/Surface;)V";
nm[1].fnPtr = (void*)naSetSurface;
nm[2].name = "naGetVideoRes";
nm[2].signature = "()[I";
nm[2].fnPtr = (void*)naGetVideoRes;
nm[3].name = "naSetup";
nm[3].signature = "(II)I";
nm[3].fnPtr = (void*)naSetup;
nm[4].name = "naPlay";
nm[4].signature = "()V";
nm[4].fnPtr = (void*)naPlay;
nm[5].name = "naStop";
nm[5].signature = "()V";
nm[5].fnPtr = (void*)naStop;
jclass cls = (*env)->FindClass(env, "roman10/tutorial/android_ffmpeg_tutorial02/MainActivity");
//Register methods with env->RegisterNatives.
(*env)->RegisterNatives(env, cls, nm, 6);
return JNI_VERSION_1_6;
}
例子出自 :
http://pan.baidu.com/s/1gfjTq7L 原项目是在github上,一时找不到链接。这是我保存好的,没有修改。 里面有两个工程,第二个可以用。上面的代码是摘自第二个工程tutorial02.c中的代码。
结尾 :这种方式注册native方法很方便,更改C/C++文件和java文件都不需要用麻烦的javah去编译了。听说JNI_OnUnload方法还可以更改Framework层的模块。小白我还没有试呢。