以MediaRecorder为例介绍android中,java层的native函数是如何能找到对应的jni层的函数的。 MediaRecorder.java中,生命了这样的一个方法
private static native final void native_init();

那是怎么知道是这个方法的呢? MediaRecorder.java位于android.media包中,所以native_init的全路径是android.media.MediaRecorder.native_init。显而易见,将“.”替换成“_”就是jni函数的名字了。这里说的就是JNI函数的注册问题,就是将java层的native函数和JNI层函数的具体实现关联起来。 JNI函数的注册有两种方法,一种是静态方法,需要用javah为每个声明了native函数的java类编译出的class文件生成一个头文件,另一种是动态注册,通过数据结构保存关联关系实现注册,这里主要介绍动态注册。 动态注册 动态注册需要一个数据结构去保存相关的关联关系,这个结构(在jni.h中声明)是:
typedef struct {  const char* name; //java中native函数的名字  const char* signature; //Java函数的签名信息,用字符串表示,是参数类型和返回值类型的组合  void* fnPtr; } JNINativeMethod; //JNI层函数的函数指针,void*类型

在JNI层中(android_media_MediaRecorder.cpp)是如何使用这个结构体的:
 static JNINativeMethod gMethods[] = { {"native_init","()V",(void *)android_media_MediaRecorder_native_init}, }; // This function only registers the native methods, and is called from// JNI_OnLoad in android_media_MediaPlayer.cppint register_android_media_MediaRecorder(JNIEnv *env) //什么时候会调用呢?后面介绍{return AndroidRuntime::registerNativeMethods(env,"android/media/MediaRecorder", gMethods, NELEM(gMethods));}

利用AndroidRuntime类提供的registerNativeMethods函数完成注册工作
 /** Register native methods using JNI.*//*static*/ int AndroidRuntime::registerNativeMethods(JNIEnv* env,const char* className, const JNINativeMethod* gMethods, int numMethods) //位于AndroidRuntime.cpp{return jniRegisterNativeMethods(env, className, gMethods, numMethods);} /** Register native JNI-callable methods.** "className" looks like "java/lang/String".*/int jniRegisterNativeMethods(JNIEnv* env, const char* className,const JNINativeMethod* gMethods, int numMethods) //位于JNIHelp.c{ jclass clazz;LOGV("Registering %s natives\n", className);clazz = (*env)->FindClass(env, className);if (clazz == NULL){LOGE("Native registration unable to find class '%s'\n", className); return -1;}if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0){LOGE("RegisterNatives failed for '%s'\n", className); return -1;} return 0;}

来源: <http://www.netmite.com/android/mydroid/dalvik/libnativehelper/JNIHelp.c> 实际上所有的注册工作最后就是调用: (*env)->RegisterNatives(env,clazz,gMethods,numMethods)完成。那么这些动态注册的函数是什么时候和什么地方调用的呢?其实,当Java层通过System.loadLibrary加载完JNI动态库之后,就会查找库中叫JNI_OnLoad函数,通过调用它完成动态注册的工作。
externint register_android_media_MediaRecorder(JNIEnv *env);jint JNI_OnLoad(JavaVM* vm, void* reserved) //JavaVM* vm是Java虚拟机在JNI层的对象,每一个java进程只有一个JVM{JNIEnv* env = NULL; //每一个线程有一个JNIEnv对象jint result = -1; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {LOGE("ERROR: GetEnv failed\n");goto bail;}  if (register_android_media_MediaRecorder(env) < 0) { //动态注册MediaRecorder的JNI函数LOGE("ERROR: MediaRecorder native registration failed\n");goto bail;} /* success -- return valid version number */result = JNI_VERSION_1_4; bail:return result;}

更多相关文章

  1. Android(安卓)如何添加一种锁屏方式
  2. Android(安卓)利用ViewPager、Fragment、PagerTabStrip实现多页
  3. wifi学习笔记
  4. Android(安卓)5.0输入系统分析之InputReader线程分析
  5. Android(安卓)RemoteCallbackList类
  6. Android培训班(68)dex文件打开流程
  7. android 事件传递机制
  8. Android(安卓)动态创建Drawable selector
  9. Android中获取应用程序(包)的大小-----PackageManager的使用(二)

随机推荐

  1. Android使用SQLite数据库(1)
  2. android 随手记之文件+参数上传请求
  3. 清单文件Manifest中的android:name
  4. android开发出现No Launcher activity fo
  5. 关于android原生Webview的一些属性整理(持
  6. Android开发错误信息与解决方案汇总
  7. Android之录制视频文件
  8. android 源代码研究之----frameworks----
  9. Android 不休眠 不锁屏
  10. Android for x86