Android NDK Development (1) ———— Android JNI Introduction and call Process __android

Source: Internet
Author: User
Tags comparison table goto svm

/********************************************************************************************
* author:conowen@ Big Bell
* e-mail:conowen@hotmail.com
* Http://blog.csdn.net/conowen
* Note: This article for the original, only as a learning exchange use, reproduced please indicate the author and source.

********************************************************************************************/


1. JNI Introduction

JNI is all called Java Native Interface (Java Local call). Starting with Java1.1, JNI became part of the Java platform, allowing Java code to interact with code written in other languages, such as c&c++. The concept of JNI was not introduced from the Android release.


2. JNI and NDK

Simply put, Android's NDK provides some cross-compilation tool chains and Android libraries, which can be invoked by developers when writing native language programs. The NDK provided by the Cross compilation tool chain compiles the c&c++ code that has already been written to build the library.

Of course, you can also build your own cross compilation environment without NDK tools and libraries. The library is then generated and, as long as the specification operates, it can generate a library file that can make the Java layer successfully invoke.


Using NDK to compile the local language can refer to this blog post: http://blog.csdn.net/conowen/article/details/7522667


3. JNI Call Process

As we all know, Android application layer classes are written in Java, these Java classes are compiled into a DEX file, must rely on the Dalvik virtual machine (dummy Machine) to execute. If you need to load the c&c++ function when executing a Java program, the Dalvik virtual machine will load the c&c++ library, (System.loadlibrary ("Libname"), and let the Java layer call these local functions smoothly. It's important to be clear that these c&c++ functions are not running in Dalvik virtual machines, so they work faster and faster than they do in Dalvik virtual machines.

After the Dalvik virtual machine successfully loads the library, it automatically looks for the Jni_onload function inside the library, which is used as follows:

(1) Tell the Dalvik virtual machine which JNI version the C library uses. If the Jni_onload () function is not specified in your library, the VM defaults to the oldest JNI 1.1 version of the library. But the new version of JNI does a lot of expansion, also optimizes some content, if need to use the new features of JNI, must declare JNI version in Jni_onload () function. Such as

result = Jni_version_1_4;

When there is no jni_onload () function, the Android debugging information makes the following prompt (no jni_onload found)

04-29 13:53:12.184:D/DALVIKVM (361): Trying to load lib/data/data/com.conowen.helloworld/lib/libhelloworld.so 0x44edea98
04-29 13:53:12.204:D/DALVIKVM (361): Added shared lib/data/data/com.conowen.helloworld/lib/ libhelloworld.so 0x44edea98
04-29 13:53:12.204:D/DALVIKVM (361): No Jni_onload found Com.conowen.helloworld/lib/libhelloworld.so 0x44edea98, skipping Init


(2) because the Dalvik virtual machine loads the C library, the first thing is to invoke the Jni_onload () function, so we can do some initialization work in jni_onload (), such as registering JNI functions, and so on. Registering local functions can speed up the efficiency of Java layer calls to local functions.


In addition: There is a jni_onunload () function corresponding to the jni_onload () function, and when the virtual machine releases the C library, the Jni_onunload () function is invoked to perform clean-up actions.



4. Examples (about the data type conversion in JNI and the common Jni method next blog introduction)

The following is an example of the onLoad.cpp in Havlenapetr's FFmpeg project:

OnLoad.cpp file #define TAG "Ffmpeg_onload" #include <stdlib.h> #include <android/log.h> #include "jniutils.

H "extern" C "{extern int register_android_media_ffmpegavrational (jnienv *env);
#ifdef build_with_convertor extern int register_android_media_ffmpeg (jnienv *env);
#endif extern int Register_android_media_ffmpegavformatcontext (jnienv *env);

extern int Register_android_media_ffmpegavinputformat (jnienv *env);
extern int Register_android_media_ffmpegavcodeccontext (jnienv *env);
extern int register_android_media_ffmpegutils (jnienv *env);

extern int Register_android_media_ffmpegavframe (jnienv *env);
#ifdef build_with_player extern int register_android_media_ffmpegplayerandroid (jnienv *env);

#endif static JAVAVM *SVM;
 * * Throw A exception with the specified class and a optional message. */int Jnithrowexception (jnienv* env, const char* className, const char* msg) {Jclass Exceptionclass = ENV-&GT;FINDCL
    Ass (className);
if (Exceptionclass = = NULL) {        __android_log_print (Android_log_error, TAG, "Unable to find exception class%s",
        ClassName);
    return-1;
			    } if (Env->thrownew (Exceptionclass, msg)!= Jni_ok) {__android_log_print (Android_log_error, TAG,
    "Failed throwing '%s '", ClassName, MSG);
return 0;
    } jnienv* getjnienv () {jnienv* env = NULL; if (svm->getenv (void**) &env, jni_version_1_4)!= jni_ok) {__android_log_print (Android_log_error, TAG
    	, "Failed to obtain jnienv");
    return NULL;
return to Env;
 /* * Register Native jni-callable methods.
 * "ClassName" looks Like "java/lang/string".
                             */int Jniregisternativemethods (jnienv* env, const char* ClassName, Const jninativemethod* gmethods, int nummethods)/* Jump from Com_media_ffmpeg_ffmpegplayer.cpp file to This, completes the final registration * to the Dalvik virtual machine (that is androidruntime) registers passes overThe local function contained in the parameter gmethods[] */{Jclass clazz;
    __android_log_print (Android_log_info, TAG, "registering%s natives\n", className);
    Clazz = Env->findclass (className); if (Clazz = NULL) {__android_log_print (Android_log_error, TAG, "Native Registration unable to find class '%s ' \"
        , className);
    return-1; } if (Env->registernatives (Clazz, Gmethods, Nummethods) < 0) {__android_log_print (Android_log_error, TA
        G, "Registernatives failed for '%s '", className);
    return-1;
return 0;
    When the//dalvik virtual machine loads the C library, the first thing is to invoke the Jni_onload () function Jint jni_onload (javavm* vm, void* reserved) {jnienv* env = null;//define JNI env
	Jint result = Jni_err;
	SVm = VM;
	 /*javavm::getenv prototype for Jint (*GETENV) (javavm*, void**, Jint); * The GETENV () function returns a Jni environment that is different for each thread, because the Dalvik virtual machine is usually multi-threading. When each thread calls Jni_onload (), the JNI env used is different, so we have to retrieve the vm->getenv * *///Get the JNI env if (Vm->geten) every time we enter the function. V ((void**) &env, jni_version_1_4)!= Jni_ok) {__android_log_print (Android_log_error, TAG, "GetEnv failed!");
    return result;

__android_log_print (Android_log_info, TAG, "Loading ..."); /* Start Registration * Incoming parameter is JNI env * because there are many classes below, only register_android_media_ffmpegplayerandroid (env) as an example * * * #ifdef Build_with_con Vertor if (register_android_media_ffmpeg (env)!= JNI_OK) {__android_log_print (Android_log_error, TAG, "can" T l
        Oad android_media_ffmpeg ");
    Goto end; #endif if (Register_android_media_ffmpegavformatcontext (env)!= JNI_OK) {__android_log_print (android_log_error
        , TAG, "can ' t load Android_media_ffmpegavformatcontext");
	Goto end; } if (Register_android_media_ffmpegavcodeccontext (env)!= JNI_OK) {__android_log_print (Android_log_error, TAG, "
        Can ' t load android_media_ffmpegavcodeccontext ');
	Goto end; } if (Register_android_media_ffmpegavrational (env)!= JNI_OK) {__android_log_print (Android_log_error, TAG, "can" T load anDroid_media_ffmpegavrational ");
    Goto end; } if (Register_android_media_ffmpegavinputformat (env)!= JNI_OK) {__android_log_print (Android_log_error, TAG, "can
    	' t load Android_media_ffmpegavinputformat ');
    Goto end; } if (Register_android_media_ffmpegutils (env)!= JNI_OK) {__android_log_print (Android_log_error, TAG, "can" t load and
		Roid_media_ffmpegutils ");
	Goto end; } if (Register_android_media_ffmpegavframe (env)!= JNI_OK) {__android_log_print (Android_log_error, TAG, "can" t load an
		Droid_media_ffmpegavframe ");
	Goto end; #ifdef Build_with_player if (register_android_media_ffmpegplayerandroid (env)!= JNI_OK) {//skip to----com_media_ffmpeg_
    	FFMpegPlayer.cpp file __android_log_print (android_log_error, TAG, "can ' t load android_media_ffmpegplayerandroid");
    Goto end;

    #endif __android_log_print (Android_log_info, TAG, "loaded");

result = Jni_version_1_4;
End:return result;



 }



Com_media_ffmpeg_ffmpegplayer.cpp Files/* * * * * * Due to the large amount of code, the beginning of the com_media_ffmpeg_ffmpegplayer.cpp part of the omission, only to post the relevant part of the registration function.
* * Static const char* CONST KCLASSPATHNAME = "Com/media/ffmpeg/ffmpegplayer"; 
 * * Due to gmethods[] is a < name, function pointers > Comparison table, in the program execution, * can call the Registernativemethods () function multiple times to replace the local function pointer, * so as to achieve the purpose of elastic call local function. */static Jninativemethod gmethods[] = {{"Setdatasource", "(ljava/lang/string;) V", (void *) Com_media _ffmpeg_ffmpegplayer_setdatasource}, {"_setvideosurface", "(landroid/view/surface;) V", (void *) COM_MEDIA_FFM Peg_ffmpegplayer_setvideosurface}, {"Prepare", "() V", (void *) Com_media_ffmpe G_ffmpegplayer_prepare}, {"_start", "() V", (void *) COM_MEDIA_FFMPEG_FFMPEGPL
    Ayer_start}, {"_stop", "() V", (void *) Com_media_ffmpeg_ffmpegplayer_stop}, {"Getvideowidth", "() I", (void *) Com_media_fFmpeg_ffmpegplayer_getvideowidth}, {"Getvideoheight", "() I", (void *) Com_media_ffmpe G_ffmpegplayer_getvideoheight}, {"Seekto", "(I) V", (void *) Com_media_ffmpeg_f Fmpegplayer_seekto}, {"_pause", "() V", (void *) Com_media_ffmpeg_ffmpegplayer 
    _pause}, {"IsPlaying", "() Z", (void *) com_media_ffmpeg_ffmpegplayer_isplaying}, {"GetCurrentPosition", "() I", (void *) Com_media_ffmpeg_ffmpegplayer_getcurrentposition}
    , {"Getduration", "() I", (void *) Com_media_ffmpeg_ffmpegplayer_getduration},               {"_release", "() V", (void *) Com_media_ffmpeg_ffmpegplayer_release}, {"_reset",   "() V", (void *) Com_media_ffmpeg_ffmpegplayer_reset}, {"Setaudiostreamtype",               "(I) V",              (void *) Com_media_ffmpeg_ffmpegplayer_setaudiostreamtype}, {"Native_init", "() V",            (void *) Com_media_ffmpeg_ffmpegplayer_native_init}, {"Native_setup", "(Ljava/lang/object;) V",                              (void *) Com_media_ffmpeg_ffmpegplayer_native_setup}, {"Native_finalize", "() V",                           (void *) Com_media_ffmpeg_ffmpegplayer_native_finalize}, {"Native_suspend_resume", "(Z) I",

(void *) Com_media_ffmpeg_ffmpegplayer_native_suspend_resume},}; int register_android_media_ffmpegplayerandroid (jnienv *env) {return jniregisternativemethods (env, KClassPathName,
	Gmethods, sizeof (gmethods)/sizeof (gmethods[0));
                             /* Jumps to the * Jint jniregisternativemethods in the OnLoad.cpp file (jnienv* env, const char* ClassName,
                             
	 Const jninativemethod* gmethods, int nummethods)
 */
}



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.