Android JNI基础

0.头文件的生成及基础参数详解

package com.example.jnitest;

public class JNITest {

    public native String getStringFromC();

    public native static String getString2FromC();
}

里面有两个native方法
用命令行进入该项目src目录,使用javah命令javah com.example.jnitest.JNITest 生成头文件
com_example_jnitest_JNITest.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_jnitest_JNITest */

#ifndef _Included_com_example_jnitest_JNITest
#define _Included_com_example_jnitest_JNITest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_jnitest_JNITest
 * Method:    getStringFromC
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_jnitest_JNITest_getStringFromC
  (JNIEnv *, jobject);

/*
 * Class:     com_example_jnitest_JNITest
 * Method:    getString2FromC
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_jnitest_JNITest_getString2FromC
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

JniTest.c

JNIEXPORT jstring JNICALL Java_com_example_jnitest_JNITest_getStringFromC
  (JNIEnv *env, jobject jobj){
    //JNIEnv 结构体指针
    //env二级指针
    //代表Java运行环境,调用Java中的代码
    //简单的实现
    //将C的字符串转为一个java字符串
    return (*env)->NewStringUTF(env,"C String");
}


JNIEXPORT jstring JNICALL Java_com_example_jnitest_JNITest_getString2FromC
  (JNIEnv *env, jclass jcls){
    return (*env)->NewStringUTF(env,"C String");
}
//每个native函数,都至少有两个参数(JNIEnv*,jclass或者jobject)
//1)当native方法为静态方法时:
//jclass 代表native方法所属类的class对象(JNITest.class)
//2)当native方法为非静态方法时:
//jobject 代表native方法所属的对象

1.类型转换

基本数据

boolean jboolean
byte jbyte;
char jchar;
short jshort;
int jint;
long jlong;
float jfloat;
double jdouble;
void void

引用类型(对象)

String  jstring
object  jobject
//数组,基本数据类型的数组
byte[]  jByteArray
//对象数组
object[](String[])   jobjectArray

2.访问属性

1)访问非静态属性

package com.example.jnitest;

public class JNITest {
    public String xm = "xmhaha";
    //访问属性,返回修改后的属性
    public native String accessField();
}
JNIEXPORT jstring JNICALL Java_com_example_jnitest_JNITest_accessField
  (JNIEnv *env, jobject jobj){
    //jobj是对象,JNITest.class
    jclass cls = (*env)->GetObjectClass(env, jobj);

这里写图片描述

    //jfieldID
    //属性名称,属性签名
    jfieldID fid = (*env)->GetFieldID(env, cls, "xm", "Ljava/lang/String;");

    //xm >> super xm

    //获取xm属性的值
    //Get<Type>Field
    jstring jstr = (*env)->GetObjectField(env, jobj, fid);
    //jstring -> c字符串
    //isCopy 是否复制(true代表赋值,false不复制)
    char *c_str = (*env)->GetStringUTFChars(env,jstr,JNI_FALSE);
    //拼接得到新的字符串
    char text[20] = "super ";
    strcat(text,c_str);

    //c字符串 ->jstring
    jstring new_jstr = (*env)->NewStringUTF(env, text);

    //修改xm
    //Set<Type>Field
    (*env)->SetObjectField(env, jobj, fid, new_jstr);

    return new_jstr;
}

2)访问静态属性

package com.example.jnitest;

public class JNITest {
    public static int count = 8;
    //访问属性,返回修改后的属性
    public native String accessStaticField();
}
JNIEXPORT jstring JNICALL Java_com_example_jnitest_JNITest_accessStaticField
  (JNIEnv *env, jobject jobj){
    //jclass
    jclass cls = (*env)->GetObjectClass(env, jobj);
    //jfieldID
    jfieldID fid = (*env)->GetStaticFieldID(env, cls, "count", "I");
    //GetStatic<Type>Field
    jint count = (*env)->GetStaticIntField(env, cls, fid);
    count++;
    //修改
    //SetStatic<Type>Field
    (*env)->SetStaticIntField(env,cls,fid,count);
}

3.访问方法

1)访问非静态方法

package com.example.jnitest;

public class JNITest {
    public native void accessMethod();

    /**
     * 产生指定范围的随机数
     * 
     * @param max
     * @return
     */
    public int genRandomInt(int max) {
        return new Random().nextInt(max);
    }
}

获得方法的签名:
用命令行进入项目的bin/classes目录,使用javap -s -p
这里写图片描述
得到方法签名
这里写图片描述

JNIEXPORT void JNICALL Java_com_example_jnitest_JNITest_accessMethod
  (JNIEnv *env, jobject jobj){
    //jclass
    jclass cls = (*env)->GetObjectClass(env, jobj);
    //jmethodID
    jmethodID mid = (*env)->GetMethodID(env, cls, "genRandomInt", "(I)I");
    //调用
    //Call<Type>Method
    jint random = (*env)->CallIntMethod(env, jobj, mid, 200);
    printf("random num:%ld",random);

    //.....
}

2)访问静态方法

package com.example.jnitest;

public class JNITest {
    public native void accessStaticMethod();

    public static String getUUID() {
        return UUID.randomUUID().toString();
    }
}
JNIEXPORT void JNICALL Java_com_example_jnitest_JNITest_accessStaticMethod
  (JNIEnv *env, jobject jobj){
    //jclass
    jclass cls = (*env)->GetObjectClass(env, jobj);
    //jmethodID 
    jmethodID mid = (*env)->GetStaticMethodID(env, cls, "getUUID", "()Ljava/lang/String;");

    //调用
    //CallStatic<Type>Method
    jstring uuid = (*env)->CallStaticObjectMethod(env, cls, mid);
    //.....
 }

3)访问构造方法

//使用java.util.Date产生一个当前时间
JNIEXPORT jobject JNICALL Java_com_dongnaoedu_jni_JniTest_accessConstructor
(JNIEnv *env, jobject jobj){
    jclass cls = (*env)->FindClass(env, "java/util/Date");
    //jmethodID(构造方法用<init>)
    jmethodID constructor_mid = (*env)->GetMethodID(env, cls, "<init>", "()V");
    //实例化一个Date
    jobject date_obj = (*env)->NewObject(env, cls, constructor_mid);
    //调用getTime方法
    jmethodID mid = (*env)->GetMethodID(env, cls, "getTime", "()J");
    jlong time = (*env)->CallLongMethod(env, date_obj, mid);
    return date_obj;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值