The NDK development of Android
I. Background of the NDK generation
The Android platform has supported C and C + + development since its inception. As we all know, the Android SDK is based on Java implementations, which means that third-party apps that are developed based on the Android SDK must use the Java language. But this is not the same as "third-party apps can only use Java." When the Android SDK was first released, Google announced that its virtual machine Dalvik supported JNI programming, which means that third-party applications could call their own C dynamic library through JNI, i.e., on Android, the "java+c" programming is always possible.
However, Google also said that the use of Native SDK programming compared to the Dalvik virtual machine has some disadvantages, the Android SDK documentation, no JNI help found. Even if third-party application developers use JNI to complete their own C dynamic-link library (SO) development, how so is packaged with the app as an APK and released? There are also technical barriers in this. For example, the program is more complex, compatibility is difficult to protect, unable to access the framework api,debug more difficult and so on. Developers need to use them at their own discretion.
So the NDK was born. The NDK full name is native development Kit.
The release of the NDK enabled the development of "Java+c" to become officially supported by the official development approach. The NDK will be the beginning of the Android platform to support c development.
Second, why use the NDK
1. Protection of the code. Because the Java layer Code of the APK is very easy to decompile, the C + + library is more difficult to reverse.
2. The existing open Source library is easy to use. Most of the existing open source libraries are written in C + + code.
3. Improve the efficiency of the execution of procedures. Use c development for application logic that requires high performance to improve application execution efficiency.
4. Easy to transplant. The library can be used in other embedded platforms easily.
Iii. introduction of NDK
1.NDK is a collection of a range of tools
The NDK provides a range of tools to help developers quickly develop C (or C + +) dynamic libraries and automatically package so and Java applications together as APK. These tools are great for developers.
The NDK integrates the cross compiler and provides the corresponding MK file isolation CPU, platform, ABI and other differences, developers simply need to modify the Mk file (stating "which files need to compile", "compilation characteristics Requirements", etc.), you can create a so.
The NDK can automatically package so with Java applications, greatly reducing the developer's packaging effort.
2.NDK provides a stable, feature-limited API header file declaration
Google expressly declares that the API is stable and supports the currently published API in all subsequent releases. As seen from this version of the NDK, these APIs support a very limited number of features, including: C standard library (LIBC), Standard math Library (LIBM), compression library (LIBZ), log Library (Liblog).
Iv. Building the NDK development environment
1. Download install android NDK
Address: http://developer.android.com/sdk/ndk/index.html
2. Download and install Cygwin
Since the NDK compiles code with make and GCC, you must first build a Linux environment, Cygwin is a UNIX simulation environment running on the Windows platform, for learning unix/linux operating environment, or porting applications from UNIX to Windows is useful. With it, you can use the NDK to compile C, C + + code without installing Linux. : http://www.cygwin.com
1) then double-click Run, and after running you will see the Installation wizard interface.
2) Click Next and let you choose how to install it now:
- Install from the Internet: downloaded directly from the Internet and installed immediately (after the installation is complete, the download installation files are not deleted, but are still retained for the next installation).
- Download without installing: Just download the installation file locally, but don't install it for the time being.
- Install from local directory: Do not download the installation files directly from one of the directories containing the installation files.
3) Select the first item and click Next.
4) Select the directory to install, note, it is best not to put in Chinese and white space in the directory, it seems to cause installation problems, other options do not change, then click Next:
5) The previous step is to choose the directory to install Cygwin, this is the directory where you download the installation package, the default is that you run the Setup.exe directory, directly click the next step:
6) At this time you have a total of three connection options:
- Direct Connection: Connect directly.
- Use IE5 Settings: Connect using IE's connection parameter settings.
- Use HTTP/FTP proxy: Connect using HTTP or FTP Proxy server (you need to enter the server address, port number).
Users can choose according to their own network connection situation, under normal circumstances, the choice of the first, that is, the direct connection method. Then click "Next".
7) This is the choice to download the site, select Next after point.
8) The list of loaded installation packages is downloaded at this time
9) Search is able to enter the name of the package you want to download and can quickly filter out the packages you want to download. The four radio buttons are the style of selecting the tree below, and by default it's OK to move. View default is category, suggest change to full show all package again check, some of the province's packages are hidden away. The bottom left corner of the check box is whether to hide the expired package, the default tick, do not care it on the line, the bottom to download the package we want to install, in order to avoid all download, here are listed below the development of the NDK needed package: autoconf2.1, automake1.10, Binutils, Gcc-core, gcc-g++, Gcc4-core, gcc4-g++, GDB, Pcre, Pcre-devel, gawk, make a total of 12 packages
10) then start choosing to install these packages, point skip, turn it into a digital version format, to ensure that the bin item into a fork, and the SRC item is the source code, this is not necessary to choose.
11) Let's test if the Cygwin is already installed.
Run Cygwin, in the popup command line window input: Cygcheck-c Cygwin command, will print out the current Cygwin version and running state, if the status is OK, then Cygwin run normally.
Then enter gcc–version,g++--version,make–version,gdb–version for testing, and if you print out the version information and some descriptive information, the Cygwin installation is successful!
3. Configure NDK Environment variables
A First find the Cygwin installation directory, find a home\< your user name >\.bash_profile file, mine is: E:\cygwin\home\Administrator\.bash_profile, ( Note: My home folder when I installed there is nothing, the solution: first open the environment variable, the inside of the user variable to delete the home variable, in the E:\cygwin\home folder under the folder named Administrator (is the user name), and then the E:\cygwin\etc\skel\.bash_profile copy to this folder).
b Open a. bash_profile file, add ndk=/cygdrive/< your drive letter >/<android NDK directory > For example:
Ndk=/cygdrive/e/android-ndk-r5
Export NDK
The NDK name is random, for the convenience of later use, choose a short name, and then save
C Open Cygwin, enter the CD $NDK, and if you output the/CYGDRIVE/E/ANDROID-NDK-R5 information configured above, the environment variable setting is successful.
4. Using the NDK to compile the program
A Now we use the installed NDK to compile a simple program, we choose the NDK's own example Hello-jni, I am located in E:\android-ndk-r5\samples\hello-jni (depending on your specific installation location),
b Run Cygwin, enter the command Cd/cygdrive/e/android-ndk-r5/samples/hello-jni, and go to the E:\android-ndk-r5\samples\hello-jni directory.
C Input $NDK/ndk-build, after successful execution, it will automatically generate a libs directory, put the compiled. so file inside. ($NDK is to invoke the environment variables we configured earlier, Ndk-build is the compiler that calls the NDK)
D At this time go to Hello-jni's libs directory to see if there are any generated. so files, if so, your NDK is functioning properly!
5. Integration of C/D + + development environment in eclipse
A Add-in for Eclipse: CDT, choose an online installation here. First sign in to http://www.eclipse.org/cdt/downloads.php to find the online installation address for your Eclipse version of the CDT plugin.
b Then click on the Help menu to find the Install New software menu
C Click the Add button, fill in the address, go out of the plugin list, select All, and then choose Next to complete the installation.
D After the installation is complete, right-click on the new project in Eclispe, and if a C + + project appears, your CDT plugin is successfully installed!
6. Configuring the C + + compiler
A Open Eclipse, import the NDK's own Hello-jni example, right-click the project name, click Properties, pop up the configuration screen, then click Builders, pop Up the project's compilation tool list, then click New, add a compiler, Click on the Add interface, select Program, click OK.
b The add interface appears, first to compile a name for the configuration, such as: C_builder, set location for < you cygwin installation path >\bin\bash.exe program, for example: E:\cygwin\bin\bash.exe, Set working directory to < your cygwin installation path >\bin directory, for example: E:\cygwin\bin, set Arguments to--login-c "cd/cygdrive/e/android-ndk- R5/samples/hello-jni && $NDK/ndk-build "
In the above configuration,/cygdrive/e/android-ndk-r5/samples/hello-jni is the directory of the program you are currently compiling, $NDK is the environment variable of the NDK that was previously configured, the two are configured according to your specific installation directory, the other does not change, Arguments This string of parameters is actually to bash.exe command-line program parameters, enter the program directory to be compiled, and then run the Ndk-build compiler program
C Then switch to the Refresh tab and give the refresh resources upon completion a hook
D Then switch to the Build Options tab and tick the last three items
E Then click on the Specify Resources button, select the Resource directory, tick your project directory to
F Finally click Finish, click OK all the way to save the previous configuration, note: If you configure the compiler under other compilers, remember to point up the up button, the first place, or C code compiled later than Java code compilation, will cause your C The code compiles two times to see the latest changes.
G Compile configuration is also configured to complete, now to test whether it can be automatically compiled, open the project JNI directory in the Hello-jni.c file to be prompted Hello from jni! Change to another text: Hello, My name is Alex. And then run your program in the emulator, if the emulator shows you the latest modified text, then congratulations! You have all the configuration success!
V. Develop your own NDK program
The best way to get started is to learn about Android's own example, which is done by learning about the Android NDK's own demo program: Hello-jni to achieve this goal.
1. Construction of development environment
1) The development of the NDK for Android needs to be done under Linux: Because of the need to generate. So files that are written in C/D + +, this requires a cross-compilation environment, and cross-compiling requires a Linux system.
2) Install the ANDROID-NDK Development Kit, which can be downloaded from the Google Android website: The tool of this development kit can be used to compile the code of Android JNI
3) Android application development environment: including Eclipse, Java, Android SDK, ADT, etc.
How to download and install ANDROID-NDK I'm not going to be verbose here. After installation, you need to add ANDROID-NDK to the environment variable path:
sudo gedit/etc/environment
Add the installation path of your ANDROID-NDK to the environment Path environment variable, and then let the changed environment variable take effect immediately:
Source/etc/environment
After the above steps, knock at the command line:
Ndk-bulid
The following error, instead of Ndk-build not found, indicates that the NDK environment has been successfully installed.
Android ndk:could not find application project directory!
Android ndk:please define the Ndk_project_path variable to the it.
/HOME/BRAINCOL/WORKSPACE/ANDROID/ANDROID-NDK-R5/BUILD/CORE/BUILD-LOCAL.MK:85: * * * Android ndk:aborting. Stop.
2. Writing the Code
1) First, write Java code
Build an Android App Engineering Hellojni, create a Hellojni.java file:
Hellojni.java:
Import android.app.Activity;
Import Android.widget.TextView;
Import Android.os.Bundle;
public class Hellojni extends Activity
{
/** called when the activity is first created. */
@Override
public void OnCreate (Bundle savedinstancestate)
{
Super.oncreate (savedinstancestate);
TextView TV = new TextView (this);
Tv.settext (Stringfromjni ());
Setcontentview (TV);
}
/* A Native method that's implemented by the ' hello-jni ' native library, which are packaged with this application. */
Public native String Stringfromjni ();
Public native String Unimplementedstringfromjni ();
/* This is used-load the ' Hello-jni ' Library on application startup. The library has already been unpacked into
/data/data/com.example.hellojni/lib/libhello-jni.so at installation time by the package manager. */
static {
System.loadlibrary ("Hello-jni");
}
}
This code is very simple, the comments are clear, here only two points::
?
static { System.loadLibrary( "hello-jni" ); } |
Indicates that the HELLO-JNI is loaded when the program starts running, and the code for the static zone declaration is executed before the OnCreate method. If you have more than one class in your program, and if the Hellojni class is not the entry for your application, then Hello-jni (the full name is libhello-jni.so) will be loaded the first time you use the Hellojni class.
?
public native String stringFromJNI(); public native String unimplementedStringFromJNI(); |
You can see the native keyword in the declaration of both methods, which means that the two methods are local methods, that is, the two methods are implemented by local code (c + +), which is simply a declaration in Java code.
Compile the project with Eclipse and generate the corresponding. class file, which must be completed before the next step, because the. h file is required for the corresponding. class file.
2) write the corresponding C + + code
At the beginning of the study, there was a question that would be confusing, how to write the corresponding C + + code, how to define the function name? Here's a way to use the Javah tool to generate the corresponding. h file, and then write the corresponding C + + code based on the. h file.
A. Generate the appropriate. h file:
Take me in this environment, first in the terminal into the newly created HELLOJNI project directory:
?
[email protected]:~$ cd workspace/android/NDK/hello-jni/ |
LS View project file
?
[email protected]:~/workspace/android/NDK/hello-jni$ ls AndroidManifest.xml assets bin default .properties gen res src |
You can see that there are currently only a few standard Android app files (clips).
First we create a JNI folder under the project directory:
?
[email protected]:~/workspace/android/NDK/hello-jni$ mkdir jni [email protected]:~/workspace/android/NDK/hello-jni$ ls AndroidManifest.xml assets bin default .properties gen jni res src |
The corresponding. h file can be generated below:
?
[email protected]:~/workspace/android/NDK/hello-jni$ javah -classpath bin -d jni com.example.hellojni.HelloJni |
-classpath Bin: Indicates the road strength of the class
-D JNI: The directory where the generated header file resides
Com.example.hellojni.HelloJni is the full class name
The success of this step is based on the creation of the Hellojni.class in the bin/com/example/hellojni/directory. Now you can see that the JNI directory has more than one. h file:
?
[email protected]:~/workspace/android/NDK/hello-jni$ cd jni/ [email protected]:~/workspace/android/NDK/hello-jni/jni$ ls com_example_hellojni_HelloJni.h |
Let's take a look at the contents of com_example_hellojni_hellojni.h:
Com_example_hellojni_hellojni.h:
/* Don't EDIT this file-it are machine generated */
#include <jni.h>
/* Header for class COM_EXAMPLE_HELLOJNI_HELLOJNI */
#ifndef _included_com_example_hellojni_hellojni
#define _included_com_example_hellojni_hellojni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_hellojni_hellojni
* Method: stringfromjni
* Signature: () ljava/lang/string;
*/
Jniexport jstring Jnicall Java_com_example_hellojni_hellojni_stringfromjni
(JNIENV *, jobject);
/*
* Class: com_example_hellojni_hellojni
* Method: unimplementedstringfromjni
* Signature: () ljava/lang/string;
*/
Jniexport jstring Jnicall Java_com_example_hellojni_hellojni_unimplementedstringfromjni
(JNIENV *, jobject);
#ifdef __cplusplus
}
#endif
#endif
The Jniexport and Jnicall in the above code are JNI macros that are not required in the jni of Android and, of course, are not error-written. From the above source code can be seen that the function name that is quite long ah .... But still very regular, exactly according to: Java_pacakege_class_mathod form to name.
Other words:
The Stringfromjni () method in Hello.java corresponds to the Java_com_example_hellojni_hellojni_stringfromjni () method in C/
The Unimplementedstringfromjni () method in Hellojni.java corresponds to the Java_com_example_hellojni_hellojni_ Unimplementedstringfromjni () method
Note the following comments:
Signature: () ljava/lang/string;
() ljava/lang/string; () indicates that the parameter of the function is empty (null here means that there are no parameters other than jnienv *, Jobject, jnienv*, Jobject is a required two parameter for all JNI functions, Represents the JNI environment and the corresponding Java class (or object) itself, respectively, ljava/lang/string; A String object that represents the return value of the function as Java.
B. Write the appropriate. C File:
HELLO-JNI.C:
#include <string.h>
#include <jni.h>
/* This is a trivial JNI example where we use a native method
* To return a new VM String. See the corresponding Java source
* File located at:
* Apps/samples/hello-jni/project/src/com/example/hellojni/hellojni.java
*/
Jstring Java_com_example_hellojni_hellojni_stringfromjni (jnienv* env, Jobject thiz)
{
Return (*ENV)->newstringutf (env, "Hello from JNI!");
}
This only implements the Java_com_example_hellojni_hellojni_stringfromjni method, and Java_com_example_hellojni_hellojni_ The Unimplementedstringfromjni method is not implemented because only the Stringfromjni () method is called in Hellojni.java, so Unimplementedstringfromjni () The method is not implemented or not, but it is advisable to put all the Java definitions of the local methods are implemented, write an empty function is OK ... There is always better than nothing.
The Java_com_example_hellojni_hellojni_stringfromjni () function simply returns a Jstring object with a content of "Hello from JNI!" (corresponding to a string object in Java). HELLO-JNI.C file has been written, and now you can delete the com_example_hellojni_hellojni.h file, of course, I still do, but I am accustomed to the need to clean up the files.
3) Compile hello-jni.c to generate the corresponding library
A write Android.mk file
To create a new android.mk file under the JNI directory (that is, the hello-jni.c sibling), the Android.mk file is an Android makefile file with the following content:
# Copyright (C) The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# You are not a use of this file except in compliance with the License.
# Obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# unless required by applicable or agreed to writing, software
# Distributed under the License is distributed on a "as is" BASIS,
# without warranties or CONDITIONS of any KIND, either express or implied.
# See the License for the specific language governing permissions and
# Limitations under the License.
#
Local_path: = $ (call My-dir)
Include $ (clear_vars)
Local_module : = Hello-jni
Local_src_files: = Hello-jni.c
Include $ (build_shared_library)
This androd.mk file is very short, let's take a line-by-row explanation:
Local_path: = $ (call My-dir)
A android.mk file must first define the Local_path variable. It is used to find source files in the development tree. In this example, the macro function ' My-dir ', provided by the compilation system, is used to return the current path (that is, the directory containing the android.mk file).
Include $ (clear_vars)
Clear_vars is provided by the build system, specifying that GNU makefile clears many local_xxx variables for you (such as Local_module, Local_src_files, local_static_libraries, etc...) , except Local_path. This is necessary because all the compilation control files are in the same GNU make execution environment, and all the variables are global.
Local_module: = Hello-jni
To compile the target object, the Local_module variable must be defined to identify each module that you describe in the Android.mk file. The name must be unique and does not contain any spaces.
Note: The compilation system will automatically generate the appropriate prefix and suffix, in other words, a shared library module named ' Hello-jni ' will generate ' libhello-jni.so ' files.
Important NOTE: If you name the library ' Libhello-jni ', the compilation system will not add any LIB prefixes and will generate ' libhello-jni.so ', This is to support the Android.mk file from the source code of the Android platform, if you really need to do so.
Local_src_files: = Hello-jni.c
The local_src_files variable must contain a C or C + + source code file that will be compiled into a module. Note that you do not have to list header files and include files here, because the compilation system will automatically find the dependent files for you; Just list the source code files that are passed directly to the compiler.
Note that the default C + + source file extension is '. cpp '. It is also possible to specify a different extension, as long as the local_default_cpp_extension variable is defined, do not forget to start the small dot (i.e. '. Cxx ' instead of ' cxx ')
Include $ (build_shared_library)
Build_shared_library means compiling a shared library, which is a compiled system-supplied variable, pointing to a GNU makefile script, responsible for collecting since the last call to ' include $ (clear_vars) ', defined in Local_ XXX variable, and decide what to compile and how to do it correctly. There are also build_static_library variable representations to generate a static library: lib$ (Local_module). A, build_executable represents the build executable.
B. Generating. So shared library files
The Andro file has been written, and you can now use the Ndk-build script in the Android NDK SDK to generate the corresponding. So shared library, as follows:
[Email protected]:~/workspace/android/ndk/hello-jni/jni$ CD.
[Email protected]:~/workspace/android/ndk/hello-jni$ ls
Androidmanifest.xml Assets bin Default.properties Gen Jni Libs obj res src
[Email protected]:~/workspace/android/ndk/hello-jni$ ndk-build
Gdbserver: [arm-linux-androideabi-4.4.3] Libs/armeabi/gdbserver
Gdbsetup:libs/armeabi/gdb.setup
install:libhello-jni.so = libs/armeabi/libhello-jni.so
You can see that the Libhello-jni.so shared library has been generated correctly, so let's go to the libs/armeabi/directory to see:
[Email protected]:~/workspace/android/ndk/hello-jni$ cd libs/
[Email protected]:~/workspace/android/ndk/hello-jni/libs$ ls
Armeabi
[Email protected]:~/workspace/android/ndk/hello-jni/libs$ cd armeabi/
[Email protected]:~/workspace/android/ndk/hello-jni/libs/armeabi$ ls
Gdbserver Gdb.setup libhello-jni.so
4) Recompile Hellojni project in Eclipse, build apk
After the HELLOJNI project is refreshed in Eclipse, the build apk,libhello-jni.so shared library will be packaged together in the APK file. Look at the results of the operation in the simulator.
Android NDK Development (RPM)