NDK简介

一、NDK简介:

         C/C++的动态库。Dalvik通过JNI编程方式调用C/C++代码。

         NDK编程提高软件性能,加密保护APK文件

         ndk-build        NDK编译生成脚本

         Java编译时会根据java声明文件生成dex文件,即使没有java代码

         NDK共享库:NDK生成的 .so文件(类似dll)

         NDK静态库:.a文件件

        

二、JNI中的数据类型:

         数据分两大类:基本类型,引用类型

                   基本类型

Java类型

JNI类型

C/C++类型

大小

boolean

jboolean

unsigned char

无符号8位

byte

jbyte

char

有符号8位

char

jchar

unsigned short

无符号16位

short

jshort

short

有符号16位

int

jint

Int

有符号32位

long

jlong

long long

有符号64位

float

jfloat

float

32位浮点数

double

jdouble

double

64位浮点数

                   引用类型

Java类型

原生类型

描述

java.lang.Class

jclass

类类型

java.lang.Throwable

jthrowable

异常类型

java.lang.String

jstring

字符类型

java.lang.Object[]

jobjectArray

任意java对象数组

boolean[]

jbooleanArray

布尔型数组

byte[]

jbyteArray

比特型数组

char[]

jcharArray

字符型数组

short[]

jshortArray

短整型数组

int[]

jintArray

整型数组

long[]

jlongArray

长整型数组

float[]

jfloatArray

浮点型数组

double[]

jdoubleArray

双浮点型数组

 

三、JNI中对Java类、域、方法的描述符

         1。域描述:基本类型,引用类型,数组类型

                   基本类型描述符

域描述符

Java语言类型

Z

boolean

B

byte

C

char

S

short

I

int

J

long

F

Float

D

double

                 引用描述符:L+类描述+;

Eg:String               Ljava/lang/String;

         Object[]           [Ljava/lang/object;

                   数组域的描述符

Eg:int[]                   [I

         float[]               [F

         String[]             [Ljava/lang/String;

         int[][]                [[I

 

         2。类描述符:类的完整名(包名+类名)“.”替换成“/”

Eg:java.lang.String               :java/lang/String

         3。方法描述符:

                   规则:参数的域描述符按照声明顺序放入一个括号中,后跟返回值类型的域描述符。没有返回值用V(void)表示,如果是类引用后面加“;”

Eg:String text()             ()Ljava/lang/String;

         int fun(int i,Object object)             (ILjava/lang/Object;)I

         void set(byte[] bytes)                      ([B)V

 

         Native中字符串的转换

                   1。C-〉Java

                            jstring NewStringUTF(JNIEnv *env, // JNI接口指针

                                                                    const char* bytes)// C字符串

Eg:jstring jstring1 = env->NewStringUTF(“Hello Wrold”);

                   2。Java-〉C

                            char* GetStringUTFChars(JNIEnv *env,      // JNI接口指针

  jstring string,      // jstring java字符串

  jboolean* isCopy) // 表示返回副本还是堆中固定值

Eg:jboolean iscopy;

         char* ch = env->GetStringUTFChars(jstring1,&iscopy);

 

Native中创建数组

         1。创建一维数组

// 创建

jintArray NewIntArray(JNIEnv *env,   // JNI接口指针

                                                 jsize length);// 数组长度

// 赋值数组某一范围

void SetIntArrayRegion(JNIEnv *env,      //JNI接口指针

                                                  jintArray array,  //目的数组

                                                  jsize start,      //基本类型数组开始的位置

                                                  jsize len,        //数组长度

                                                  const jint* buf); //源数组

// 获取数组值

void GetIntArrayRegion(JNIEnv *env,      //JNI接口指针

                       jintArray array,  //目的数组

                       jsize start,      //基本类型数组开始的位置

                       jsize len,        //数组长度

                       const jint* buf); //源数组

// 释放局部数组对象

void DeleteLocalRef(JNIEnv *env,                 // JNI接口指针

                                         jobject localRef)    // 要释放的局部数组对象

用于构建其他基本数据类型的数组

New<PrimitiveType>Array 方法族

Set< PrimitiveType >ArrayRegion

Get< PrimitiveType >ArrayRegion

 

         2。创建数组对象

         // 创建

jobjectArray NewIntArray(JNIEnv *env,      // JNI接口指针

                                                    length,// 数组长度

                                                         jcalss elementClass,// 类型

                                                         jobject initialElement)// 初始值

// 设置

void SetobjectArrayElement(JNIEnv *env,      //JNI接口指针

                                                      jobjectArray array,  //目的数组

                                                      jsize index,      //目的数组的第几个索引

                                                      jobject value)       //写入的值

 

         Native中java操作java类中的属性

1。Java层非静态

         获取java层中属性ID

         jfieldID GetFieldID(JNIEnv *env, // JNI接口指针

                                               jclass class, // Java类对象

                                               const char *name,// 该属性的name名称     

                                               const char *sig): // 属性的域签名    

         获取Java层中属性值

         NativeType Get<type>Field(JNIEnv *env, // JNI接口指针

                                                                   jobject obj, // java 对象(不能null)

                                                                   jfieldID fieldID);// 有效的域ID

         设置java层类中属性的值

         void Set<type>Field(JNIEnv *env, // JNI接口指针

                                                        jobject obj, // java 对象(不能null)

                                                        jfieldID fieldID,// 有效的域ID

                                                        NativeType value);// 设置新值

2。Java层静态

         获取java层中属性ID

         jfieldID GetStaticFieldID(JNIEnv *env, // JNI接口指针

                                                                  jclass class, // Java类对象

                                                                  const char *name,// 该属性的name名称   

                                                             const char *sig): // 属性的域签名 

         获取Java层中属性值

         NativeType GetStatic<type>Field(JNIEnv *env, // JNI接口指针

                                                                   jobject obj, // java 对象(不能null)

                                                                   jfieldID fieldID);// 有效的域ID

         设置java层类中属性的值

         void SetStatic<type>Field(JNIEnv *env, // JNI接口指针

                                                        jobject obj, // java 对象(不能null)

                                                        jfieldID fieldID,// 有效的域ID

                                                        NativeType value);// 设置新值

 

         Native中操作Java层类或接口的方法

1。Java层静态方法:

                  获取java层中属性ID

         jmethodID GetMethodID(JNIEnv *env, // JNI接口指针

                                                     jclass class, // Java类对象

                                                     const char *name,// 该属性的name名称

                                                          const char *sig): // 属性的域签名

                  获取Java层中属性值

         NativeType Call<type>MOthod(JNIEnv *env, // JNI接口指针

                                                                   jobject obj, // java 对象(不能null)

                                                                   jmethodID jmethodID,// 方法ID

                                                                   ...);// 要调用方法的参数

2。Java层静态方法操作

         获取java层中属性ID

         jmethodID GetStaticMethodID(JNIEnv *env, // JNI接口指针

                                                                           jclass class, // Java类对象

                                                                           const char *name,// 该属性的name名称     

                                                                           const char *sig): // 属性的域签名    

         获取Java层中属性值

         NativeType CallStatic<type>MOthod(JNIEnv *env, // JNI接口指针

                                                                                      jobject obj, // java 对象(不能null)

                                                                                      jmethodID jmethodID,// 方法ID

                                                                                      ...);// 要调用方法的参数

 

动态注册Native方法

1。在Java层声明要导出的函数

public native String getNatvieString();

2。在native中编写普通方法

3。定义数组在该数组中将Java中声明方法和native中定义的方法进行邦定

4。在JNI初始化函数JNI_OnLoad中注册函数

jint JNI_OnLoad(JavaVM *vm,void* reserved)

{

         // 1。获取env对象

         GetEnv或者AttachCurrentThread

         // 2。获取class

         FindClass

         // 3。注册

         RegisterNatives()

         // 4。返回jni版本

         return JNI_VERSION_xx;

}

 

         NDK调试器两款:

1。GDB:UNIX/LINUX下基于命令行的调试工具

2。LLDB:基于LLVM框架。

上一篇:JNI学习笔记:JNIEnv、jobject与jclass详解


下一篇:Jni 线程JNIEnv,JavaVM,JNI_OnLoad(GetEnv返回NULL?FindClass返回NULL?)