Android JNI dynamic registration
- Dynamic and static registration
- Dynamic registration
- JNI thread
Dynamic and static registration
- Static registration: Usually the default is static registration
Such as:
Static registration:
- Advantages: simple to use, convenient in the program will run when the initial call
- Disadvantages: Long class name, bundled with the class name, once changing the package name will be more troublesome
Dynamic registration
- Advantages: Initialization at the beginning of the run, simple code
- Disadvantages: More troublesome to use.
Static registration is not mentioned, this article mainly introduces dynamic registration
Dynamic registration
Dynamic registration is like calling the constructor of a class, which initializes all methods every time it is first run
In this method, complete all initializations in the Activity!
jint JNI_OnLoad(JavaVM *javaVm, void *) {
// Return the JNI version number
return JNI_VERSION_1_6;
}
Copy the code
JNI_OnLoad source code:
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved);
Copy the code
Step 1: Get the Env from the JVM, if returned! =0: Failed to get Env note :JVM is unique
// Get Env in the jVM
int result = javaVm->GetEnv(reinterpret_cast<void **>(&jniEnv), JNI_VERSION_1_6);
//result ! = 0 fails
if(result ! = JNI_OK) {/ / fail
return - 1;
}
Copy the code
This code is relatively simple not to say!
Step 2: Dynamically register the methods to be initialized with Env
/ / get jclass
jclass thread_class = jniEnv->FindClass(path);
/** * source code: * jint RegisterNatives(jclass clazz, const JNINativeMethod* methods, Jint nMethods) * Parameter one :class * Parameter two: structure array * parameter three: structure size */
jniEnv->RegisterNatives(thread_class, jniNativeMethod,
sizeof(jniNativeMethod) / sizeof(JNINativeMethod));
Copy the code
- Parameter 1: jclass
- Parameter 2 :JNINativeMethod structure
typedef struct {
const char* name; / / the method name
const char* signature; / / signature
void* fnPtr; // The callback function
} JNINativeMethod;
Copy the code
- Parameter 3 :JNINativeMethod Array length
Corresponding code of parameter 2:
void javaDynamicRegist(JNIEnv *jniEnv, jobject jobj) {
LOGE("javaDynamicRegist")}int javaDynamicRegist2(JNIEnv *jniEnv, jobject jobj, jstring name) {
const char *name2 = jniEnv->GetStringUTFChars(name, nullptr);
LOGE("javaDynamicRegist2%s\n", name2);
return 200;
}
/** typedef struct { const char* name; // Call name const char* signature; // Sign void* fnPtr; } JNINativeMethod; * /
static const JNINativeMethod jniNativeMethod[] = {
{"nativeDynamicRegist"."()V", (void *) javaDynamicRegist},
{"nativeDynamicRegist2"."(Ljava/lang/String;) I", (void *) javaDynamicRegist2},
};
Copy the code
Auxiliary graph:
Use:
Here native method error does not matter, this is normal state!
The running results are as follows:
2021- 04- 30 16:57:03.098 330- 330./com.example.jni E/native layer: javaDynamicRegist2021- 04- 30 16:57:03.098 330- 330./com.example.jni E/native layer: javaDynamicRegist2 li Yuan BaCopy the code
JNI thread
In C/C++, threads use pThreads
Pthread function | instructions |
---|---|
pthread_create() | The creation thread starts running the related thread function and exits when it finishes |
pthread_eixt() | Because exit() is used to end the process, a thread-specific terminating function is required |
pthread_join() | Suspend the current thread, used to block waiting for the thread to terminate, and return immediately if the thread has terminated, 0= success |
pthread_cancel() | Sending a termination signal to the thread returns 0 on success, but success does not mean that the thread will terminate |
Auxiliary code diagram:
Remember to guide the package:
#include <pthread.h>
Copy the code
Pthread_create () :
- Parameter 1: thread ID
- Parameter 2: Thread attribute (usually 0 or NULlptr)
- Parameter 3: Function callback
- Parameter 4: The value passed
Why set Jobject as a global variable? A: Jobject cannot span threads or functions.
Function callback:
void *my_thread_action(void *pVoid) {
MyThread *thread = static_cast<MyThread *>(pVoid);
/** * The JVM has only one jNIEnv solution: */
JNIEnv *newJniEnv = nullptr;
/** * jint AttachCurrentThread(JNIEnv** p_env, void* thr_args
jint result = ::jvm->AttachCurrentThread(&newJniEnv, nullptr);
// Result == 0 indicates success
if(result ! = JNI_OK) {return 0; // Attach failed, return
}
jclass j_c = newJniEnv->GetObjectClass(thread->jobj);
jmethodID j_id = newJniEnv->GetMethodID(j_c, "isThread"."()V");
// Call the Java layer isThread method
newJniEnv->CallVoidMethod(thread->jobj, j_id);
// Unattach
::jvm->DetachCurrentThread();
// The reference cannot be released directly
return nullptr;
}
Copy the code
The JVM is retrieved when JNI_OnLoad is initialized
jint JNI_OnLoad(JavaVM *javaVm, void *) {
::jvm = javaVm;
}
Copy the code
:: JVM is equivalent to this.jvm in Java
Finally calling the Java layer method:
Effect:
Note:
If the so library returns an error, comment out the other two
In the same way, if you want to see JNI basic use (native simp-lib.cpp) code, then JNI advanced and QQ voice practice code comment out!
Only one CPP file can now exist
The complete code
Other JNI articles:
Introduction to Android JNI
Android JNI :Android JNI
Android JNI QQ funny voice combat (including complete Demo)
Chapter 5 :JNI exception catching and handling
Original is not easy, your praise is my biggest support ~