Introduction to ndk development and ndk Development
Reprinted please indicate the source:
Http://blog.csdn.net/yujun411522/article/details/46774035
This article is from: [yujun411522 blog]
1. BackgroundNDK (Native Develepment Kit) is a tool for developing an App using a local language (C or C ++), because the program is complex and difficult to guarantee compatibility in the previous development using a local language, unable to access the Framework API, debugging is more difficult and so on, So Google launched this local development tool to simplify the Java + local language process.
2 advantages
1. CodeProtection. Because the java-Layer Code of apk is easily decompiled, it is difficult to reverse the C/C ++ library. For details about the Android security mechanism, see Android code obfuscation.
2. You can easily use existing open source libraries. Most of the existing open-source libraries are written in C/C ++ code.
3. Improve Program ExecutionEfficiency. The high-performance application logic is developed using C to improve the application execution efficiency.
4. Ease of transplantation. The C/C ++ library can be easily used on other embedded platforms. Especially some apps with high performance requirements, such as mobile games, are generally developed using the Native language.
3. Windows environment Configuration(1) download NDK Development Kit: From the ndk-7, Google has improved the ndk operation, do not need to use cygwin to cross-compile, which greatly improves our development speed. Now the NDK has been output to r10e, directly from the kernel:
(2) configure the NDK directory of the system: in eclipse, configure the NDK location in window> Preferences> Android> NDK, that is, the location of the decompressed folder. Note that the above two steps are at the system scope level and only need to be configured once.
(3)
Add native support for projects: Right-click Android Tools on the project and choose Add Native Support ..., and then give it to us. so file name, for example: NDKTest, A jni directory will be generated later, and an NDKTest will be generated in this directory. cpp file, and an Android. mk file:
This mk file is very important and will be configured here later.
(4)
Create a Builder for the projectA. Project-> Properties-> Builders-> New, create a Builder. B. In the displayed Choose configuration type dialog box, select Program and click OK ]:
C. In the pop-up Edit Configuration dialog box, configure the tab Main ]. In Location, enter the path of the nkd-build.cmd and enter the TestNdk Location in Working Diretcoty.
D. in the Edit Configuration dialog box, click Refresh on the Configuration tab, and select Refresh resources upon completion ",
Select The "The entire workspace ",
Check "Recuresively include sub-folders ":
In the Edit Configuration dialog box, go to the Configuration tab Build options ].
Check "After a" Clean ". (After this operation is checked, If You Want To compile ndk, you only need to clean the project and start cross-compilation)
Check "During manual builds ",
Check "During auto builds ",
Select Specify working set of relevant resources "." Select the "jni" directory created in the NDKTest project: click "finish". Click "OK" to complete the configuration.
After the Builder is added to the project, it is generated on the console.
Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 9 in ./AndroidManifest.xml [armeabi] Compile++ thumb: NDKTest <= NDKTest.cpp[armeabi] StaticLibrary : libstdc++.a[armeabi] SharedLibrary : libNDKTest.so[armeabi] Install : libNDKTest.so => libs/armeabi/libNDKTest.so
So far, the third and fourth steps of the NDK configuration of the project are the most important. to configure the NDK correctly, perform the most critical NDK development.
4. NDK development of the project(1)
Compile a java FileThe native method is involved. The content is as follows:
package com.jni;public class JNITest { public static native int add(int a, int b); public static native String getHelloFromNative();}
(2)
Generate the. h header file(The first pitfall) You can use the javah command to find the project directory and use CMD to enter the directory.
Run javah-classpath bin/classes com. jni. JNITest
A header file com_jni_JNITest.h is generated in the project.
Note: when using the javah command, pay attention to three principles: 1. Class names must use full-path class names without extensions
2. Keep yourself in the appropriate directory,
3. correctly set the work class Path 4. If the class file is a package name + class name
If the first problem has a. class suffix, an error is returned.
When using the javah command, we often encounter an error: "class files cannot be found ":
The classpath parameter can be used here, and "bin/classes" should not be written as "/bin/classes". Otherwise, the classpath cannot be found.
So here we just need to enter the javah command in the correct format. Don't worry about it. What we need is to generate the header file. The operations I use here are: 1. Run cmd to enter the project root directory; 2. Run "javah-classpath bin/classes package name + type". Do not add the class suffix. Run the command to generate a header file in the project root directory and check the header file:
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_jni_JNITest */#ifndef _Included_com_jni_JNITest#define _Included_com_jni_JNITest#ifdef __cplusplusextern "C" {#endif/** Class: com_jni_JNITest* Method: add* Signature: (II)I*/JNIEXPORT jint JNICALL Java_com_jni_JNITest_add (JNIEnv *, jclass, jint, jint);/** Class: com_jni_JNITest* Method: getHelloFromNative* Signature: ()Ljava/lang/String;*/JNIEXPORT jstring JNICALL Java_com_jni_JNITest_getHelloFromNative (JNIEnv *, jclass);#ifdef __cplusplus}#endif#endif
So far, the first pitfall has been solved.
(3)
Compile the corresponding native FunctionCopy the header file to the jni directory of the project and create a file named com_jni_JNITest.c with the same name as the header file.
/* * com_jni_JNITest.c * * Created on: 2015-7-6 * Author: Administrator */#include "com_jni_JNITest.h"#include <stdlib.h>#include <stdio.h>#ifdef __cplusplusextern "C"{#endifJNIEXPORT jstring JNICALL Java_com_jni_JNITest_getHelloFromNative( JNIEnv *env, jclass arg) { jstring str = (*env)->NewStringUTF (env, "HelloWorld from JNI !"); return str;}JNIEXPORT jint JNICALL Java_com_jni_JNITest_add (JNIEnv *env, jclass arg, jint a, jint b) { return a + b;}#ifdef __cplusplus}#endif
Note: The header file and the C language file may or report an error, saying "jni cannot be parsed. h file ", the solution here is to import the library file for it: add the library file corresponding to the NDK to the project path: project → Properties → C/C ++ General → Paths and Symbols → distributed des → Add
ANDROID_NDK_HOME is the root directory of ndk. Here I add all the three platforms.
(4)
Android. mk file configuration(Second pitfall) We have actually generated the Android. mk file in Add Native Support. Now we only pay attention to two parts:
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE : = NDKTestLOCAL_SRC_FILES := com_jni_JNITest.cinclude $(BUILD_SHARED_LIBRARY)
Note the following two points:
LOCAL_MODULE: = NDKTest // The Name Of The generated library file. Do not modify it.
LOCAL_SRC_FILES: = Com_jni_JNITest.c // here is the corresponding native file. Generally, do not modify LOCAL_MODULE. Make sure that LOCAL_SRC_FILES is correct. Otherwise, the error "No implementation found for native xxx" is returned; the second pitfall is solved.
Clean the project now. At this time, if the header file and the C language file still report an error, say a syntax error, re-open the header file and the C language file, it may be that the project has not been re-constructed. Anyway, after cleaning again, we found that a libNDKTest. so file is generated under the obj/local/armeabi/objs Directory, which is the library file.
(5)
Call in java(Third pitfall) This call is also pitfall. First, there is a static code block to load the Connection Library file.
Static {// note that the error cannot be written here; otherwise, the Android NDK java. lang. unsatisfiedLinkError: findLibrary // returned null System. loadLibrary ("NDKTest"); // This place is a pitfall and must not be filled in incorrectly}
Be sure to write "NDKTest" here, and never write "libNDKTest. so ", the system will perform the corresponding operations according to the specific platform. If it is a windows platform, the previous" lib "and later" will be automatically added ". so ", here we need to be the same as the LOCAL_MODULE value in the mk file, otherwise the error is returned: java. lang. unsatisfiedLinkError: Couldn't load libNDKTest. so from loader dalvik. system. pathClassLoader findLibrary returned null.
After loading the library file, you can call the native function in java. Here, you can simply print the return value of the native function:
Protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); String str = JNITest. getHelloFromNative (); // native call TextView tv1 = new TextView (this); tv1.setText (str); setContentView (tv1 );}
Result:
Good. Call successful !!! This involves JNI. You can view the JNI introduction section.
There are many pitfalls involved in the development of NDK. The key step is to generate the header file, write the implementation file, configure the mk file, correctly load the library file in java, and finally call it.
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.