JNI(Java Native Interface) Java本地接口, Java代码使用JNI调用外部的本地C/C++代码,同样,外部的C/C++ 代码可以调用Java代码。

NDK与JNI区别:
(1)NDK:NDK是Google开发的一套开发和编译工具集, 主要用于Android的JNI开发;
(2)JNI : JNI是一套编程接口, 用来实现Java代码与本地的C/C++代码进行交互。


一、JNI编程步骤:
(1)声明native方法:在Java代码中声明 native method()方法;
(2)实现JNI的C/C++方法:在JNI层实现Java中声明的native方法,并在JNI层,将C/C++代码编译成动态库;
(3)加载动态库: 在Java代码中的静态代码块中加载JNI编译后的动态共享库。


二、JNI开发方式比较

静态注册

1)书写不便,JNI层函数名特别长;

2)初次调用native函数时要根据函数名搜索对应的JNI层函数来建立关联关系,这样很影响效率。

动态注册

(1)书写方便;

2)使用用函数映射表来调用相应的函数,效率较高。


三、动态注册

1、关键接口介绍

1System.loadLibrary()函数

Java程序通过System.loadLibrary加载完JNI动态库,完成对C++函数的调用。

static{System.loadLibrary("HelloJNI");}

2JNI_OnLoad()函数

JNI_OnLoad()函数在VM执行System.loadLibrary(xxx)函数时被调用,有两个重要的作用:

 a、指定JNI版本:告诉VM该组件使用那一个JNI版本(若未提供JNI_OnLoad()函数,VM会默认该使用最老的JNI 1.1),如果要使用新版本的JNI,例如JNI 1.4版,则必须由JNI_OnLoad()函数返回常量JNI_VERSION_1_4(该常量定义在jni.h)来告知VM

b、初始化设定,当VM执行到System.loadLibrary()函数时,会立即先呼叫JNI_OnLoad()方法,因此在该方法中进行各种资源的初始化操作最为恰当,而动态注册的工作就是在这里完成的。

3JNINativeMethod结构体

JNINativeMethod结构体建立JavaC++函数的联系,在jni.h中被定义,如下:

typedef struct {

const char* name;

const char* signature;

void* fnPtr;

} JNINativeMethod;

第一个变量nameJava中函数的名字;

第二个变量signature,用字符串是描述了函数的参数和返回值;

第三个变量fnPtr是函数指针,指向C++函数。

4RegisterNatives()registerNativeMethods()

RegisterNatives()通过调用registerNativeMethods()JNINativeMethod结构体,将c/c++中的方法映射到Java空间。

下面看关键代码,全部代码下载

static JNINativeMethod methods[] = {{"hello", "()Ljava/lang/String;", (void*) hello_jni },};static int registerNativeMethods(JNIEnv* env, const char* className,    JNINativeMethod* gMethods, int numMethods){    jclass clazz;    clazz = env->FindClass(className);    if (clazz == NULL) {        fprintf(stderr, "Native registration unable to find class '%s'", className);        return JNI_FALSE;    }    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {        fprintf(stderr, "RegisterNatives failed for '%s'", className);        return JNI_FALSE;    }    return JNI_TRUE;}static const char* classPathName = "com/example/hellojni/MainActivity";static int registerNatives(JNIEnv* env){  if (!registerNativeMethods(env, classPathName,                 methods, sizeof(methods) / sizeof(methods[0]))) {    return JNI_FALSE;  }  return JNI_TRUE;}typedef union {    JNIEnv* env;    void* venv;} UnionJNIEnvToVoid;jint JNI_OnLoad(JavaVM* vm, void* reserved){    UnionJNIEnvToVoid uenv;    uenv.venv = NULL;    jint result = -1;    JNIEnv* env = NULL;    printf("JNI_OnLoad");    if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {        fprintf(stderr, "GetEnv failed");        goto bail;    }    env = uenv.env;    if (!registerNatives(env)) {        fprintf(stderr, "registerNatives failed");    }    result = JNI_VERSION_1_4;bail:    return result;}

2、JNI类型映射表

Java 类型

Native 类型

类型说明

Field descriptor

boolean

jboolean

C/C++8位整型

Z

byte

jbyte

C/C++带符号的8位整型

B

char

jchar

C/C++无符号的16位整型

C

short

jshort

C/C++带符号的16位整型

S

int

jint

C/C++带符号的32位整型

I

long

jlong

C/C++带符号的64位整型

J

float

jfloat

C/C++32位浮点型

F

double

jdouble

C/C++64位浮点型

D

Object

jobject

任何Java对象,或者没有对应java类型的对象

Ljava/lang/Object;

Class

jclass

Class对象

Ljava/lang/Object;

String

jstring

字符串对象

Ljava/lang/String;

Object[]

jobjectArray

任何对象的数组

[Ljava/lang/Object;

boolean[]

jbooleanArray

布尔型数组

[Z

byte[]

jbyteArray

比特型数组

[B

char[]

jcharArray

字符型数组

[C

short[]

jshortArray

短整型数组

[S

int[]

jintArray

整型数组

[I

long[]

jlongArray

长整型数组

[J

float[]

jfloatArray

浮点型数组

[F

double[]

jdoubleArray

双浮点型数组

[D

Void

Void

V


3、JNI调试

(1)添加头文件JNIlog.h,链接下载;
(2)在Android.mk 中加入:
LOCAL_LDLIBS := -llog
(3)调用
LOGD("%s:%u, static_hello", __func__, __LINE__);


4、静态与非静态原生函数的区别
其区别在于第二个参数随本地方法是静态还是非静态而有所不同:
(1)非静态本地方法的第二个参数是对对象的引用;
(2)静态本地方法的第二个参数是对其Java类的引用;
其余的参数对应通常Java方法的参数,参数类型需要根据一定规则进行映射。


更多相关文章

  1. C语言函数的递归(上)
  2. Android(安卓)实现全屏 去掉标题栏
  3. android去掉EditView的默认焦点问题
  4. Google Admob广告Android(安卓)、简单应用
  5. android DES 字符串加密后 解密乱码
  6. Android高手进阶教程(十五)---Android中万能的BaseAdapter(Spinn
  7. Android(安卓)开发中常见的Eclipse排版设置
  8. Android提高第十八篇之自定义PopupWindow实现的Menu(TabMenu)
  9. 2018-05-27

随机推荐

  1. android JB2连拍降速原理介绍
  2. Android(安卓)jni 编程(参数的传递,成员,方
  3. Android(安卓)保存图片到SQLite
  4. android中控件公用产生的冲突的解决办法
  5. android图表工具achartengine之ChartFact
  6. Android(安卓)AudioManager控制系统声音
  7. android 7种对话框的使用
  8. Android(安卓)UI之TextView实现图文混合
  9. Android(安卓)Intent传递对象小结
  10. android 自定义进度条下载apk并更新