public void test01(View view) {
int[] ints = new int[]{1, 2, 3, 4, 5, 6};
String[] strs = new String[]{"李小龙", "李连杰", "李元霸"};
testArrayAction(99, "你好", ints, strs);
for (int anInt : ints) {
Log.d(TAG, "Java test01: anInt:" + anInt);
}
}
extern "C"
JNIEXPORT void JNICALL
Java_com_derry_as_1jni_1project_MainActivity_testArrayAction(JNIEnv *env, jobject thiz,
jint count,
jstring text_info,
jintArray ints,
jobjectArray strs) {
int countInt = count;
LOGI("参数一 countInt:%d\n", countInt);
const char *textInfo = env->GetStringUTFChars(text_info, NULL);
LOGI("参数二 textInfo:%s\n", textInfo);
int *jintArray = env->GetIntArrayElements(ints, NULL);
jsize size = env->GetArrayLength(ints);
for (int i = 0; i < size; ++i) {
*(jintArray + i) += 100;
LOGI("参数三 int[]:%d\n", *jintArray + i);
}
env->ReleaseIntArrayElements(ints, jintArray, 0);
jsize strssize = env->GetArrayLength(strs);
for (int i = 0; i < strssize; ++i) {
jstring jobj = static_cast<jstring>(env->GetObjectArrayElement(strs, i));
const char *jobjCharp = env->GetStringUTFChars(jobj, NULL);
LOGI("参数四 引用类型String 具体的:%s\n", jobjCharp);
env->ReleaseStringUTFChars(jobj, jobjCharp);
}
}

public void test02(View view) {
Student student = new Student()
student.name = "史泰龙"
student.age = 88
putObject(student, "九阳神功")
Log.d(TAG, "Java test02: student:" + student.toString())
}
// jobject student == Student
// jstring str == String
extern "C"
JNIEXPORT void JNICALL
Java_com_derry_as_1jni_1project_MainActivity_putObject(JNIEnv *env,
jobject thiz,
jobject student,
jstring str) {
const char *strChar = env->GetStringUTFChars(str, NULL)
LOGI("strChar:%s\n", strChar)
env->ReleaseStringUTFChars(str, strChar)
// --------------
// 1.寻找类 Student
// jclass studentClass = env->FindClass("com/derry/as_jni_project/Student")
jclass studentClass = env->GetObjectClass(student)
// 2.Student类里面的函数规则 签名
jmethodID setName = env->GetMethodID(studentClass, "setName", "(Ljava/lang/String;)V")
jmethodID getName = env->GetMethodID(studentClass, "getName", "()Ljava/lang/String;")
jmethodID showInfo = env->GetStaticMethodID(studentClass, "showInfo", "(Ljava/lang/String;)V")
// 3.调用 setName
jstring value = env->NewStringUTF("AAAA")
env->CallVoidMethod(student, setName, value)
// 4.调用 getName
jstring getNameResult = static_cast<jstring>(env->CallObjectMethod(student, getName))
const char *getNameValue = env->GetStringUTFChars(getNameResult, NULL)
LOGE("调用到getName方法,值是:%s\n", getNameValue)
// 5.调用静态showInfo
jstring jstringValue = env->NewStringUTF("静态方法你好,我是C++")
env->CallStaticVoidMethod(studentClass, showInfo, jstringValue)
}
public void test03(View view) {
insertObject();
}
// C++ 堆 栈 ...
// JNI函数 局部引用,全局引用,...
extern "C"
JNIEXPORT void JNICALL
Java_com_derry_as_1jni_1project_MainActivity_insertObject(JNIEnv *env, jobject thiz) {
/* //局部引用
jstring str0 = env->GetStringUTFChars()
jstring str1 = env->GetStringUTFChars()
jstring str2 = env->GetStringUTFChars()
jstring str3 = env->GetStringUTFChars()
jstring str5 = env->GetStringUTFChars()
jstring str6 = env->GetStringUTFChars()
jstring str7 = env->GetStringUTFChars()
// 好习惯:
// 我用完了,我就释放,在我函数执行过程中,不会导致 内存占用多
env->ReleaseStringUTFChars()
env->ReleaseStringUTFChars()
env->ReleaseStringUTFChars()
env->ReleaseStringUTFChars()
env->ReleaseStringUTFChars()
env->ReleaseStringUTFChars()
env->ReleaseStringUTFChars()*/
// 1.通过包名+类名的方式 拿到 Student class 凭空拿class
const char *studentstr = "com/derry/as_jni_project/Student"
jclass studentClass = env->FindClass(studentstr)
// 2.通过student的class 实例化此Student对象 C++ new Student
jobject studentObj = env->AllocObject(studentClass)
// env->NewObject() // NewObject 实例化对象,会调用对象的构造函数
// 方法签名的规则
jmethodID setName = env->GetMethodID(studentClass, "setName", "(Ljava/lang/String;)V")
jmethodID setAge = env->GetMethodID(studentClass, "setAge", "(I)V")
// 3.调用方法 setName
jstring strValue = env->NewStringUTF("Derry")
env->CallVoidMethod(studentObj, setName, strValue)
env->CallVoidMethod(studentObj, setAge, 99)
// ==================== 下面是 Person对象 调用person对象的 setStudent 函数等
// 4.通过包名+类名的方式 拿到 Student class 凭空拿class
const char *personstr = "com/derry/as_jni_project/Person"
jclass personClass = env->FindClass(personstr)
jobject personObj = env->AllocObject(personClass)
// setStudent 此函数的 签名 规则
jmethodID setStudent = env->GetMethodID(personClass, "setStudent",
"(Lcom/derry/as_jni_project/Student
env->CallVoidMethod(personObj, setStudent, studentObj)
// 规范:一定记得释放【好习惯】
// 第一类
env->DeleteLocalRef(studentClass)
env->DeleteLocalRef(personClass)
env->DeleteLocalRef(studentObj)
env->DeleteLocalRef(personObj)
// 第二类
// env->ReleaseStringUTFChars()
// TODO 局部引用: jobject jclass jstring ... 【函数结束后,会自动释放】
}
public void test04(View view) {
testQuote();
}
jclass dogClass
extern "C"
JNIEXPORT void JNICALL
Java_com_derry_as_1jni_1project_MainActivity_testQuote(JNIEnv *env, jobject thiz) {
if (NULL == dogClass) {
/*const char * dogStr = "com/derry/as_jni_project/Dog"
dogClass = env->FindClass(dogStr)
// 升级全局引用: JNI函数结束也不释放,反正就是不释放,必须手动释放 ----- 相当于: C++ 对象 new、手动delete
const char * dogStr = "com/derry/as_jni_project/Dog"
jclass temp = env->FindClass(dogStr)
dogClass = static_cast<jclass>(env->NewGlobalRef(temp))
// 记住:用完了,如果不用了,马上释放,C C++ 工程师的赞美
env->DeleteLocalRef(temp)
}
// <init> V 是不会变的
// 构造函数一
jmethodID init = env->GetMethodID(dogClass, "<init>", "()V")
jobject dog = env->NewObject(dogClass, init)
// 构造函数2
init = env->GetMethodID(dogClass, "<init>", "(I)V")
dog = env->NewObject(dogClass, init, 100)
// 构造函数3
init = env->GetMethodID(dogClass, "<init>", "(II)V")
dog = env->NewObject(dogClass, init, 200, 300)
// 构造函数4
init = env->GetMethodID(dogClass, "<init>", "(III)V")
dog = env->NewObject(dogClass, init, 400, 500, 600)
env->DeleteLocalRef(dog)
// dogClass = NULL
// 这样就解决了
/*env->DeleteGlobalRef(studentClass)
studentClass = NULL
}
public void test05(View view) {
delQuote();
}
extern "C"
JNIEXPORT void JNICALL
Java_com_derry_as_1jni_1project_MainActivity_delQuote(JNIEnv *env, jobject thiz) {
if (dogClass != NULL) {
LOGE("全局引用释放完毕,上面的按钮已经失去全局引用,再次点击会报错");
env->DeleteGlobalRef(dogClass);
dogClass = NULL;
}
show();
}
Test.cpp
#include <iostream>
#include <android/log.h>
#define TAG "JNISTUDY"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__);
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__);
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__);
int age = 99;
void show() {
LOGI("show run age:%d\n", age);
}