Android下如何通过JNI方法向上提供接口总结
来源:互联网 发布:淘宝邻家好货有好处吗 编辑:程序博客网 时间:2024/05/28 15:36
Android下如何通过JNI方法向上提供接口总结
参考文献:
http://blog.csdn.net/luoshengyang/article/details/6575988
http://www.androidmi.com/Androidkaifa/rumen/201005/633.html
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文件,其内容如下:
01
/*
02
* Copyright (C) 2009 The Android Open Source Project
03
*
04
* Licensed under the Apache License, Version 2.0 (the "License");
05
* you may not use this file except in compliance with the License.
06
* You may obtain a copy of the License at
07
*
08
* http://www.apache.org/licenses/LICENSE-2.0
09
*
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
}
这些注册函数是由同目录下的其他.cpp文件中实现,如上面的 register_android_server_HelloService(env)这个函数是在 com_android_service_HelloService.cpp文件中实现的.那么编译器又是如何知道这点的呢? 答案当然是Android.mk这个文件,打开这个文件,其内容如下:
01
LOCAL_PATH:= $(call my-
dir
)
02
include $(CLEAR_VARS)
03
04
LOCAL_SRC_FILES:= \
05
com_android_server_AlarmManagerService.cpp \
06
com_android_server_BatteryService.cpp \
07
com_android_server_InputApplicationHandle.cpp \
08
com_android_server_InputManager.cpp \
09
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
}
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
};
如hello_setVal函数的实现:
01
/*通过硬件抽象层定义的硬件访问接口设置硬件寄存器val的值*/
02
static
void
hello_setVal(JNIEnv* env, jobject clazz, jint value) {
03
int
val = value;
04
LOGI(
"Hello JNI: set value %d to device."
, val);
05
if
(!hello_device) {
06
LOGI(
"Hello JNI: device is not open."
);
07
return
;
08
}
09
10
hello_device->set_val(hello_device, val);
11
}
01
/*通过硬件抽象层定义的硬件模块打开接口打开硬件设备*/
02
static
inline
int
hello_device_open(
const
hw_module_t* module,
struct
hello_device_t** device) {
03
return
module->methods->open(module, HELLO_HARDWARE_MODULE_ID, (
struct
hw_device_t**)device);
04
}
05
/*通过硬件模块ID来加载指定的硬件抽象层模块并打开硬件*/
06
static
jboolean hello_init(JNIEnv* env, jclass clazz) {
07
hello_module_t* module;
08
09
LOGI(
"Hello JNI: initializing......"
);
10
if
(hw_get_module(HELLO_HARDWARE_MODULE_ID, (
const
struct
hw_module_t**)&module) == 0) {
11
LOGI(
"Hello JNI: hello Stub found."
);
12
if
(hello_device_open(&(module->common), &hello_device) == 0) {
13
LOGI(
"Hello JNI: hello device is open."
);
14
return
0;
15
}
16
LOGE(
"Hello JNI: failed to open hello device."
);
17
return
-1;
18
}
19
LOGE(
"Hello JNI: failed to get hello stub module."
);
20
return
-1;
21
}
3 方法列表说明
关于static const JNINativeMethod method_table[]方法列表的原型如下:
1
typedef
struct
{
2
const
char
* name;
3
const
char
* signature;
4
void
* fnPtr;
5
} JNINativeMethod;
第一个变量name是Java中函数的名字。第二个变量signature,用字符串是描述了函数的参数和返回值.第三个变量fnPtr是函数指针,指向C函数。
其中比较难以理解的是第二个参数,例如:"()V"
"(II)V"
"(Ljava/lang/String;Ljava/lang/String;)V"
实际上这些字符是与函数的参数类型一一对应的。"()" 中的字符表示参数,后面的则代表返回值。例如"()V" 就表示void Func();
"(II)V" 表示 void Func(int, int);
具体的每一个字符的对应关系如下
字符 Java类型 C类型
V void void
Z jboolean boolean
I jint int
J jlong long
D jdouble double
F jfloat float
B jbyte byte
C jchar char
S jshort short
数组则以"["开始,用两个字符表示
[I jintArray int[]
[F jfloatArray float[]
[B jbyteArray byte[]
[C jcharArray char[]
[S jshortArray short[]
[D jdoubleArray double[]
[J jlongArray long[]
[Z jbooleanArray boolean[]
上面的都是基本类型。如果Java函数的参数是class,则以"L"开头,以";"结尾.中间是用"/" 隔开的包及类名。而其对应的C函数名的参数则为jobject. 一个例外是String类,其对应的类为jstring
Ljava/lang/String; String jstring
Ljava/net/Socket; Socket jobject
如果JAVA函数位于一个嵌入类,则用$作为类名间的分隔符。
例如 "(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z"
- Android下如何通过JNI方法向上提供接口总结
- Android下如何通过JNI方法向上提供接口总结
- Android下如何通过JNI方法向上提供接口总结
- Android下如何通过JNI方法向上提供接口总结
- Android下如何通过JNI方法向上提供接口总结
- Android下如何通过JNI方法向上提供接口总结
- Android下如何通过JNI方法向上提供接口总结
- Android下如何通过JNI方法向上提供接口总结
- Android下如何通过JNI方法向上提供接口总结
- Android下如何通过JNI方法向上提供接口总结
- Android中JNI如何向上层提供接口总结
- Android中JNI如何向上层提供接口总结
- Android中HAL如何向上层提供接口总结
- Android中HAL如何向上层提供接口总结-hw_device_t
- Android中HAL如何向上层提供接口总结-hw_device_t
- Android中HAL如何向上层提供接口总结
- Android中HAL如何向上层提供接口总结 .
- Android中HAL如何向上层提供接口总结 .
- win7中隐藏 Thumbs.db
- poj-2299-逆序数-归并排序
- play vim of how to switch to normal mode
- asp.net GridView 删除时弹出确认对话框(包括内容提示)
- 如何在Form中使用描述性弹性域 .
- Android下如何通过JNI方法向上提供接口总结
- Linux内核中的系统调用
- MyEclipse 不常用的组合快捷键
- Android深入浅出之Binder机制
- 根据描述性弹性域的标题查找描述性弹性域表和列 .
- 堆栈2
- 离线地图制作工具
- 关于typedef的用法总结
- ViewPager的使用方法