Android JNI cpp文件创建 java bean 对象并返回

具体的使用方式都在代码里面了。

  • 首先准备一个 Student 和 Person
class Student {
    var name: String? = null;
    var age: Int? = 0;
}

class Person {

    constructor(){
        Log.e("Person", "无参构造器");
    }

    constructor(age: Int) {
        Log.e("Person", "age = $age");
    }

}
  • MainActivity中调用 JNI 层的代码

class MainActivity : AppCompatActivity() {

    companion object {
        private const val TAG: String = "MainActivity";

        init {
            System.loadLibrary("native-lib")
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

    }

    fun onClick(view: View) {
    	// JNI创建并返回 student 对象
        val student = useObjectFromJNI();
        Log.d(TAG, student.name);
        // JNI 通过构造器创建 Person 对象
        useConstructorINI();
    }
    private external fun stringFromJNI(): String
    private external fun useObjectFromJNI(): Student;
    private external fun useConstructorINI();
}

  • JNI 实现如下
  • 创建 Student
// ------头文件
#include <jni.h>
#include <string>
#include <android/log.h>

#define TAG "ld"
#define log_debug(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)
#define log_info(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)


// 创建并返回student
extern "C"
JNIEXPORT jobject JNICALL
Java_com_lu_jni_MainActivity_useObjectFromJNI(JNIEnv *env, jobject thiz) {

    // 使用 Java 类
    // 创建 Student 对象

    // student 文件路径
    const char *student_path = "com/lu/jni/Student";
    // 获取 class
    jclass student_class = env->FindClass(student_path);
        // 创建对象 AllocObject局部引用  分配新 Java 对象而不调用该对象的任何构造函数。返回	该对象的引用。	
    // NewGlobalRef是全局引用
    jobject student = env->AllocObject(student_class);
    // 获取 jmethodID  (GetMethodID:第一个参数:jclass 第二个参数:要调用的方法名
    // 第三个参数 "(Ljava/lang/String;)V" 传入 java/lang/String 参数 返回Void
    // V -> void (L ;)引用类型写法 如果是Int 可以写成 (I)V  也可以写成  "(Ljava/lang/Integer;)V"
    jmethodID studentMethodId = env->GetMethodID(student_class, "setName", "(Ljava/lang/String;)V");
    jstring value = env->NewStringUTF("张三");
    // 调用 student 的 setName 方法
    env->CallVoidMethod(student, studentMethodId, value);

    // 通过构造方法创建 person 传入student
    const char *person_path = "com/lu/jni/Person";
    jclass person = env->FindClass(person_path);

    return student;
}

  • 创建 Person
// 下面是创建 Person 并传入构造器参数
jclass person;
extern "C"
JNIEXPORT void JNICALL
Java_com_lu_jni_MainActivity_useConstructorINI(JNIEnv *env, jobject thiz) {

    if (person == NULL) {
        log_debug("进入创建方法");
        const char *person_path = "com/lu/jni/Person";
        jclass tmpClass = env->FindClass(person_path);
        // NewGlobalRef 创建一个新的全局的引用,只能使用DeleteGlobalRef()函数销毁这个全局引用
        person = static_cast<jclass>(env->NewGlobalRef(tmpClass));
    }
    // <init> 代表构造器创建
    const char *constructor = "<init>";
    // 获取 jmethodID    ()V 代表无参数的构造器
    //jmethodID methodId = env->GetMethodID(person, constructor, "()V");
    //env->NewObject(person, methodId);

    // 如果是有参数的构造器  Person中传入int类型参数
    jmethodID methodId1 = env->GetMethodID(person, constructor, "(I)V");
    jobject personObj = env->NewObject(person, methodId1, 100);

}

  • 使用结束后回收一下 即使是在栈中创建出栈会自动弹出,但是也建议手动删除

// 使用完记得主动回收 如果是通过 new 来创建的对象是在堆内存中 一定要回收掉
void deleteClass(JNIEnv *env) {
    if (person != NULL) {
        // 释放全局对象
        env->DeleteGlobalRef(person);
        person = NULL;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章