android nativate 动态注册 静态注册
说明:在java函数的入口比较容易分析,
把activity的生命周期或者关键函数通过放在so层,分析起来就困难多了
1、在MainActivity中
package com.demo.nativate; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; import com.demo.nativate.databinding.ActivityMainBinding; public class MainActivity extends AppCompatActivity { // Used to load the 'nativate' library on application startup. static { System.loadLibrary("nativate"); } private ActivityMainBinding binding; // @Override protected native void onCreate(Bundle savedInstanceState); // { // super.onCreate(savedInstanceState); // setContentView(R.layout.activity_main); // // Example of a call to a native method // TextView tv = findViewById(R.id.sample_text); // tv.setText(stringFromJNI()); // } /** * A native method that is implemented by the 'nativate' native library, * which is packaged with this application. */ public native String stringFromJNI(); }
2、静态注册
#include <jni.h> #include <string> #include <android/log.h> #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "Tag->", __VA_ARGS__) extern "C" JNIEXPORT jstring JNICALL Java_com_demo_nativate_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_demo_nativate_MainActivity_onCreate(JNIEnv *env, jobject thiz, jobject saved_instance_state) { // TODO: implement onCreate() LOGD("静态注册 MainActivity OnCreate be called!"); //super.onCreate(savedInstanceState); jclass MainActivityClass = env->GetObjectClass(thiz); jclass AppCompatActivityClass = env->GetSuperclass(MainActivityClass); jmethodID onCreate = env->GetMethodID(AppCompatActivityClass, "onCreate", "(Landroid/os/Bundle;)V"); env->CallNonvirtualVoidMethod(thiz, AppCompatActivityClass, onCreate, saved_instance_state); //调用父类方法 LOGD("静态注册 super.onCreate(savedInstanceState) be called!"); // setContentView(R.layout.activity_main); jmethodID setContentView_id = env->GetMethodID(MainActivityClass, "setContentView", "(I)V"); jclass layoutClass = env->FindClass("com/demo/nativate/R$layout"); jfieldID activity_main_id = env->GetStaticFieldID(layoutClass, "activity_main", "I"); jint id_txt_main = env->GetStaticIntField(layoutClass, activity_main_id); env->CallVoidMethod(thiz, setContentView_id, id_txt_main); LOGD("静态注册 setContentView(R.layout.activity_main); be called!"); // TextView tv = findViewById(R.id.sample_textFId); jmethodID findViewById_mid = env->GetMethodID(MainActivityClass, "findViewById", "(I)Landroid/view/View;"); jclass RIdClass = env->FindClass("com/demo/nativate/R$id"); jfieldID sample_textFId = env->GetStaticFieldID(RIdClass, "sample_text", "I"); jint sample_textF = env->GetStaticIntField(RIdClass, sample_textFId); LOGD("静态注册 TextView tv = findViewById(R.id.sample_textFId); be called!"); jobject tvobject = env->CallObjectMethod(thiz, findViewById_mid, sample_textF); // tv.setText(stringFromJNI()); jclass tvClass = env->GetObjectClass(tvobject); jmethodID setText_mid = env->GetMethodID(tvClass, "setText", "(Ljava/lang/CharSequence;)V"); jstring text = env->NewStringUTF("onCreate-->Native success by c++ !!!"); env->CallVoidMethod(tvClass, setText_mid, text); env->DeleteLocalRef(text); LOGD("静态注册 tv.setText(stringFromJNI());; be called!"); }
3、动态注册
#include <jni.h> #include <string> #include <android/log.h> #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "Tag->", __VA_ARGS__) extern "C" JNIEXPORT jstring JNICALL Java_com_demo_nativate_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_demo_nativate_MainActivity_onCreate(JNIEnv *env, jobject thiz, jobject saved_instance_state) { // TODO: implement onCreate() LOGD("静态注册 MainActivity OnCreate be called!"); //super.onCreate(savedInstanceState); jclass MainActivityClass = env->GetObjectClass(thiz); jclass AppCompatActivityClass = env->GetSuperclass(MainActivityClass); jmethodID onCreate = env->GetMethodID(AppCompatActivityClass, "onCreate", "(Landroid/os/Bundle;)V"); env->CallNonvirtualVoidMethod(thiz, AppCompatActivityClass, onCreate, saved_instance_state); //调用父类方法 LOGD("静态注册 super.onCreate(savedInstanceState) be called!"); // setContentView(R.layout.activity_main); jmethodID setContentView_id = env->GetMethodID(MainActivityClass, "setContentView", "(I)V"); jclass layoutClass = env->FindClass("com/demo/nativate/R$layout"); jfieldID activity_main_id = env->GetStaticFieldID(layoutClass, "activity_main", "I"); jint id_txt_main = env->GetStaticIntField(layoutClass, activity_main_id); env->CallVoidMethod(thiz, setContentView_id, id_txt_main); LOGD("静态注册 setContentView(R.layout.activity_main); be called!"); // TextView tv = findViewById(R.id.sample_textFId); jmethodID findViewById_mid = env->GetMethodID(MainActivityClass, "findViewById", "(I)Landroid/view/View;"); jclass RIdClass = env->FindClass("com/demo/nativate/R$id"); jfieldID sample_textFId = env->GetStaticFieldID(RIdClass, "sample_text", "I"); jint sample_textF = env->GetStaticIntField(RIdClass, sample_textFId); LOGD("静态注册 TextView tv = findViewById(R.id.sample_textFId); be called!"); jobject tvobject = env->CallObjectMethod(thiz, findViewById_mid, sample_textF); // tv.setText(stringFromJNI()); jclass tvClass = env->GetObjectClass(tvobject); jmethodID setText_mid = env->GetMethodID(tvClass, "setText", "(Ljava/lang/CharSequence;)V"); jstring text = env->NewStringUTF("onCreate-->Native success by c++ !!!"); env->CallVoidMethod(tvClass, setText_mid, text); env->DeleteLocalRef(text); LOGD("静态注册 tv.setText(stringFromJNI());; be called!"); } void dynamicRegister(JNIEnv *env, jobject thiz, jobject saved_instance_state) { LOGD("动态注册 MainActivity OnCreate be called!"); //super.onCreate(savedInstanceState); jclass MainActivityClass = env->GetObjectClass(thiz); jclass AppCompatActivityClass = env->GetSuperclass(MainActivityClass); jmethodID onCreate = env->GetMethodID(AppCompatActivityClass, "onCreate", "(Landroid/os/Bundle;)V"); env->CallNonvirtualVoidMethod(thiz, AppCompatActivityClass, onCreate, saved_instance_state); //调用父类方法 LOGD("动态注册 super.onCreate(savedInstanceState) be called!"); // setContentView(R.layout.activity_main); jmethodID setContentView_id = env->GetMethodID(MainActivityClass, "setContentView", "(I)V"); jclass layoutClass = env->FindClass("com/demo/nativate/R$layout"); jfieldID activity_main_id = env->GetStaticFieldID(layoutClass, "activity_main", "I"); jint id_txt_main = env->GetStaticIntField(layoutClass, activity_main_id); env->CallVoidMethod(thiz, setContentView_id, id_txt_main); LOGD("动态注册 setContentView(R.layout.activity_main); be called!"); // TextView tv = findViewById(R.id.sample_textFId); jmethodID findViewById_mid = env->GetMethodID(MainActivityClass, "findViewById", "(I)Landroid/view/View;"); jclass RIdClass = env->FindClass("com/demo/nativate/R$id"); jfieldID sample_textFId = env->GetStaticFieldID(RIdClass, "sample_text", "I"); jint sample_textF = env->GetStaticIntField(RIdClass, sample_textFId); LOGD("动态注册 TextView tv = findViewById(R.id.sample_textFId); be called!"); jobject tvobject = env->CallObjectMethod(thiz, findViewById_mid, sample_textF); // tv.setText(stringFromJNI()); jclass tvClass = env->GetObjectClass(tvobject); jmethodID setText_mid = env->GetMethodID(tvClass, "setText", "(Ljava/lang/CharSequence;)V"); jstring text = env->NewStringUTF("onCreate-->Native success by c++ !!!"); env->CallVoidMethod(tvClass, setText_mid, text); env->DeleteLocalRef(text); LOGD("动态注册 tv.setText(stringFromJNI());; be called!"); } static int registerNativates(JNIEnv *env) { jclass mainActivityClass = env->FindClass("com/demo/nativate/MainActivity"); if (mainActivityClass == nullptr) { return JNI_FALSE; } JNINativeMethod methods[] = { {"onCreate", "(Landroid/os/Bundle;)V", (void *) dynamicRegister} }; int methodsNum = sizeof(methods) / sizeof(methods[0]); if (env->RegisterNatives(mainActivityClass, methods, methodsNum) < 0) { return JNI_FALSE; } return JNI_TRUE; } jint JNI_OnLoad(JavaVM *vm, void *reserved) { LOGD("调用的 JNI_Onload函数"); //获得JNI环境 JNIEnv *env = nullptr; if ((vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6)) != JNI_OK) { return -1; } else { if (!registerNativates(env)) { return -1; } } return JNI_VERSION_1_6; }