Android下如何通过JNI方法向上提供接口总结


1 什么是JNI

JNI是Java Native Interface的缩写,即Java本地接口.从Java1.1开始,JNI标准成为Java平台的一部分,它允许java代码和用其它语言编写的代码进行交互.JNI是本地编程接口,它使得在Java虚拟机(VM)内部运行的Java代码能够与用其他编程语言(如C,C++和汇编语言)的应用程序和库进行交互操作.

在Android中提供的JNI的方式,让Java程序可以调用C语言程序。Android中很多Java类都具有native接口,这些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类有对应关系。这种关系是习惯上的写法,而不是强制的。

在Android中实现的JNI库,需要连接动态库libnativehelper.so.

2 注册JNI方法

在Android源码根目录/frameworks/base/services/jni/目录下有一个onload.cpp文件,其内容如下:

  1. /* 
  2.  * Copyright (C) 2009 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. #include "JNIHelp.h"   
  18. #include "jni.h"   
  19. #include "utils/Log.h"   
  20. #include "utils/misc.h"   
  21.   
  22. namespace android {  
  23. int register_android_server_AlarmManagerService(JNIEnv* env);  
  24. int register_android_server_BatteryService(JNIEnv* env);  
  25. int register_android_server_InputApplicationHandle(JNIEnv* env);  
  26. int register_android_server_InputWindowHandle(JNIEnv* env);  
  27. int register_android_server_InputManager(JNIEnv* env);  
  28. int register_android_server_LightsService(JNIEnv* env);  
  29. int register_android_server_PowerManagerService(JNIEnv* env);  
  30. int register_android_server_UsbDeviceManager(JNIEnv* env);  
  31. int register_android_server_UsbHostManager(JNIEnv* env);  
  32. int register_android_server_VibratorService(JNIEnv* env);  
  33. int register_android_server_SystemServer(JNIEnv* env);  
  34. int register_android_server_location_GpsLocationProvider(JNIEnv* env);  
  35. int register_android_server_connectivity_Vpn(JNIEnv* env);  
  36. int register_android_server_HelloService(JNIEnv *env);  
  37. };  
  38.   
  39. using namespace android;  
  40.   
  41. extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)  
  42. {  
  43.     JNIEnv* env = NULL;  
  44.     jint result = -1;  
  45.   
  46.     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {  
  47.         LOGE("GetEnv failed!");  
  48.         return result;  
  49.     }  
  50.     LOG_ASSERT(env, "Could not retrieve the env!");  
  51.   
  52.     register_android_server_PowerManagerService(env);  
  53.     register_android_server_InputApplicationHandle(env);  
  54.     register_android_server_InputWindowHandle(env);  
  55.     register_android_server_InputManager(env);  
  56.     register_android_server_LightsService(env);  
  57.     register_android_server_AlarmManagerService(env);  
  58.     register_android_server_BatteryService(env);  
  59.     register_android_server_UsbDeviceManager(env);  
  60.     register_android_server_UsbHostManager(env);  
  61.     register_android_server_VibratorService(env);  
  62.     register_android_server_SystemServer(env);  
  63.     register_android_server_location_GpsLocationProvider(env);  
  64.     register_android_server_connectivity_Vpn(env);  
  65.     register_android_server_HelloService(env);  
  66.   
  67.     return JNI_VERSION_1_4;  
  68. }  
onload.cpp文件上部分为注册函数的声明,下部分为调用各种注册函数,而这些注册函数就是JNI方法的注册函数! 正有通过这些注册函数,上层才有可能调用注册的JNI方法.

这些注册函数是由同目录下的其他.cpp文件中实现,如上面的register_android_server_HelloService(env)这个函数是在com_android_service_HelloService.cpp文件中实现的.那么编译器又是如何知道这点的呢? 答案当然是Android.mk这个文件,打开这个文件,其内容如下:

  1. LOCAL_PATH:= $(call my-dir)  
  2. include $(CLEAR_VARS)  
  3.   
  4. LOCAL_SRC_FILES:= \  
  5.     com_android_server_AlarmManagerService.cpp \  
  6.     com_android_server_BatteryService.cpp \  
  7.     com_android_server_InputApplicationHandle.cpp \  
  8.     com_android_server_InputManager.cpp \  
  9.     com_android_server_InputWindowHandle.cpp \  
  10.     com_android_server_LightsService.cpp \  
  11.     com_android_server_PowerManagerService.cpp \  
  12.     com_android_server_SystemServer.cpp \  
  13.     com_android_server_UsbDeviceManager.cpp \  
  14.     com_android_server_UsbHostManager.cpp \  
  15.     com_android_server_VibratorService.cpp \  
  16.     com_android_server_location_GpsLocationProvider.cpp \  
  17.     com_android_server_connectivity_Vpn.cpp \  
  18.     com_android_server_HelloService.cpp \  
  19.     onload.cpp  
  20.   
  21. LOCAL_C_INCLUDES += \  
  22.     $(JNI_H_INCLUDE) \  
  23.     frameworks/base/services \  
  24.     frameworks/base/core/jni \  
  25.     external/skia/include/core  
  26.   
  27. LOCAL_SHARED_LIBRARIES := \  
  28.     libandroid_runtime \  
  29.     libcutils \  
  30.     libhardware \  
  31.     libhardware_legacy \  
  32.     libnativehelper \  
  33.     libsystem_server \  
  34.     libutils \  
  35.     libui \  
  36.     libinput \  
  37.     libskia \  
  38.     libgui \  
  39.     libusbhost  
  40.   
  41. ifeq ($(WITH_MALLOC_LEAK_CHECK),true)  
  42.     LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK  
  43. endif  
  44.   
  45. LOCAL_MODULE:libandroid_servers  
  46.   
  47. include $(BUILD_SHARED_LIBRARY)  
在LOCAL_SRC_FILE中给出了所有实现文件(cpp文件)的路径,因此编译就能找到各个注册函数对应的实现文件了.

接下来让我们来看看其中一个注册函数的具体实现过程是如何的,比如:register_android_server_HelloService(env),打开com_android_service_HelloService.cpp文件,其下有注册函数的实现代码,如下:

  1. int register_android_server_HelloService(JNIEnv *env) {  
  2.         return jniRegisterNativeMethods(env, "com/android/server/HelloService", method_table, NELEM(method_table));  
  3. }  
其中jniRegisterNativeMethods为注册JNI方法函数,此函数在JNI方法使用中非常重要,此函数的第二个参数为对应着java类即HelloService.java的文件名,第三个参数为注册的方法表:
  1. /*JNI方法表*/  
  2. static const JNINativeMethod method_table[] = {  
  3.     {"init_native""()Z", (void*)hello_init},  
  4.     {"setVal_native""(I)V", (void*)hello_setVal},  
  5.     {"getVal_native""()I", (void*)hello_getVal},  
  6. };  
  • 1
  • 2
  • 下一页

相关内容