android native call java_Android NDK学习:native 通过JNI调用java的属性跟方法

native调用Java的普通属性

Java 代码

public class JniUtils {

static{

System.loadLibrary("JNIEnvOne");

}

public String name = "liu";

//访问普通属性

public native void modifField();

}

C 代码

//调用普通属性

JNIEXPORT void JNICALL Java_com_liu_JniUtils_modifField

(JNIEnv * env, jobject obj){

//获取类

jclass jclazz = (*env)->GetObjectClass(env, obj);

//获取属性,属性签名

jfieldID field = (*env)->GetFieldID(env, jclazz, "name", "Ljava/lang/String;");

//拿到属性的值(JNI的)

//getField 模式,不同的类型

jstring jojb = (*env)->GetObjectField(env, obj, field);

//转成c的字符串

//isCopy 是否赋值的意思。

jboolean isCopy = NULL;

char* c_str = (*env)->GetStringChars(env, jojb, &isCopy);

if (isCopy){

printf("%s\n", "this str is copy");

}

char* mid = "I am from C";

//拼接C的字符串

strcat(c_str, mid);

//setField 模式

(*env)->SetObjectField(env, obj, field, (*env)->NewStringUTF(env, c_str)); //释放 (*env)->ReleaseStringChars(env, jojb, c_str);

}

调用步骤:

- 获取类。 (*env)->GetObjectClass(env, obj);

- 获取属性签名。(*env)->GetFieldID(env, jclazz, “name”, “Ljava/lang/String;”);

- 拿到属性的值。(*env)->GetObjectField(env, obj, field);

- 把值转换成C可操作的类型。(*env)->GetStringChars(env, jojb, &isCopy);

- 操作属性的值。strcat(c_str, mid)/重新赋值等等

- 转换成JNI需要的类型。((*env)->NewStringUTF(env, c_str))

- 设置到属性里面。SetObjectField

- 把创建的字符串释放。(*env)->ReleaseStringChars(env, jojb, c_str);

native调用Java的静态属性

Java 代码

public class JniUtils {

static{

System.loadLibrary("JNIEnvOne");

}

public static String staticName = "liu";

//访问静态属性

public native void modifStaticField();

}

C 代码

//获取静态属性

JNIEXPORT void JNICALL Java_com_liu_JniUtils_modifStaticField

(JNIEnv * env, jobject obj){

//先获取jclass

jclass cls = (*env)->GetObjectClass(env, obj);

//获取属性签名

jfieldID fid = (*env)->GetStaticFieldID(env, cls, "staticName", "Ljava/lang/String;");

//获取属性

jstring field = (*env)->GetStaticObjectField(env, cls, fid);

//转换成c的类型

char* str = (*env)->GetStringChars(env, field, NULL);

char* s = "static str";

strcat(s, str);

jstring result = (*env)->NewStringUTF(env, s);

(*env)->SetStaticObjectField(env, cls, fid, result);

(*env)->ReleaseStringChars(env, field, str);

}

步骤:

- 获取类

- 获取属性签名

- 获取属性

- 转换成C可操作的类型

- 操作值

- 转换成JNI需要的类型

- 设置属性

- 释放资源

native调用Java的普通方法

Java代码

public class JniUtils {

static{

System.loadLibrary("JNIEnvOne");

}

//访问普通方法

public native void callMethod(int count);

public void normalMethod(int count){

System.out.println("普通方法被调用了。count:"+count);

}

}

C 代码

//调用普通方法

JNIEXPORT void JNICALL Java_com_liu_JniUtils_callMethod

(JNIEnv * env, jobject obj,jint count){

//获取类

jclass cls = (*env)->GetObjectClass(env, obj);

//获取方法签名

jmethodID mid = (*env)->GetMethodID(env, cls, "normalMethod", "(I)V");

//调用方法

(*env)->CallObjectMethod(env, obj, mid, count);

}

步骤:

- 获取类

- 获取方法签名

- 调用方法

native调用Java的静态方法

Java 代码

public class JniUtils {

static{

System.loadLibrary("JNIEnvOne");

}

//访问静态方法

public native void callStaticMethod();

public static void staticMethod(){

System.out.println("static 方法被调用了。count:");

}

}

C 代码

//调用静态方法

JNIEXPORT void JNICALL Java_com_liu_JniUtils_callStaticMethod

(JNIEnv * env, jobject obj, jint count){

//获取类

jclass cls = (*env)->GetObjectClass(env, obj);

//获取方法签名

jmethodID mid = (*env)->GetStaticMethodID(env, cls, "staticMethod", "()V");

//调用方法

(*env)->CallStaticVoidMethod(env, cls, mid);

}

Java层调用native,返回乱码问题及调用构造方法

Java 代码

public class JniUtils {

static{

System.loadLibrary("JNIEnvOne");

}

//访问构造方法

public native void callConstructMethod();

public String name = "liu";

}

C 代码

//解决字符串的乱码问题,及访问类的构造器

//通过new String(byte[],charset)。转换编码来解决乱码问题

jstring conv_str_to_java(JNIEnv* env, char* str){

//先找到类

jclass cls = (*env)->FindClass(env, "java/lang/String");

//获取构造器的方法签名

jmethodID mid = (*env)->GetMethodID(env, cls, "", "([BLjava/lang/String;)V");

//需要转换的字符串长度

int arr_len = strlen(str);

//jbyte-char。初始化一个同等长度的字符数组

jbyteArray arr = (*env)->NewByteArray(env, arr_len);

//str数组赋值到jbytArray

(*env)->SetByteArrayRegion(env, arr, 0, arr_len, str);

//把需要的编码,转换成JNI需要的类型

jstring charsetName = (*env)->NewStringUTF(env, "GB2312");

//调用String的构造方法,初始化String类

jstring result = (*env)->NewObject(env, cls, mid, arr, charsetName);

return result;

}

//调用普通属性

JNIEXPORT void JNICALL Java_com_liu_JniUtils_callConstructMethod

(JNIEnv * env, jobject obj){

//获取类

jclass jclazz = (*env)->GetObjectClass(env, obj);

//获取属性,属性签名

jfieldID field = (*env)->GetFieldID(env, jclazz, "name", "Ljava/lang/String;");

//拿到属性的值(JNI的)

//getField 模式,不同的类型

jstring jojb = (*env)->GetObjectField(env, obj, field);

//转成c的字符串

char* c_str = (*env)->GetStringChars(env, jojb,NULL);

char* mid = "我是C的字符串";

//拼接C的字符串

strcat(c_str, mid);

//setField 模式

//这样是有乱码的

//(*env)->SetObjectField(env, obj, field, (*env)->NewStringUTF(env, c_str)); //通过上面的函数转换后,就没有乱码了 (*env)->SetObjectField(env, obj, field, conv_str_to_java(env,c_str));

//释放

(*env)->ReleaseStringChars(env, jojb, c_str);

}

native调用Java的普通的类的方法

Java 代码

public class JniUtils {

static{

System.loadLibrary("JNIEnvOne");

}

//访问普通类的普通方法

public native long callNormalClassMethod();

}

C 代码

//访问普通类的方法

JNIEXPORT jlong JNICALL Java_com_liu_JniUtils_callNormalClassMethod

(JNIEnv * env, jobject obj){

//找到类

jclass cls = (*env)->FindClass(env, "java/util/Date");

//获取构造方法的签名

jmethodID construct_id = (*env)->GetMethodID(env, cls, "", "()V");

//初始化 类

jobject date_obj = (*env)->NewObject(env, cls,construct_id);

//获取方法的签名

jmethodID mid = (*env)->GetMethodID(env, cls, "getTime", "()J");

//访问方法

jlong t = (*env)->CallLongMethod(env, date_obj, mid);

return t;

}

查看类属性和方法的签名

cd native方法生成的类的文件夹下

执行javap -s -p xx.xx.JniUtils

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值