Android(安卓)NDK开发基础篇(二)
此系列记录Android NDK基础开发知识,在Android NDK开发基础篇(一)中介绍了NDK、JNI以及关系,包括AS创建JNI的项目及第一个函数解析,
目的
- Java类型和native类型的映射关系
- jobject
- jclass
- JNIEnv 的基本使用
用于参数解析:
Java_com_kpa_jnijavademo_MainActivity_stringFromJNI( JNIEnv *env, jobject obj/* this */) { return env->NewStringUTF(hello.c_str());}
一、Java类型和native类型的映射关系
Java类型 | 本地类型 | JNI定义的别名 |
---|---|---|
int | long | jint/jsize |
short | short | jshort |
long | _int64 | jlong |
float | float | jfloat |
double | double | jdouble |
byte | signed char | jbyte |
boolean | unsigned char | jboolean |
char | unsigned char | jchar |
Object | _jobject* | jobject |
本地类型指的是在C/C++中的使用,JNI定义的别名是C/C++在JNI中的使用,不需要多记,后续回经常出现
二、 jobject
jobject 表示的是Java中的Object类型,在参数中有两个不同的意义需要知道
- native方法是static 修饰的: 代表native方法的类的class对象的实例
- native方法不是static 修饰的:表示native方法的实例
三、jclass
jclass 表示Java的中的Class类
在下面的JNIEnv 中会解释jclass 在C/C++中的集中获取方法
四、 JNIEnv
JNIEnv 类型在native 中实际代表了Java在native中的Java环境 ,通过JNIEnv*指针可以对Java端的代码进行操作,为什么JNI开发中首先要了解对Java的操作呢?
JNI作为Java和C/C++的连接桥梁,自然能在C/C++中操作Java的对象,最起码我们在C/C++中的一系列操作完成之后,将结果返回给Java就需要用到Java操作,以此问题还有很多。
既然是代表了Java环境,那首先有这几个概念需要了解一下:
- 对象
- 属性
- 方法
这是最起码操作一个Java对象应该具备的要素
4.1在native中创建一个Java对象
Newobject
/***jclass : Class 对象(后续解释怎么获取一个class对象)*methodID: 方法ID**/jobject NewObject(jclass clazz, jmethodID methodID, ...) { va_list args; va_start(args, methodID); jobject result = functions->NewObjectV(this, clazz, methodID, args); va_end(args); return result; }
jmethodID 在JNI中表示一个指向method的指针,创建对象时的method哪里来呢? 没错就是构造方法
为了后续更好的理解 先看一下jclass 的获取方法
4.2 JNIEnv 中获取jclass 的方法
- FindClass
// 通过类的全名获取class 对象 jclass FindClass(const char* name) { return functions->FindClass(this, name); }
eg:
// 获取Java中Date 对象的Class对象jclass date_clazz = env->FindClass("java/util/Date");
- GetObjectClass
// 通过native方法中的jobject对象获取Class 对象jclass GetObjectClass(jobject obj) { return functions->GetObjectClass(this, obj); }
eg:
Java_com_kpa_jnijavademo_JNIDemo_sayHello(JNIEnv *env, jobject thiz) {// 根据native sayHello方法中jobject 的class 对象 jclass jniDemo = env->GetObjectClass(thiz); }
- GetSuperClass
//根据jclass 可以获取他的父类的jclass 对象jclass GetSuperclass(jclass clazz) { return functions->GetSuperclass(this, clazz); }
4.3 JNI获取jmethod、jfieldID
GetMethodID/GetStaticMethodID
/*** clazz 所在class 对象* name: 方法名称* sig: 方法签名(变量和方法在JNI中都是有签名的)**/jmethodID GetMethodID(jclass clazz, const char* name, const char* sig) { return functions->GetMethodID(this, clazz, name, sig); }jmethodID GetStaticMethodID(jclass clazz, const char* name, const char* sig) { return functions->GetStaticMethodID(this, clazz, name, sig); }
GetFieldID/GetStaticFieldID
jfieldID GetFieldID(jclass clazz, const char* name, const char* sig) { return functions->GetFieldID(this, clazz, name, sig); }jfieldID GetStaticFieldID(jclass clazz, const char* name, const char* sig) { return functions->GetStaticFieldID(this, clazz, name, sig); }
通过javap命令查看类中的属性和方法的签名
javap -s -p XXX.class
eg:
public class com.kpa.jnijavademo.Demo { public int a; descriptor: I public com.kpa.jnijavademo.Demo(); descriptor: ()V //构造方法签名 public int add(int, int); descriptor: (II)I public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V}
I、()V、(II)I都是签名
eg:
void createObj1(JNIEnv *env) {// native 创建Java对象// 获取Java中的Date的Class对象 jclass date_clazz = env->FindClass("java/util/Date"); // 获取构造方法的ID 构造方法名称始终是 jmethodID mid_date = env->GetMethodID(date_clazz, "" , "()V"); // 生成Date对象 jobject date_obj = env->NewObject(date_clazz, mid_date); jmethodID get_time_id = env->GetMethodID(date_clazz, "getTime", "()J"); jlong time = env->CallLongMethod(date_obj, get_time_id); printf("时间 ==== %I64d", time);}
然后看一下上面4.1中NewObject创建一个对象
eg:
// 获取Java中的Date的Class对象 jclass date_clazz = env->FindClass("java/util/Date"); // 获取构造方法的ID 构造方法名称始终是 jmethodID mid_date = env->GetMethodID(date_clazz, "" , "()V");
4.4
到此为止,介绍了JNI中如果获取对象的Class 对象,创建对象,以及获取方法、属性等功能。
在Android NDK特别篇中多介绍几个使用案例
更多相关文章
- Android快速开发工具集合——YUtils
- Android的Btimap处理大图片解决方法
- JetPack 之 DataBinding 的使用
- Android中如何将dp,dip,sp与px相互转化
- Android屏幕元素层次结构
- 浅谈Java中Collections.sort对List排序的两种方法
- 类和 Json对象
- Python list sort方法的具体使用
- python list.sort()根据多个关键字排序的方法实现