#include <jni.h>
#include <string>
#include <android/log.h>
//
// Created by 15155 on 2022/11/23.
//
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "yuanrenxue->", __VA_ARGS__)
extern "C" JNIEXPORT jstring JNICALL
Java_com_yuanrenxue_course6_14_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C"
JNIEXPORT void JNICALL
Java_com_yuanrenxue_course6_14_MainActivity_demo(JNIEnv *env, jobject thiz) {
// TODO: implement demo()
__android_log_print((int) 6, "yuanrenxue->", "run here.");
__android_log_print((int) 6, "yuanrenxue->", "current jni version %d", env->GetVersion());
// jint version = env->GetVersion(); 获取JNI 版本
// JNI_VERSION_1_6;
//#define JNI_VERSION_1_1 0x00010001
//#define JNI_VERSION_1_2 0x00010002
//#define JNI_VERSION_1_4 0x00010004
//#define JNI_VERSION_1_6 0x00010006
//类操作
//1.获取对象Class jcalss com.yuanrenxue.course6_4 MysteryBox
jclass mysteryBoxClass = env->FindClass("com/yuanrenxue/course6_4/MysteryBox");
jclass clsClazz = env->GetObjectClass(mysteryBoxClass);
jmethodID jmethodId = env->GetMethodID(clsClazz, "getSimpleName", "()Ljava/lang/String;");
auto className = (jstring) env->CallObjectMethod(mysteryBoxClass, jmethodId);
const char *str = env->GetStringUTFChars(className, nullptr);
LOGD("获取对象 MysteryBox_Class_Name == %s", str);
// 2.获取一个类的父类
jclass parentClass = env->GetSuperclass(mysteryBoxClass);
clsClazz = env->GetObjectClass(parentClass);
jmethodId = env->GetMethodID(clsClazz, "getSimpleName", "()Ljava/lang/String;");
className = (jstring) env->CallObjectMethod(parentClass, jmethodId);
str = env->GetStringUTFChars(className, nullptr);
LOGD("获取一个类的父类 MysteryBox_Parent_Class_Name == %s",str);
//3.判断类型1是否可以安全的转换为类型2
jboolean IsAssignableFrom = env->IsAssignableFrom(mysteryBoxClass, parentClass);
LOGD("判断类型1是否可以安全的转换为类型2 mysteryBoxClass IsAssignableFrom parentClass== %d", IsAssignableFrom);
//对象操作
//1.不通过构造函数生成对象
jobject mysteryBoxCObject = env->AllocObject(mysteryBoxClass);
jmethodID toString_methodID = env->GetMethodID(mysteryBoxClass, "toString",
"()Ljava/lang/String;");
auto mysteryBoxCObject_toString_methodID = (jstring) env->CallObjectMethod(mysteryBoxCObject,
toString_methodID);
str = env->GetStringUTFChars(mysteryBoxCObject_toString_methodID, nullptr);
LOGD("不通过构造函数生成对象 mysteryBoxCObject_toString_methodID== %s", str);
//2.通过构造函数生成对象
jmethodID initMethod = env->GetMethodID(mysteryBoxClass, "<init>", "()V");
jobject MysteryObject2 = env->NewObject(mysteryBoxClass, initMethod);
toString_methodID = env->GetMethodID(mysteryBoxClass, "toString",
"()Ljava/lang/String;");
auto MysteryObject2_toString_methodID = (jstring) env->CallObjectMethod(
MysteryObject2,
toString_methodID);
str = env->GetStringUTFChars(MysteryObject2_toString_methodID, nullptr);
LOGD("通过构造函数生成对象 mysteryBoxClass, <init>, ()V== %s", str);
//3.根据对象获取对应的类
mysteryBoxClass = env->GetObjectClass(mysteryBoxCObject);
clsClazz = env->GetObjectClass(mysteryBoxClass);
jmethodId = env->GetMethodID(clsClazz, "getSimpleName", "()Ljava/lang/String;");
className = (jstring) env->CallObjectMethod(mysteryBoxClass, jmethodId);
str = env->GetStringUTFChars(className, nullptr);
LOGD("根据对象获取对应的类 MysteryBox_Class_Name == %s", str);
//4.判断某个对象是否为特定的实例
jboolean IsInstanceOf = env->IsInstanceOf(mysteryBoxCObject, mysteryBoxClass);
LOGD("判断某个对象是否为特定的实例 IsInstanceOf == %hhu",IsInstanceOf);
//属性操作
//1.获取非静态成员属性的ID mysteryBoxCObject price
jfieldID price_filed_id = env->GetFieldID(mysteryBoxClass, "price", "I");
//2.获取非静态成员属性的值(方法的合集)
jint price = env->GetIntField(MysteryObject2, price_filed_id);
LOGD("获取非静态成员属性的值 price == %d",price);
//3.设置非静态成员属性的值(方法的合集)
env->SetIntField(MysteryObject2, price_filed_id, 20);
price = env->GetIntField(MysteryObject2, price_filed_id);
LOGD("设置非静态成员属性的值 price == %d",price);
//4.获取静态成员属性的ID MysteryBox BASE_PRICE
jfieldID BASE_PRICE_filed_id = env->GetStaticFieldID(mysteryBoxClass, "BASE_PRICE", "I");
//5.获取静态成员属性的值
jint static_price = env->GetStaticIntField(mysteryBoxClass, BASE_PRICE_filed_id);
LOGD("获取静态成员属性的值 BASE_PRICE == %d",static_price);
//6.设置静态成员属性的值
env->SetStaticIntField(mysteryBoxClass, BASE_PRICE_filed_id, 666);
static_price = env->GetStaticIntField(mysteryBoxClass, BASE_PRICE_filed_id);
LOGD("设置静态成员属性的值 BASE_PRICE == %d",static_price);
//方法的操作 getContent
//1.获取非静态方法id
jmethodID getContentmethid = env->GetMethodID(mysteryBoxClass, "getContent",
"()Ljava/lang/String;");
//2.调用非静态方法
auto getContent = (jstring) env->CallObjectMethod(MysteryObject2, getContentmethid);
str = env->GetStringUTFChars(getContent, nullptr);
LOGD("调用非静态方法 getContent == %s",str);
//3.获取静态方法id staticMethod
jmethodID staticMethodID = env->GetStaticMethodID(mysteryBoxClass, "staticMethod",
"(Ljava/lang/String;I)Ljava/lang/String;");
//4.调用静态方法
jstring jstring1 = env->NewStringUTF("hell word!");
auto callstatic = (jstring) env->CallStaticObjectMethod(mysteryBoxClass, staticMethodID,
jstring1, 30);
str = env->GetStringUTFChars(callstatic, nullptr);
LOGD("调用静态方法 callstatic == %s", str);
/*
* 2022-12-06 01:34:45.102 6536-6536/com.yuanrenxue.course6 D/yuanrenxue->: onCreate: run sucess!!
2022-12-06 01:34:45.103 6536-6536/com.yuanrenxue.course6 E/yuanrenxue->: run here.
2022-12-06 01:34:45.103 6536-6536/com.yuanrenxue.course6 E/yuanrenxue->: current jni version 65542
2022-12-06 01:34:45.103 6536-6536/com.yuanrenxue.course6 E/yuanrenxue->: 获取对象 MysteryBox_Class_Name == MysteryBox
2022-12-06 01:34:45.103 6536-6536/com.yuanrenxue.course6 E/yuanrenxue->: 获取一个类的父类 MysteryBox_Parent_Class_Name == MysteryParentBox
2022-12-06 01:34:45.103 6536-6536/com.yuanrenxue.course6 E/yuanrenxue->: 判断类型1是否可以安全的转换为类型2 mysteryBoxClass IsAssignableFrom parentClass== 1
2022-12-06 01:34:45.103 6536-6536/com.yuanrenxue.course6 E/yuanrenxue->: 不通过构造函数生成对象 mysteryBoxCObject_toString_methodID== MysteryBox{content='null', isOpened=false, price=0, brand='null'}
2022-12-06 01:34:45.103 6536-6536/com.yuanrenxue.course6 E/yuanrenxue->: 通过构造函数生成对象 mysteryBoxClass, <init>, ()V== MysteryBox{content='普通款', isOpened=false, price=10, brand='手办盲盒'}
2022-12-06 01:34:45.104 6536-6536/com.yuanrenxue.course6 E/yuanrenxue->: 根据对象获取对应的类 MysteryBox_Class_Name == MysteryBox
2022-12-06 01:34:45.104 6536-6536/com.yuanrenxue.course6 E/yuanrenxue->: 判断某个对象是否为特定的实例 IsInstanceOf == 1
2022-12-06 01:34:45.104 6536-6536/com.yuanrenxue.course6 E/yuanrenxue->: 获取非静态成员属性的值 price == 10
2022-12-06 01:34:45.104 6536-6536/com.yuanrenxue.course6 E/yuanrenxue->: 设置非静态成员属性的值 price == 20
2022-12-06 01:34:45.104 6536-6536/com.yuanrenxue.course6 E/yuanrenxue->: 获取静态成员属性的值 BASE_PRICE == 10
2022-12-06 01:34:45.104 6536-6536/com.yuanrenxue.course6 E/yuanrenxue->: 设置静态成员属性的值 BASE_PRICE == 666
2022-12-06 01:34:45.104 6536-6536/com.yuanrenxue.course6 E/yuanrenxue->: 调用非静态方法 getContent == 这个盲盒没有打开哦
2022-12-06 01:34:45.104 6536-6536/com.yuanrenxue.course6 D/yuanrenxue->: staticMethod: name=hell word!, price=30
2022-12-06 01:34:45.104 6536-6536/com.yuanrenxue.course6 E/yuanrenxue->: 调用静态方法 callstatic == 我是静态方法变量
*/
}
void OnCreate(JNIEnv *env, jobject thiz, jobject savedInstanceState) {
//super.onCreate(savedInstanceState);
jclass MainActivity_cls1 = env->GetObjectClass(thiz);
jclass AppCompatActivity = env->GetSuperclass(MainActivity_cls1);
jmethodID onCreate = env->GetMethodID(AppCompatActivity, "onCreate", "(Landroid/os/Bundle;)V");
env->CallNonvirtualVoidMethod(thiz, AppCompatActivity, onCreate, savedInstanceState);
LOGD("super.onCreate(savedInstanceState);被调用");
//setContentView(R.layout.activity_main);
jmethodID setContentView_mid = env->GetMethodID(MainActivity_cls1, "setContentView", "(I)V");
char *R_layout = "com/yuanrenxue/course6_4/R$layout";
jclass layout = env->FindClass(R_layout);
jfieldID activity_main_fid = env->GetStaticFieldID(layout, "activity_main", "I");
jint activity_main = env->GetStaticIntField(layout, activity_main_fid);
env->CallVoidMethod(thiz, setContentView_mid, activity_main);
LOGD("setContentView(R.layout.activity_main); 被调用");
// //第一行:super.onCreate(savedInstanceState);因此首先需要获取superclass
// jclass AppCompatActivity_cls1 = env->FindClass(
// "androidx/appcompat/app/AppCompatActivity");//已经知道类名
// jclass MainActivity_cls1 = env->FindClass("com/yuanrenxue/course6_4/MainActivity");
////调用这个函数protected void onCreate(@Nullable Bundle savedInstanceState)
// jmethodID superclassOnCreate_mid = env->GetMethodID(AppCompatActivity_cls1, "onCreate",
// "(Landroid/os/Bundle;)V");
// env->CallNonvirtualVoidMethod(thiz, AppCompatActivity_cls1, superclassOnCreate_mid,
// savedInstanceState);
//
////第二行:setContentView(R.layout.activity_main);
// jmethodID setContentView_mid = env->GetMethodID(MainActivity_cls1, "setContentView", "(I)V");
// char *R_layout = "com/yuanrenxue/course6_4/R$layout";
// jclass R_layout_cls = env->FindClass(R_layout);
// jfieldID activity_main_fid = env->GetStaticFieldID(R_layout_cls, "activity_main",
// "I");//这里对应R$layout那个图看出来的
jint activity_main_value = env->GetStaticIntField(MainActivity_cls1, activity_main_fid);
env->CallVoidMethod(thiz, setContentView_mid, activity_main_value);
// private native String demoUTFString();
jmethodID demoUTFString = env->GetMethodID(MainActivity_cls1, "demoUTFString",
"()Ljava/lang/String;");
auto str = (jstring) env->CallObjectMethod(thiz, demoUTFString);
LOGD("private native String demoUTFString(); 被调用");
// Log.d(TAG, "onCreate: demoUTFString = " + this.demoUTFString());
jclass Log = env->FindClass("android/util/Log");
jmethodID d = env->GetStaticMethodID(Log, "d", "(Ljava/lang/String;Ljava/lang/String;)I");
jfieldID TAG_ID = env->GetStaticFieldID(MainActivity_cls1, "TAG", "Ljava/lang/String;");
jstring tag = static_cast<jstring>(env->GetStaticObjectField(MainActivity_cls1, TAG_ID));
env->CallStaticIntMethod(Log, d, tag, str);
LOGD("Log.d(TAG, \"onCreate: demoUTFString = \" + this.demoUTFString()); 被调用");
jmethodID exceptionMId = env->GetMethodID(MainActivity_cls1,"exception", "()V");
env->CallVoidMethod(thiz,exceptionMId);
LOGD("private native void exception(); 被调用");
}
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
__android_log_print(6, "yuanrenxue->", "JNI_OnLoad函数被调用");
JNIEnv *env = nullptr;
if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
return JNI_ERR;
}
//动态注册
// com.yuanrenxue.course6_4
jclass classzz = env->FindClass("com/yuanrenxue/course6_4/MainActivity");
/*
* jint RegisterNatives(jclass clazz, const JNINativeMethod* methods,
jint nMethods)
*/
/*
* typedef struct {
const char* name;
const char* signature;
void* fnPtr;
} JNINativeMethod;
*/
JNINativeMethod methods[] = {
{"onCreate", "(Landroid/os/Bundle;)V", (void *) OnCreate}
};
env->RegisterNatives(classzz, methods, 1);
return JNI_VERSION_1_6;
}
////同时静态注册 和 同时动态注册 会使用动态注册的
extern "C"
JNIEXPORT void JNICALL
Java_com_yuanrenxue_course6_14_MainActivity_exception(JNIEnv *env, jobject thiz) {
// TODO: implement exception()
jclass clazz = env->GetObjectClass(thiz);
env->GetStaticFieldID(clazz, "test1", "Ljava/lang/String;");
//1.在nativate处理异常 不抛给java
jthrowable jthrowable1 = env->ExceptionOccurred();
if (jthrowable1) {
//进入这里表示出现了异常 小根据需求进行异常的处理
LOGD("在nativate处理异常 不抛给java");
env->ExceptionClear();//清除掉当前的异常,防止程序崩溃
env->GetStaticFieldID(clazz, "test", "Ljava/lang/String;");
}
LOGD("在nativate处理异常 不抛给java");
//2.把异常抛给java
env->GetStaticFieldID(clazz, "test1", "Ljava/lang/String;");
if (jthrowable1) {
//进入这里表示出现了异常 小根据需求进行异常的处理
LOGD("把异常抛给java");
env->ExceptionDescribe();
env->ExceptionClear();//清除掉当前的异常,防止程序崩溃
env->GetStaticFieldID(clazz, "test", "Ljava/lang/String;");
// env->ThrowNew(env->FindClass("java/lang/Exception"),"nativate 把异常抛给java");
env->DeleteLocalRef(clazz); //释放资源
}
//3.抛出致命异常 程序退
env->FatalError("抛出致命异常 程序退出");
}