Android--jni Programming Detailed

Source: Internet
Author: User

The Android system does not allow a program to be used purely in C + +, which requires that the native (Native) code be embedded in the Java code Native c/c++--that is, by way of JNI. So JNI is very important for Android bottom-up developers.

How to package. So files into an. APK

Let's start with the simplest case, if there is a JNI implementation of the--libxxx.so file, then how to use it in the APK?

The implementation steps are as follows:

1, in your project root directory to establish Libs/armeabi directory;

2, copy the libxxx.so file to libs/armeabi/;

3. The. So file is already included in the. apk file of the ADT plugin automatically compiled output.

4, install the APK file, you can directly use the method in JNI;

I think I need to briefly explain the naming rules of libxxx.so, and follow the Linux tradition, lib.so is the format of the class library file name, but when you specify the library name in the Java system.loadlibrary ("Something") method, you cannot include the prefix-- LIB, and the suffix ——. so.

Ready to write your own JNI module

You must want to know how to write your own xxx.so, but this involves too much knowledge about JNI. Simply put: JNI is the Java platform-defined "Java standard" for interacting with native code on the host platform, and it typically has two usage scenarios: 1. Use legacy code (previously developed by C + +, Delphi), 2. To better and more directly interact with the hardware and achieve higher performance.

1. First create a Java class containing the native method:

Package Com.okwap.testjni;public Final class Myjni {//native method, public static native string SayHello (string name);}
2. Generate the. h file via the Javah command, as follows (com_okwap_testjni.h file):

#include #ifndef _included_com_okwap_testjni_myjni#define _included_com_okwap_testjni_myjni#ifdef __ Cplusplusextern "C" {#endifJNIEXPORT jstring jnicall Java_com_okwap_testjni_myjni_sayhello (jnienv *, Jclass, jstring); #ifdef __cplusplus} #endif #endif

This is a standard C language header file where Jniexport, Jnicall is the JNI keyword (in fact it is a macro without any content, only for indicative purposes), and Jint, Jstring is a mapping of int and java.lang.String types in the JNI environment. The definitions of these keywords can be seen in jni.h.

3. Implement the above methods in the Com_okwap_testjni.c file:

4, compilation-Two different compilation environments

The C language code above is compiled into the final. So dynamic library file in two ways:

Android NDK: The full name is Native Developer Kit, which is a tool for compiling local JNI source code, providing a convenient way for developers to integrate local methods into Android applications. In fact, the NDK, like the full-source compilation environment, uses Android's compilation system-that is, by android.mk files to control compilation. The NDK can run on Linux, Mac, Window (+cygwin) three platforms. For more details on how to use the NDK, please refer to the following information:

Full Source compilation environment: The Android platform provides a build-based compilation system that can be used to write the correct android.mk file for the app. This environment requires git to get the full source copy from the official website and compile it successfully, for more details please refer to: http://source.android.com/index.html

Whichever of the above two methods you choose, you must write your own android.mk file, please refer to the relevant documentation for writing the file.

The entry function of the JNI component--jni_onload (), Jni_onunload ()

When a JNI component is successfully loaded and unloaded, a function callback is performed, and when the VM executes to the system.loadlibrary (XXX) function, it first executes the jni_onload () function in the JNI component, and when the VM releases the component, it calls Jni_onunload ( function Look at the sample code first:

The OnLoad method, called Jint jni_onload (javavm* vm, void* reserved) {logi ("Jni_onload startup~~!") when System.loadlibrary () is executed; return jni_version_1_4;} OnUnload method, called void Jni_onunload (javavm* vm, void* reserved) {LOGE ("Call Jni_onunload ~~!!") when the JNI component is disposed;}

Jni_onload () has two important functions:

Specify JNI version: tells the VM that the component uses the JNI version (if the Jni_onload () function is not provided, the VM defaults to the oldest JNI 1.1 version), and if a new version of JNI, such as JNI version 1.4, is to be used, it must be by jni_onload () The function returns a constant jni_version_1_4 (defined in jni.h) to inform the VM.

The initialization setting, when the VM executes to the System.loadlibrary () function, immediately first calls the Jni_onload () method, so the initialization of various resources in the method is most appropriate.

The action of Jni_onunload () corresponds to Jni_onload (), which is called when the VM releases the JNI component, so that the resource release is most appropriate for the cleanup of the method.

Using the Registernativemethods method

For Java programmers, we may always follow: 1. Write Java classes with the native method;--->2. Use the Javah command to generate the. h header file;--->3. Writing code to implement the method in the header file, such an "official" process, But maybe some people can't stand the "ugly" method name, the Registernatives method can help you to insinuate the method in C + + to the native method in Java, without having to follow a specific method naming format. Let's take a look at the sample code:

Define the target class name static const char *classname = "com/okwap/testjni/myjni";//define Method insinuate relationship static Jninativemethod methods[] = {" SayHello "," (ljava/lang/string;) ljava/lang/string; ", (void*) sayhello},};jint jni_onload (javavm* vm, void* reserved) { declaring variable jint result = Jni_err; jnienv* env = Null;jclass clazz;int methodslenght;//Gets the JNI environment object if ((*VM)->getenv (VM, (void**) &env, jni_version_1_ 4) = JNI_OK) {LOGE ("error:getenv failed\n"); return jni_err;} ASSERT (env! = NULL);//Register local method. Load Target Class clazz = (*env)->findclass (Env,classname), if (clazz = = NULL) {LOGE ("Native Registration unable to find class '%s ' ", className); return jni_err;} Establishment method insinuate relationship//acquisition method Length Www.2cto.commethodsLenght = sizeof (methods)/sizeof (methods[0]); if ((*env)->registernatives ( Env,clazz, methods, Methodslenght) < 0) {LOGE ("Registernatives failed for '%s '", className); return jni_err;} result = Jni_version_1_4;return result;} The key to establishing a mapping relationship between C + + methods and Java methods is the JNINATIVEMETHOD structure, which is defined in jni.h as follows: typedef struct {Const char* Name;//java method name COnst char* Signature; Java method signature void* fnptr;//c/c++ function pointer} jninativemethod

The code that initializes the structure is referenced in the preceding example:

Define method insinuate relationship static Jninativemethod methods[] = {{"SayHello", "(ljava/lang/string;) ljava/lang/string;", (void*) SayHello },};

One of the more difficult to understand is the second parameter--signature the value of the field, in fact, these characters correspond to the function's parameter type/return type one by one, where the character in "()" represents the parameter, followed by represents the return value. For example, "() v" means void func (), "(II) v" denotes void func (int, int), and the corresponding relationship of each character is as follows:

Character Java Type C + + type
V void void
Z Jboolean Boolean
I Jint int
J Jlong Long
D jdouble Double
F jfloat Float
B Jbyte Byte
C Jchar Char
S Jshort Short

The array starts with a "[" and is represented by two characters:

Character Java Type C + + type
[Z Jbooleanarray boolean[]
[I Jintarray int[]
[F Jfloatarray float[]
[B Jbytearray byte[]
[C Jchararray char[]
[S Jshortarray short[]
[D Jdoublearray double[]
[J Jlongarray long[]

All of the above are basic types, and if the arguments are Java classes, start with "L" and ";" At the end, the middle is separated by "/" packet and the class name, and its corresponding C function parameter is Jobject, an exception is the String class, it corresponds to the C type jstring, for example: ljava/lang/string; , Ljava/net/socket; And so on, if the Java function is in an embedded class (also known as an inner class), use $ as the delimiter between the class names, for example: "Landroid/os/fileutils$filestatus;".

Using the Registernativemethods method is not just to change the ugly long method name, but the most important thing is to improve efficiency, because when the Java class calls to the local function through the VM, it usually relies on the VM to dynamically find the. So local function ( Therefore, they need a naming format for a particular rule, and if a method requires successive calls many times, it is searched every time, so using registernatives to register the local function with the VM can make it more efficient to find the function.

Another important use of the Registernativemethods method is that the runtime dynamically adjusts the mapping between the local function and the Java function values, requiring only multiple calls to the Registernativemethods () method and passing in different mapping table parameters.

Log output in JNI

You must be very familiar with the use of log.x (TAG, "message") series methods in Java code, as well as in C + + code, but first you want to include related header files. Unfortunately, you use a different compilation environment (refer to the two compilation environments above), and the corresponding header files are slightly different.

If it is in the full source compilation environment, as long as the include header file, you can use the corresponding Logi, LOGD and other methods, as well as define LOG_TAG,LOG_NDEBUG and other macro values, the sample code is as follows:

#define LOG_TAG "Hellojni" #define LOG_NDEBUG 0#define log_nidebug 0#define log_nddebug 0#include#include# Includejstring Java_com_inc_android_ime_hellojni_stringfromjni (jnienv* env,jobject thiz) {LOGI ("Call stringFromJNI! \ n "), return (*ENV)->newstringutf (env," Hello from JNI (Chinese)! ");
The log-related. h header file, in the following source path:

Myeclair\frameworks\base\include\utils\log.h
Myeclair\system\core\include\cutils\log.h

If you are compiling in the NDK environment, you need # include, the sample code is as follows:

#ifndef __jnilogger_h_#define __jnilogger_h_#include#ifdef _cplusplusextern "C" {#endif #ifndef log_tag#define LOG_TAG "My_log_tag" #endif # define LOGD (...) __android_log_print (android_log_debug,log_tag,__va_args__) #define LOGI (...) __ Android_log_print (android_log_info,log_tag,__va_args__) #define LOGW (...) __android_log_print (ANDROID_LOG_WARN, log_tag,__va_args__) #define LOGE (...) __android_log_print (android_log_error,log_tag,__va_args__) #define LOGF (...) __android_log_print (android_log_fatal,log_tag,__va_args__) #ifdef __cplusplus} #endif #endif

You can download the above header file to unify the usage differences between the two different environments. Also, do not forget to include the application of the class library in your Android.mk file, in both environments

Ifeq ($ (host_os), Windows)
#NDK环境下
Local_ldlibs: =-llog
Else
#完整






Android--jni Programming Detailed

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.