This is my translation. It will introduce how to install Android ndk and start using it. After this tutorial is complete, you will create your own project and use the Java code to simply call the native C language code.
Tutorial details
Technology:Android SDK, ndk, and C Language
Difficulty:Advanced
Expected completion time:60-90 minutes)
Prerequisites:
Before you start, you need to take some time to understand the difficulty of this tutorial. It is marked as "advanced ". The reason we mark it as "advanced" is that the author wants to ensure that you meet the following requirements:
1. Have experience in Java and C language.
2. It can adapt to command line operations.
3. Know how to understand your cygwin, awk, and other tool versions.
4. can adapt to Android development.
5. There is an effective Android Development Environment (I used Android 2.2 When writing this article)
5. Use eclipse or easily apply the eclipse instructions to your ide.
6. Even if these conditions are not met, you are welcome to read this tutorial, but may encounter difficulties in some steps.
If the above conditions are met, these difficulties will be easily lifted. That is to say, even if you think you are a mobile development veteran, using ndk is still easy to encounter difficulties and troubles. Please note that you may need to troubleshoot the fault on your own so that everything can run properly in your development system.
This tutorial provides the complete open source code for the sample project. (I found the downloaded stuff)
Description of when to use ndk
Well, you are reading this tutorial. Maybe you are considering using ndk in your android project. However, the author wants to spend some time discussing why ndk is so important, when it should be used, and -- equally important, when it should not be used.
In general, you only need to use ndk when the application is really a processor killer. That is to say, the algorithm you designed should use all the processor resources of dalvikvm, and the Native operation is more advantageous. Also, don't forget that in Android 2.2, the JIT compiler will improve the efficiency of similar code.
Another reason for using ndk is convenient transplantation. If you have a large amount of C-language code in your existing applications, using ndk not only accelerates the development process of your project, but also keeps modifications synchronized between your android and non-android projects. This is especially true for OpenGL ES applications written for other platforms.
Don't think that as long as native code is used, application efficiency can be improved. Conversion between Java and native C languages increases resource overhead. Therefore, this is really necessary only when you have tasks that consume CPU resources in a centralized manner.
Step 2: Download the tool
Now, let's get started! You need to download the ndk. Download the tool first, because you can check it during the download process to make sure that the versions of other required tools are correct.
Download the ndk suitable for your operating system from the android website.
Check your tool Version against the following:
1. If cygwin 1.7 or later is in windows
2. Upgrade awk to the latest version (we use 20070501)
3. GNU make 3.81 or later (we use 3.81)
If any of the versions is too old, upgrade them before continuing.
Step 2: Install ndk
Since the ndk has been downloaded (right ?), You need to decompress it. Decompress the package and put it in a suitable directory. Put it in the same directory as the android SDK.Remember where you put it.
Now, you may want to add the ndk tool in path settings. If you are on Mac or Linux, you can use your native path settings. If you are running cygwin in Windows, you need to set the cygwin path.
Step 2: Create a project
Create a regular Android project. To avoid future problems, the path of your project must not contain spaces. The author's project has a package named "com. mamlambo. sample. ndk1" with a default activity called "androidndk1sampleactivity"-you will see them later.
Create a directory named "JNI" on the top of the project-this is where you place native code. If you are familiar with JNI, you will know that android ndk is based on the JNI concept to a large extent-it is essentially a JNI with only a limited header file compiled in C language.
Step 2: add some C-language code
Now, create a file named native. c In the JNI folder. Write the following C language code to this file at the beginning, and we will add another function later:
- # Include
- # Include
- # Include
- # Define debug_tag "ndk_androidndk1sampleactivity"
- Void java_com_mamlambo_sample_ndk1_androidndk1sampleactivity_hellolog (jnienv * ENV, jobject this, jstring logthis)
- {
- Jboolean iscopy;
- Const char * szlogthis = (* env)-> getstringutfchars (ENV, logthis, & iscopy );
- _ Android_log_print (android_log_debug, debug_tag, "ndk: LC: [% s]", szlogthis );
- (* Env)-> releasestringutfchars (ENV, logthis, szlogthis );
- }
Copy code
This function is actually very simple. It obtains the string parameter of a Java object, converts it to a C-string, and writes it to logcat.
However, the function name is very important. It starts with a specific word "Java", followed by the package name, class name, and method name, which is the same as that defined in Java. Each part is separated by an underscore instead of a dot.
The first two parameters of the function are also important. The first parameter is the JNI environment, which is frequently called with the Helper function. The second parameter is the Java object to which the function belongs.
Step 2: Call native code from Java
Now that you have written the native code, let's look back at the Java side. In the default activity, create a button according to your preferences and add a button processor. Call hellolog from the button processor:
- Hellolog ("This will log to logcat via the native call .");
Copy code
Then you must add a function declaration in Java. Add the following declaration to your activity class:
- Private native void hellolog (string logthis );
Copy code
It tells the compilation and linking system that this method will be implemented in the native code.
Finally, you need to load the library to which the native code is finally compiled. Add the following static initialization program to the activity class to load the database by name (the Library name is determined by your choice and will be used in the next step ):
- Static {
- System. loadlibrary ("ndk1 ");
- }
Copy code
Step 2: add the make file of native code
In the JNI folder, now you need to add the makefile to be used in compilation. This file must be named "android. mk". If the file you named earlier is native. C and the library is ndk1, the content of Android. mk should be like this:
- Local_path: = $ (call my-DIR)
- Include $ (clear_vars)
- Local_ldlibs: =-llog
- Local_module: = ndk1
- Local_src_files: = native. c
- Include $ (build_shared_library)
Copy code
Step 2: Compile native code
Now that your native code is complete and the make file is ready, it is time to compile the native code. In the command line (for Windows users in cygwin), you need to run the ndk-build command in the root directory of your project. The ndk-build tool is in the ndk tool directory. It is the most convenient way to add it to our path.
In subsequent compilation, if you use the "ndk-build clean" command, you can ensure that everything is re-compiled.
Step 2: run the code
Now you are ready to run the code. Load the project in your favorite simulator or handheld device, view logcat, and then click the button.
Two things may happen. First, it may work normally. Congratulations! However, you may want to continue reading.
You may also get errors like "cocould not execute method of activity" in logcat. This is normal. This only indicates that you missed a step. Eclipse is prone to this situation. Generally, eclipse is set to automatically recompile.
If it does not know that something has been modified, it will not automatically recompile and relink. In this example, eclipse does not know that you have compiled the native code. Therefore, the "cleaning" project (click Project> clean in the eclipse toolbar) will force eclipse to recompile.
Step 2: add another native Function
The following functions not only demonstrate the ability to return values, but also demonstrate the ability to return objects such as strings. Add the following functions to native. C:
- Jstring java_com_mamlambo_sample_ndk1_androidndk1sampleactivity_getstring (jnienv * ENV, jobject this, jint value1, jint value2)
- {
- Char * szformat = "the sum of the two numbers is: % I ";
- Char * szresult;
- // Add the two values
- Jlong sum = value1 + value2;
- // Malloc room for the resulting string
- Szresult = malloc (sizeof (szformat) + 20 );
- // Standard sprintf
- Sprintf (szresult, szformat, sum );
- // Get an object string
- Jstring result = (* env)-> newstringutf (ENV, szresult );
- // Cleanup
- Free (szresult );
- Return result;
- }
Copy code
For normal compilation, you need to add an include stdio. H Statement. In addition, to respond to this new Native function, add the following declaration in your activity Java class:
- Private native string getstring (INT value1, int value2 );
Copy code
Now you can set the function as needed. We use the following two calls and outputs:
- String result = getstring (5, 2 );
- Log. V (debug_tag, "Result:" + result );
- Result = fig (105,123 2 );
- Log. V (debug_tag, "result2:" + result );
Copy code
Back to the C language function, you will notice that we have done a lot of things. First, we need to create a buffer when using the sprintf () call in the malloc () function ). If you do not forget to clear the result by using the free () function, this is reasonable.
Then, to return the result, you can use a JNI helper function called newstringutf. This function is basically used to obtain a C-language string and create a new Java object. This new String object can be returned as a result later, and you can use it as a regular Java String object in the Java class.
Instruction Set, compatibility
Android ndk requires the android SDK 1.5 or later. In the new version of ndk, some new header files can be used to expand access to some APIs-especially OpenGL ES libraries.
However, none of them are compatible. This is the native code, which is compiled by the processor architecture during use. So what kind of processor architecture does it support? In the current ndk (when writing this article), it only supports armv5te and ARMv7-A instruction sets. By default, the target architecture is set to armv5te, which can run on Android devices using ARM chips.
It is expected to support other instruction sets in the future (including x86 ). This has an interesting potential: The ndk solution cannot be applied to all devices. For example, an Intel (Intel) Atom processor Android tablet with x86 instruction sets is available on the market.
So what about the ndk on the simulator? The simulator runs real virtual machines, including full processor virtual machines. Yes, that means running Java in a virtual machine is equivalent to running a virtual machine in the virtual machine.
Summary
What are the results? After you installed Android ndk, have you finally completed some fully functional and running applications that use native C-language code? We hope so. There are many potential "Problems!" in this process !" But in some ways, these are worthwhile.