JNI是Java Native Interface的缩写,译为Java本地接口。它允许Java代码和其他语言编写的代码进行交互。在android中提供JNI的方式,让Java程序可以调用C语言程序。android中很多Java类都具有native接口,这些接口由本地实现,然后注册到系统中。以下这个图可以很好的说明问题:

android主要的JNI代码放在以下的路径中:frameworks/base/core/jni/,这个路径中的内容被编译成库libandroid_runtime.so,这是个普通的动态库,被放置在目标系统的/system/lib目录下。此外,android还有其他的JNI库。JNI中的各个文件,实际上就是普通的C++源文件;在android中实现的JNI库,需要连接动态库libnativehelper.so。

(1)以Android源码根目录/frameworks/base/services/jni/目录下有一个onload.cpp文件。onload.cpp文件上部分为注册函数的声明,下部分为注册函数,只有通过这些注册函数,上层才有可能调用注册的JNI方法。这些注册函数是由同目录下的其他.cpp文件中实现,如register_android_server_VibratorService这个函数是在com_android_server_VibratorService.cpp文件中实现的。注册代码如下:

int register_android_server_VibratorService(JNIEnv *env){    return jniRegisterNativeMethods(env, "com/android/server/VibratorService",            method_table, NELEM(method_table));}

其中jniRegisterNativeMethods为注册JNI方法函数,此函数的第二个参数对应着java类即VibratorService.java的文件名(即VibratorService.java (frameworks\base\services\java\com\android\server)),第三个参数为注册的方法表:

static JNINativeMethod method_table[] = {    { "vibratorExists", "()Z", (void*)vibratorExists },    { "vibratorOn", "(J)V", (void*)vibratorOn },    { "vibratorOff", "()V", (void*)vibratorOff }};

这里定义的三个函数就可以直接在VibratorService.java中被调用,只不过在该文件头部要以native申明函数。这三个函数的实现是在Vibrator.c (hardware\libhardware_legacy\vibrator)中,不同的JNI函数实现方法和地方是不同的。

(2)方法列表说明,static const JNINativeMethod method_table[]方法列表的原型如下:

typedef struct {const char* name;const char* signature;void* fnPtr;} JNINativeMethod;

Andorid使用了一种Java 和 C 函数的映射表数组,并在其中描述了函数的参数和返回值。第一个变量name是Java中函数的名字;第二个变量signature,用字符串描述了函数的参数和返回值;第三个变量fnPtr是函数指针,指向C函数。其中比较难以理解的是第二个参数,例如:()Z (J)V ()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类位于一个嵌入类,则用$作为类名间的分隔符,比如:"android/os/FileObserver$ObserverThread"

===========================================================================================================

下面举一个实例,运行Java程序直接调用WINDOWS的对话框:

(1)新建一个TestNew.java文件,输入以下内容:

public class TestNew {public static native void hello(String msg);static{System.loadLibrary("TestNew");}/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubhello("hello,kitty!");}}

在配置好java的环境变量C:\Program Files\Java\jdk1.6.0_13\bin之后,用javac TestNew.java命令就生成了TestNew.class文件。
(2)在命令行中用javah TestNew,在class文件的基础上生成TestNew.h(就是jni代理stub的接口),内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class TestNew */#ifndef _Included_TestNew#define _Included_TestNew#ifdef __cplusplusextern "C" {#endif/* * Class:     TestNew * Method:    hello * Signature: (Ljava/lang/String;)V */JNIEXPORT void JNICALL Java_TestNew_hello  (JNIEnv *, jclass, jstring);#ifdef __cplusplus}#endif#endif

(3)在VC 6.0中新建一个win32 Dynamic-Link Library项目,项目名是TestNew。DLL类型选择a simple dll project,之后打开项目所在的文件目录,把步骤(2)生成的TestNew.h拷贝到此目录。点击左边中间的FileView,切换到文件浏览模式,在Header Files上点击右键,选择Add Files to Folder…。选择TestNew.h文件,点击OK。

打开StdAfx.h文件,再最后面添加几行语句,#include <jni.h>,#include "TestNew.h",加完如下:

#include <windows.h>#include <jni.h>#include "TestNew.h"

打开TestNew.cpp,在最后面添加一段代码:

JNIEXPORT void JNICALL Java_TestNew_hello(JNIEnv * env, jclass obj, jstring jMsg) {const char *strMsgPtr = env->GetStringUTFChars( jMsg , 0);    MessageBox( 0, strMsgPtr,"Message box from VC++ ", 0 ); env->ReleaseStringUTFChars( jMsg, strMsgPtr);  }

(4)在VC的菜单上选择Tools-Options…,打开选项对话框。在Directories文件夹,添加上jdk所在文件夹下的include和include\win32文件夹。


点击VC上的菜单项Build-Build All,生成TestNew.dll。

(5)VC项目Debug文件夹中的TestNew.dll复制到TestNew.class所在的文件夹下。在命令行下输入javaTestNew,弹出MessageBox对话框。调用win32 api成功。如下:


参考原文:http://www.cnblogs.com/mandroid/archive/2011/06/15/2081093.html

参考原文:http://www.iteye.com/topic/304594#814127

参考原文:http://blog.csdn.net/flydream0/article/details/7088514

更多相关文章

  1. C语言函数的递归(上)
  2. 如何将打开res raw目录中的数据库文件?
  3. 将Android移植到FS2410开发板上
  4. Android(安卓)Bluetooth HID实现详解
  5. Android(安卓)Studio 开发经验纵览
  6. android manifest 文件Activity配置节中的属性汇总
  7. android使用opensl es进行简单的音频播放
  8. icovn移植到android上
  9. Android(安卓)Activity 各函数解析

随机推荐

  1. Android(安卓)HAL实现的三种方式(1) - 基
  2. 关于Android(安卓)intent的知识 隐式意图
  3. Android(安卓)Develop Training——Andro
  4. 几点Android(安卓)开发中的小技巧
  5. android 新浪微博客户端的表情功能的实现
  6. 从CM刷机过程和原理分析Android系统结构
  7. Android笔记_2013_02_21
  8. Android练习项目 Mp3播放器实现(一)
  9. Android(安卓)Canvas类介绍和Android(安
  10. Android(安卓)Studio五分钟带你从菜鸟到