注册native函数有两种方法:静态注册和动态注册。1、静态注册方法根据函数名找到对应的JNI函数:Java层调用函数时,会从对应的JNI中寻找该函数,如果没有就会报错,如果存在则会建立一个关联联系,以后在调用时会直接使用这个函数,这部分的操作由虚拟机完成。静态方法就是根据函数名来遍历java和jni函数之间的关联,而且要求jni层函数的名字必须遵循特定的式,其缺点在于:1)javah生成的jni层函数特别长;2)初次调用native函数时要根据名字搜索对应的jni层函数来建立关联联系,这样影响效率。2、动态注册方法JNI 允许你提供一个函数映射表,注册给Jave虚拟机,这样Jvm就可以用函数映射表来调用相应的函数,就可以不必通过函数名来查找需要调用的函数了。Java与JNI通过JNINativeMethod的结构来建立联系,它在jni.h中被定义,其结构内容如下:typedef struct {const char* name;const char* signature;void* fnPtr;} JNINativeMethod;第一个变量name是Java中函数的名字。第二个变量signature,用字符串是描述了函数的参数和返回第三个变量fnPtr是函数指针,指向C函数。当java通过System.loadLibrary加载完JNI动态库后,紧接着会查找一个JNI_OnLoad的函数,如果有,就调用它,而动态注册的工作就是在这里完成的。1)JNI_OnLoad()函数JNI_OnLoad()函数在VM执行System.loadLibrary(xxx)函数时被调用,它有两个重要的作用:指定JNI版本:告诉VM该组件使用那一个JNI版本(若未提供JNI_OnLoad()函数,VM会默认该使用最老的JNI 1.1版),如果要使用新版本的JNI,例如JNI 1.4版,则必须由JNI_OnLoad()函数返回常量JNI_VERSION_1_4(该常量定义在jni.h中) 来告知VM。初始化设定,当VM执行到System.loadLibrary()函数时,会立即先呼叫JNI_OnLoad()方法,因此在该方法中进行各种资源的初始化操作最为恰当,2)RegisterNativesRegisterNatives在AndroidRunTime里定义syntax:jint RegisterNatives(jclass clazz, const JNINativeMethod* methods,jint nMethods)3、在android中加入自定义的native函数JNI在Android层次结构中的作用如下图所示: 在Android中,主要的JNI代码在以下的路径中:Android源码根目录/frameworks/base/core/jni/这个路径中的内容将被编译成库libandroid_runtime.so,这就是一个普通的动态库,被放置在目标系统的/system/lib目录中.除此之外,Android还包含其他的JNI库,例如,媒体部分的JNI目录frameworks/base/media/jni/中,被编译成库libmedia_jni.so.JNI中的各个文件实际上就是C的普通文件,其命名一般和支持的Java类有对应关系。这种关系是习惯上的写法,而不是强制的。1)注册JNI方法在Android源码根目录/frameworks/base/services/jni/目录下有一个onload.cpp文件,加入 jni函数申明和jni函数注册方法#include "JNIHelp.h" #include "jni.h" #include "utils/Log.h" #include "utils/misc.h" namespace android { int register_android_server_AlarmManagerService(JNIEnv* env); int register_android_server_BatteryService(JNIEnv* env); int register_android_server_InputApplicationHandle(JNIEnv* env); int register_android_server_InputWindowHandle(JNIEnv* env); int register_android_server_InputManager(JNIEnv* env); int register_android_server_LightsService(JNIEnv* env); int register_android_server_PowerManagerService(JNIEnv* env); int register_android_server_UsbDeviceManager(JNIEnv* env); int register_android_server_UsbHostManager(JNIEnv* env); int register_android_server_VibratorService(JNIEnv* env); int register_android_server_SystemServer(JNIEnv* env); int register_android_server_location_GpsLocationProvider(JNIEnv* env); int register_android_server_connectivity_Vpn(JNIEnv* env); int register_android_server_HelloService(JNIEnv *env); //此处加入自定义jni函数申明}; using namespace android; extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint result = -1; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { LOGE("GetEnv failed!"); return result; } LOG_ASSERT(env, "Could not retrieve the env!"); register_android_server_PowerManagerService(env); register_android_server_InputApplicationHandle(env); register_android_server_InputWindowHandle(env); register_android_server_InputManager(env); register_android_server_LightsService(env); register_android_server_AlarmManagerService(env); register_android_server_BatteryService(env); register_android_server_UsbDeviceManager(env); register_android_server_UsbHostManager(env); register_android_server_VibratorService(env); register_android_server_SystemServer(env); register_android_server_location_GpsLocationProvider(env); register_android_server_connectivity_Vpn(env); register_android_server_HelloService(env); //jni方法注册 return JNI_VERSION_1_4; } onload.cpp文件上部分为注册函数的声明,下部分为调用各种注册函数,而这些注册函数就是JNI方法的注册函数! 正是通过这些注册函数,上层才能调用注册的JNI方法.以register_android_server_HelloService为例,来看一个注册函数的具体实现过程是如何的。打开com_android_service_HelloService.cpp文件2)加入注册函数的实现代码,如下:int register_android_server_HelloService(JNIEnv *env) { return jniRegisterNativeMethods(env, "com/android/server/HelloService", method_table, NELEM(method_table)); } #其中jniRegisterNativeMethods为注册JNI方法函数,#此函数的第二个参数为对应着java类即HelloService.java的文件名,第三个参数为注册的方法表3)加入jni方法表 static const JNINativeMethod method_table[] = { {"init_native", "()Z", (void*)hello_init}, {"setVal_native", "(I)V", (void*)hello_setVal}, {"getVal_native", "()I", (void*)hello_getVal}, }; 4)方法表内各个接口的实现代码static void hello_setVal(JNIEnv* env, jobject clazz, jint value) { val = value; LOGI("Hello JNI: set value %d to device.", val); } static jint hello_getVal(JNIEnv* env, jobject clazz) { LOGI("Hello JNI: get value %d from device.", val); return val; } static jboolean hello_init(JNIEnv* env, jclass clazz) { LOGI("Hello JNI: initializing......"); return -1; } 完整代码如下:namespace android{ int val; static void hello_setVal(JNIEnv* env, jobject clazz, jint value) { val = value; LOGI("Hello JNI: set value %d to device.", val); } static jint hello_getVal(JNIEnv* env, jobject clazz) { LOGI("Hello JNI: get value %d from device.", val); return val; } static jboolean hello_init(JNIEnv* env, jclass clazz) { LOGI("Hello JNI: initializing......"); return -1; } static const JNINativeMethod method_table[] = { {"init_native", "()Z", (void*)hello_init}, {"setVal_native", "(I)V", (void*)hello_setVal}, {"getVal_native", "()I", (void*)hello_getVal}, }; int register_android_server_HelloService(JNIEnv *env) { return jniRegisterNativeMethods(env, "com/android/server/HelloService", method_table, NELEM(method_table)); } }出处:
推荐整理分享深入了解android平台的jni---注册native函数(深入了解是啥意思),希望有所帮助,仅作参考,欢迎阅读内容。
文章相关热门搜索词:深入了解求助者时,首先要进行工作是,深入了解对方的36个问题,深入了解英语,深入了解的高级表达,深入了解android系统,深入了解的高级表达,深入了解android系统,深入了解的高级表达,内容如对您有帮助,希望把文章链接给更多的朋友!
Android 接口回调实例 Android接口回调方法处处涉及到,比如常用的Button点击事件就是一个接口回调,可见掌握熟练使用接口回调方法的重要性。接口回调的简单解释就是:比
Android中Context详解 大家好,今天给大家介绍下我们在应用开发中最熟悉而陌生的朋友-----Context类,说它熟悉,是应为我们在开发中时刻的在与它打交道,例如:Service、Broa
Afinal AfinalAfinal是什么