The previous section describes the JNI and basic usage in Android, which we summarize by analyzing the JNI instances in the Android source code.
A bridge leading to two different worlds
As we said before, JNI is like a bridge linking Java to the native world, and if there is no native layer of support on the Android platform for our systems, even virtual machines in Java are implemented through native.
Ii. Brief introduction of Mediascanner class
Mediascannerr completes the scanning of multimedia files in Android. For example, Mediascanner scans the system memory and SD card files, the results of the scan will be loaded in the database, the music in this application to see the list of the activity of the song album name, genre, song length and other information, Are all the information in the database that was put in the database after the scan and the last read.
Mediascanner This feature uses the three basic components of Android:
1, Mediascannerservice (derived from service), complete the scan task, and put the scan results into the media database.
2, Mediaprovider (ContentProvider derivative), for the Media Library related operation request, the general situation is to write, delete, check, more operation.
3, mediascannerreceiver receive the external scanning request.
Three, Mediascanner registration analysis
Open Mediascnner.java to see
static { system.loadlibrary ("Media_jni"); Native_init (); }
The dynamic link library is loaded here, and then the Native_init () method is called
private static native final void Native_init ();
Open Android_media_mediascanner.cpp to see the implementation of Native_init ()
This function gets a field ID, which in turn causes class initialization.//It's called from a static block in MEDIASC Anner, which won ' t run until the//first time an instance of this class is Used.static Voidandroid_media_mediascanner_nati Ve_init (jnienv *env) { logv ("Native_init"); Jclass clazz = Env->findclass (Kclassmediascanner); if (clazz = = NULL) { return; } Fields.context = Env->getfieldid (Clazz, "Mnativecontext", "I"); if (Fields.context = = NULL) { return; }}
The above registration method is static registration, in fact, there is a dynamic way to register
The Java native function and the JNI function are one by one corresponding, so in JNI, this relationship is recorded through the jninativemethoid structure. The following is the dynamic registry in Android_media_mediascanner.cpp.
Static Jninativemethod gmethods[] = {{"Processdirectory", "(ljava/lang/string; landroid/media/mediascannerclient;) V ", (void *) Android_media_mediascanner_processdirectory}, {" Proce Ssfile "," (ljava/lang/string; ljava/lang/string; landroid/media/mediascannerclient;) V ", (void *) Android_media_mediascanner_processfile}, {" SetLocale " , "(ljava/lang/string;) V", (void *) Android_media_mediascanner_setlocale}, {"Extractalbumart", (Ljava/io/filedescriptor;) [B], (void *) Android_media_mediascanner_extractalbumart}, {"Nativ E_init "," () v ", (void *) Android_media_mediascanner_native_init}, {" Native_setup "," () v ", (void *) Android_media_mediascanner_native_setup}, {" Native_finalize "," () V ", (void *) Android_media_mediascanner_native_finalize},};
JThe Ninativemethod structure is as follows:
Type struct{ const char* name; Const char* Signature; void* Fnptr;} Jninativemethod;
The first attribute is the name of a native function in Java
The second property is the signature of the parameter and return type
The third attribute is the native corresponding function name
The Androidruntime class provides a registernativemethods function to complete the registration work, implemented as follows:
/* Register native methods using JNI. *//*static*/int Androidruntime::registernativemethods (jnienv* env, const char* className, const jninativemethod* gmethods, int nummethods) { return jniregisternativemethods (env, ClassName, Gmethods, nummethods);}
Jniregisternativemethods is a help function provided by the Android platform.
In the actual application only two functions can be used to complete the dynamic registration work.
Jclass clazz = (*env)->findclass (env, className);(*env)->registernatives (env, Clazz, Gmethods, nummethods);
When the Java layer is installed to play the JNI dynamic library through System.loadlibrary, a function called Jni_onload is then found in the library. If so, call it, and the dynamic registration work is done here.
Jint jni_onload (javavm* vm, void* reserved) {jnienv* env = NULL; Jint result =-1; if (vm->getenv (void**) &env, jni_version_1_4)! = JNI_OK) {LOGE ("error:getenv failed\n"); Goto bail; } assert (env! = NULL); if (Register_android_media_mediaplayer (env) < 0) {LOGE ("Error:mediaplayer native registration failed\n"); Goto bail; } if (Register_android_media_mediarecorder (env) < 0) {LOGE ("Error:mediarecorder native registration failed\ n "); Goto bail; } if (Register_android_media_mediascanner (env) < 0) {LOGE ("Error:mediascanner Native registration failed\n" ); Goto bail; } if (Register_android_media_mediametadataretriever (env) < 0) {LOGE ("error:mediametadataretriever native re Gistration failed\n "); Goto bail; } if (Register_android_media_amrinputstream (env) < 0) {LOGE ("Error:amrinputstream native registration Faile D\n "); Goto bail; } if (Register_android_media_resampleinputstream (env) < 0) {LOGE ("Error:resampleinputstream native Registratio n failed\n "); Goto bail; } if (Register_android_media_mediaprofiles (env) < 0) {LOGE ("Error:mediaprofiles native registration Failed" ); Goto bail; } if (Register_android_mtp_mtpdatabase (env) < 0) {LOGE ("Error:mtpdatabase native registration failed"); Goto bail; } if (Register_android_mtp_mtpdevice (env) < 0) {LOGE ("Error:mtpdevice native registration failed"); Goto bail; } if (Register_android_mtp_mtpserver (env) < 0) {LOGE ("Error:mtpserver native registration failed"); Goto bail; }/* Success--Return valid version number */result = Jni_version_1_4;bail:return result;}
Deep understanding of Android (5)--Analysis of JNI in Android from Mediascanner