How to compile the JNI module on the Android platform (2)

Source: Internet
Author: User

In the previous article, the Android platform SDK has been released to cupcake 1.5 (the latest development version may be later than this version, and we look forward to Android 2.0: d)

For Android 1.5 developers, the good news is that cupcake has started to "officially" support developers to compile their own JNI libraries, this is mainly because Google released an Android-ndk Development Kit, which is specially designed to develop some necessary header files and some runtime libraries for JNI, it provides more convenient script support for Android app developers. This kind of convenience and efficiency is not available in the sdks of Android 1.0 and 1.1 and related tools. After using ndk, I felt good. Even if I didn't use ndk before, I simply used a third-party compilation tool for JNI development, and publish a JNI code for testing.

I can see from the ndk statement that some of the ideas that Google puts forward when using JNI technology for development are as follows:
The ndk is ** not * a good way to write generic native code that runs on Android
Devices. In particle, your applications shoshould still be written in the Java
Programming Language, handle Android system events appropriately to avoid
"Application not responding" dialog or deal with the Android Application
Life-cycle.

Note however that is possible to write a sophisticated application in
Native code with a small "application wrapper" used to start/stop it
Appropriately.

A good understanding of JNI is highly recommended, since implements operations
In this environment require specific actions from the developers, that are
Not necessarily common in typical native code. These include:

-Not being able to directly access the content of VM objects through
Direct native pointers. E. g. You cannot safely get a pointer to
String object's 16-bit char array to iterate over it in a loop.

-Requiring explicit reference management when the native code wants
Keep handles to VM objects between jni cils.

The ndk only provides system headers for a very limited set of native
APIs and libraries supported by the Android platform. While a typical
Android system image between des between native shared libraries, these showould
Be considered an implementation detail that might change drastically
Updates and releases of the platform.

If an Android system library is not explicitely supported by the ndk
Headers, then applications shocould not depend on it being available, or
They risk breaking after the next over-the-air system update on various
Devices.

Selected system libraries will gradually be added to the set of stable ndk
APIS.

From the above point of view, we can see that Google has a strong confidence in the stability of Dalvik and the android framework. Therefore, developers are not recommended to use JNI technology (I personally think, they are worried that different levels of developers will affect the stability of their systems ), at the same time, it also warned developers that even using JNI technology may not significantly improve the running efficiency of the Program (I am skeptical about this, Java is actually a Java, how can the running efficiency of swaying scripts on the VM be compared with that of optimized native programs? Of course, this question is true to the benevolent, wise to the wise .)

In short, although Google provides ndk to easily build the JNI module of the Android platform, it is no difference to know that running several scripts is similar to not understanding it, I hope to understand the JNI technology of Android in principle.

So we started the JNI construction process of the "Tufa:
(1) Preparations for the tool chain
The first step, of course, is the JDK and Android sdks.
Second not, log onto the download page of The http://www.codesourcery.com, download the arm-2008q3-72-arm-none-linux-gnueabi.bin compilation tool (even Linux environment, different OS may be slightly different)
Then install and set the environment variables, and even paste the environment variable settings to back up them:
# For Midnight Commander default editor, I hate VI or Vim (sorry for Vi-ers)
Export editor = Emacs
Export viewer = Emacs

# For splint
Export larch_path =/usr/local/share/splint/lib
Export lclimportdir =/usr/local/share/splint/imports
Export Path =/usr/local/bin/splint: $ {path}

# For Android JNI developments
Export Path =/home/Wayne/codesourcery/sourcery_g ++ _ lite/bin: $ {path}

# For Android SDK
Export Path =/home/web/android-sdk-linux_x86-1.5_r1/tools: $ {path}
Export Path =/home/Wayne/jdk1.6.0 _ 12/bin :$ {path}
Export java_home =/home/Wayne/jdk1.6.0 _ 12
Export android_java_home =$ {java_home}
Export android_home =/home/Wayne/android-sdk-linux_x86-1.5_r1

# For Symbian s60 V3 Dev
Export Path =/home/Wayne/epoc_sdk/s60_31_fp1/tools_wrapper: $ path
Export epocroot =/home/Wayne/epoc_sdk/s60_31_fp1/

# For Android platform Codes
Export android_product_out =/home/Wayne/Works/android_source/out/target/product/generic

# For Android ndk
Export android_ndk_root =/home/Wayne/The android-ndk-1.5_r1/

# For Apache ant
Export Path =/usr/local/Apache-ant-1.7.1/bin :$ {path}
Export ant_home =/usr/local/Apache-ant-1.7.1

# For splint
Export larch_path =/usr/local/share/splint/lib
Export lclimportdir =/usr/local/share/splint/import

# For git
Export Path =/usr/local/bin: $ {path}

(2) create a jnitest Project
For details about how to create a command line, refer to the method in the first article.
Create a subdirectory named "JNI" under the jnitest Directory, which will be used to store. c files.

(3) Compile the Java call class of the JNI Module
This is inevitable. For JNI, a caller must be able to add an original file named jnimodule. Java in the innermost directory of SRC. It looks as follows:
Public class jnimodule {
Static {
System. loadlibrary ("aaaa ");
}
Public native static int jni_add (int A, int B );
}
Note that we will eventually generate a name called libaaaa. so's arm-compatible binary dynamic library, but in the use of system. when loadlibrary is dynamically loaded, you only need to enter lib and. the so name is AAAA. The function of this experiment is only to calculate the sum of two numbers A and B and to print log logs to logcat in the C language module of JNI.

In jnitest. Java, we can call this class as follows:
Public void onclick (view v ){
String SS;
Int A = 3;
Int B = 4;

Ss = "";
Switch (V. GETID ()){
Case R. Id. button1:
Ss = "A =" + String. valueof (A) + "," + "B =" + String. valueof (B) + "," + "A + B =" +
String. valueof (jnimodule. jni_add (a, B ));
Settitle (SS );
Break;
Case R. Id. button2:
Settitle ("button2 click ");
Break;
Case R. Id. button3:
Int pid = Android. OS. process. mypid ();
Android. OS. process. killprocess (PID );
Break;
}
}
Note: The button3 here is very important. The function is to get the process ID of the current program and then kill it explicitly!
Why? The reason is that the regular exit function in Android does not really close the currently running process, but switches to the background. This seems very common for common Java applications and can accelerate the speed of restarting the program, but it is a nightmare for Java programs with JNI modules because the program is not really closed. So the libaaaa. So library will remain in the memory. At this time, if you want to replace the old so library with the new library, you need to restart the mobile phone... It is very painful, so I think of this method to directly kill myself, so the next Startup will automatically reload the latest so library.

(4) generate interface files for Java and C Programs
Speaking of this, we will naturally think of C. H files. The question now is how to generate the. h format C/C ++ files from the. Java file. The answer is that the javah tool is basically provided by all JDK:
Javah-classpath "Java class address" <your Java module location>
Using javah, you can easily convert the native part of the jnimodule. Java code to the export function defined in the. h file of C/C ++.

The following is the makefile used for testing. I believe that anyone who understands the makefile syntax can easily understand what the makefile is doing,
In order to make the experiment very "accurate", all paths in this makefile adopt absolute paths. In fact, relative paths are also acceptable (saving too much effort, but when doing the experiment, the request is absolutely correct ...) :
Cc = arm-None-Linux-gnueabi-gcc
LD = arm-None-Linux-gnueabi-LD
MV = mv
Pipeline = javah
Jhflags =-classpath "/home/Wayne/Works/workspace/jnitest/bin"
Ldflags =-T "/home/Wayne/codesourcery/sourcery_g ++ _ lite/ARM-None-Linux-gnueabi/lib/ldscripts/armelf_linux_eabi.xsc"-shared
Cflags =-I. -I/home/Wayne/Works/workspace/jnitest/JNI/include/Linux-I/home/Wayne /Works/workspace/jnitest/JNI-FPIC

ALL: libaaaa. So

Com_hurraytimes_jnitest_jnimodule.h:
$ (Response) $ (jhflags) COM. hurraytimes. jnitest. jnimodule

Aaaa. O: AAAA. c com_hurraytimes_jnitest_jnimodule.h
$ (CC) $ (cflags)-c-o AAAA. o aaaa. c

Libaaaa. So: AAAA. o
$ (LD) $ (ldflags)-O libaaaa. So AAAA. O libcutils.
$ (RM) ../libs/armeabi/libaaaa. So
$ (MV) libaaaa. So ../libs/armeabi/

Clean:
$ (RM) *. O *. So *~

One thing that needs to be mentioned here is about the use of arm-None-Linux-gnueabi-GCC, this compiler has been pondering how to implement the "Cross Compiler" function more easily since version 2008. In the past, arm-xxx-Linux-GCC was used to compile the software on the arm-Linux platform. If your chip changes from Samsung to Phillips, then the entire tool chain needs to be re-compiled. In order to prevent developers (especially embedded developers on a variety of chip platforms) from installing many GCC tool chains for different chipsets on their computers, with a-t parameter, developers can use a GCC tool chain to generate executable code and linked libraries of different platforms and formats. Even so, I still don't feel quite used to it. In short, thanks to codesourcery's considerate functions, it took me more than half an hour to figure out and query the information, what causes the JNI module to fail to work on Android.

(5) JNI module packaging problems
Again, we declare that only Versions later than Android 1.5 cupcake can use the packaging method mentioned below.
After checking the ndk script, I realized that android 1.5 can directly package the APK. so's JNI library is packaged into the APK installation package, which solves the issue that even the hardcore C/C ++ developers develop their own JNI groupware release, java scripts, the transfer of an event will fulfill its mission.

In fact, the specific operation is very simple. Create the following directory under the following directory of the current project:
/Libs/armeabi
Copy the self-generated so Library to the armeabi directory. When you run ant to generate the APK release package, the so library under the/libs/armeabi directory will be automatically packaged into the APK file, and then installed directly! It is very simple and convenient.
(6) methods for calling JNI makefile in ant
First of all, ant is a good thing. However, if it is to replace makefile, it is hard for me to stubbornly think. The makefile syntax is simple, so you can just knock on one. But looking back at ant's build. XML, it looks dizzy at first glance.
XML is very good, but it's just a mess of his uncle, and he claims to say that it's something for people to see... Everything really has some substantial use, and the data stored in XML (used to demonstrate XML like Hello world is free of use) makes people look dizzy.

Ant uses XML as the basic input. I personally think it is better to follow makefile to get a relatively simple syntax.
Now let's stop complaining. Let's take a look at how to automatically call the jni makefile file for the XML implementation supported by ANT in Android build. xml.
The following is an example where ant is used to compile the xml of the jni module. It can be used for development and experiment with a slight modification. You can add this before </Project>:
<Target name = "MK">
<Exec dir = "./JNI" executable = "make" OS = "Linux" failonerror = "true">
</Exec>
</Target>

<Target name = "mkclr">
<Exec dir = "./JNI" executable = "make" OS = "Linux" failonerror = "true">
<Arg line = "clean"/>
</Exec>
</Target>
The method of use is ant MK and ant mkclr. One is equivalent to calling make, and the other is equivalent to calling make clean.
The rest of the operations are put in makefile (even though a Java friend tells me that everything makefile can be done by ANT and anything makefile cannot do by ant, I am still inclined to use makefile... In addition to being stubborn, the most important reason is that you are too lazy to think about so many things .).

The last thing we need to say is that in the code that is occasionally uploaded, we may find a code called libcutils. a's compiled static library is "coming soon", mainly because ndk was not released even during the experiment, android phones do not have any tools such as gdbserver, and debugging is very painful. I think how weak it is. Do you need to output something to logcat ?! Therefore, the header files of cutils are extracted from the source code of the Android-platform, and the binary files compiled by the Android platform are directly extracted. copy the file and link it to the so library generated by my "". In this way, you can call libcutils. the log function defined in a can be directly checked by online logcat to view the log output in JNI! The ndk documentation promises that the android ndk Development Kit will provide online debugging functions (gdbserver? Haha, with GDB, I think it is unrealistic for them to completely control Android. After all, GDB is too powerful ...)

So far, the methods for compiling and writing JNI by the "Tufa" have been basically recorded and explained. I believe that my friends who can patiently read this article will surely be able to have a new understanding of the nature of ndk. Instead of modifying the lines in the README and howto documents, you can modify cloud Clouds such as Android. mk...

Of course, with the above underlying compilation exploration, coupled with the ndk provided. H and several runtime libraries, and even the static Binary Package compiled in the source code of the Android platform, JNI can implement almost any function.

In other words, once the box of Pandora is opened, it cannot be controlled by companies like Google.
If you have time to write about how to use Google's ndk to compile and debug the JNI module...

My precious time... As you see, your life is slowly getting through the mess of code...

The attachment is all the test code of jnitest, hoping to help Android explorers.

Http://blog.chinaunix.net/link.php? Url = http://blogimg.chinaunix.net %2fblog%2fupfile2%2f090709115111.gz

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.