一、得到静态(static)和实例(instance)的域与方法的JNI函数
函数 | 描述 |
GetFieldID | 得到一个实例的域的ID |
GetStaticFieldID | 得到一个静态的域的ID |
GetMethodID | 得到一个实例的方法的ID |
GetStaticMethodID | 得到一个静态方法的ID |
实例:
//创建一个class的引用
/**
* Lpackagename/classname;
* L代表这是在描述一个对象类型
* packagename/classname是该对象耳朵class路径
* 请注意一定要以分号(;)结束
*/
jclass cls = (*env)->FindClass(env, "Lpackagename/classname;");
jmethodID id = (*env)->GetMethodID(env, cls, "", "(D)V"); //注意这里方法的名称是"",它表示这是一个构造函数,而且构造参数是double型的
jobject obj = (*env)->NewObjectA(env, cls, id, args); //获得一实例,args是构造函数的参数,它是一个jvalue*类型。
二、JNI函数的定义
在android系统中,使用了一种与传统定义Java JNI方式有所不同的方式定义Native函数,最主要的区别是,其在Android中使用了一种java和C函数的映射表数组,并在其中描述了函数的参数和返回值。该数组定义如下:
typedef struct {
const char* name;//Java中函数的名字
const char* signature;//描述了函数的参数和返回值
void* fnPtr;//函数指针,指向C函数
} JNINativeMethod;
在使用时,第二个参数的传入值会像下面这些:
"()V"
"(II)V"
"(Ljava/lang/String;Ljava/lang/String;)V"
对于这些字符串的具体说明如下:
(1)"()"中的字符表示函数参数,"()"后面的表示函数的返回值。
(2)
字符 | 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 |
字符 | Java类型 | C类型 |
---|---|---|
[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对象时,则要以"L"开头,以";"结尾,中间使用"/"分隔包及类名。其对应的C函数名的参数为joblect(String类例外,String类对应的类为jstring)
如果Java函数位于一个嵌入类,则可以使用$作为类名间的分隔符。
如:"(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z"
三、注册工作
//定义一个JNINativeMethod数组
static JNINativeMethod method[]={
{
"native_init"
"()V"
(void*)android_media_MediaScanner_native_init
},
...
}
//注册数组
char* classname="xxxx";
int register(JNIEnv *env)
{
return AndroidRuntime::registerNativeMethods(env,classname,method,NELEM(method));
}
四、在本地方法中调用Java对象的方法
1、获取所需的Java类
jclass cls = (*env)->GetObjectClass(env, obj); // 使用GetObjectClass方法获取obj对应的jclass。
jclass cls = (*env)->FindClass(“android/util/log”) // 直接搜索类名,需要是static修饰的类。
2、获取MethodID
/**
* env-->JNIEnv
* cls-->第一步获取的jclass
* "callback"-->要调用的方法名
* "(I)V"-->方法的Signature, 签名同前面的JNI规则。
*/
jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V");
//GetStaticMethodID(…),获取静态方法的ID使用GetMethdoID方法获取你要使用的方法的MethdoID
3、调用方法
/**
* env-->JNIEnv
* obj-->通过本地方法穿过来的jobject
* mid-->要调用的MethodID(即第二步获得的MethodID)
* depth-->方法需要的参数(对应方法的需求,添加相应的参数)
*/
(*env)->CallVoidMethod(env, obj, mid, depth);// CallStaticIntMethod(….) , 调用静态方法
系统提供的调用方法函数:
|
|
|
|
|
|
|
|