美文网首页Android-NDK/JNI
JNI开发之传递自定义对象

JNI开发之传递自定义对象

作者: GoMoon | 来源:发表于2019-09-29 09:12 被阅读0次

一、前言

Android进行JNI开发时,有可能需要传递自定义的Java对象,这里包括从Java层传到Natvie层,以及从Native层传到Java层,本文将分别对这两种场景做简单的介绍。

二、 先定义一个Java对象

public class Book {

    private String title;

    private int year;

    private float price;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }
}

三、把对象从Java层传到Native层

先上一个表,后面会用到

Java 类型 字段符号
boolean Z
byte B
char C
short S
int I
long L
float F
double D
void V
String Ljava/lang/String;

Native层代码:

#include <jni.h>
#include <string>
#include<android/log.h>

#define TAG "NDK"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__)

//从Java层传递Book对象到Native
extern "C" JNIEXPORT void JNICALL
Java_com_jack_jnidemo_MainActivity_java2Native (
        JNIEnv* env,
        jobject object,
        jobject book) {
    jclass booCls = env->GetObjectClass(book); //获得java对象的引用
    if(booCls == NULL) {
        LOGD("book is null");
    }
    //env->GetFieldID,该方法能获取到对象字段的引用,最后一个参数参见上表
    jfieldID titleField = env->GetFieldID(booCls,"title","Ljava/lang/String;");
    jfieldID yearField = env->GetFieldID(booCls, "year","I");
    jfieldID priceField = env->GetFieldID(booCls, "price","F");
    //env->GetIntField得到字段对应的值
    jstring title = (jstring)env->GetObjectField(book  titleField);
    jint year = env->GetIntField(book, yearField);
    jfloat price = env->GetFloatField(book, priceField);

    const char * c_title = env->GetStringUTFChars(title, NULL);
    LOGD("书名:%s", c_title);
    LOGD("出版年份:%d", year);
    LOGD("价格:%f",price);

    env->ReleaseStringUTFChars(title,c_title);
}

Java层简单定义一下Native方法就可以直接调用:

public native void java2Native(Book book);

四、把一个对象从Native传到java层

先上Native层代码:

//把一个对象从Native传到java层
extern "C" JNIEXPORT jobject JNICALL
Java_com_jack_jnidemo_MainActivity_native2Java(
        JNIEnv* env,
        jobject object) {
    jclass booCls = env->FindClass("com/jack/jnidemo/Book"); //获得Book类的引用
    if(booCls == NULL){
        LOGD("book is null");
    }
    //构造函数
    jmethodID constrocID = env->GetMethodID(booCls,"<init>","()V");

    //利用构造函数生成一个对象
    jobject bookObj = env->NewObject(booCls,constrocID);

    //先拿到字段,准备赋值
    jfieldID titleField = env->GetFieldID(booCls,"title","Ljava/lang/String;");
    jfieldID yearField = env->GetFieldID(booCls,"year","I");
    jfieldID priceField = env->GetFieldID(booCls,"price","F");

    //赋值
    jstring cTitle = env->NewStringUTF("来自Native层");
    env->SetObjectField(bookObj, titleField, cTitle);

    jint year = 2018;
    env->SetIntField(bookObj, yearField, year);

    jfloat pricce = 35.5;
    env->SetFloatField(bookObj, priceField, pricce);

    return bookObj;
}

Java层简单定义一下Native方法就可以直接调用:

public native Book native2Java();

五、总结

可以看出,JNI传递自定义对象并不复杂,上面的代码基本能满足日常开发需求。

相关文章

网友评论

    本文标题:JNI开发之传递自定义对象

    本文链接:https://www.haomeiwen.com/subject/dkbzectx.html