The NDK is a toolset
that allows you to implement parts of your app using native-code languages such
as C and C++ (http://developer.android.com/tools/sdk/ndk/index.html)
You will also need Eclipse
CDT Plugin installed to build C/C++ native part from Eclipse. To install it use
menu Help -> Install New Software..., then setup CDT Main Features from http://download.eclipse.org/tools/cdt/releases/juno
URL.
The Java Native Interface
Programmer's Guide and
Specification
(http://java.sun.com/docs/books/jni/html/start.html)
Let’s go through all these
steps.
1. Create a class that declares the native method
Let’s create simple HelloWorld
Android application and modify HelloWorldActivity.java in the following way:
public class HelloWorldActivity extends Activity
{
public native String getMyData();
static {
System.loadLibrary("mylib");
}
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello_world);
setTitle(getMyData());
}
}
In Eclipse, create a
new directory named jni at the project's root using menu File | New | Folder.
Inside the jni
directory, create a new file named Android.mk using menu File
| New | File. If CDT is properly installed, the file should have the
following specific icon in the Package
Explorer view
Write the following
content into this file. Basically, this describes how to compile our native
library named mylib which is composed of one source file the helloworld.c:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mylib
LOCAL_SRC_FILES := helloworld.c
include $(BUILD_SHARED_LIBRARY
As project files for
native compilation are ready, we can write the expected native source code.
Although the C implementation file must be written by hand, the corresponding
header file can be generated with a helper tool provided by the JDK: javah.
2. Build project
Execute “Build
Project” command to generate *.class files under HelloWorld/bin/classes
directory
3. Generate header file
-
Open
project Properties window and go to
the Builder section
-
Click
on New… and create a new builder of
type Program.
In Location
select javah.exe file using Browse File
System… button.
For Working
Directory select your project bin/classes folder using Browse Workspace… button.
In Arguments
add:
-o
${workspace_loc:/HelloWorld/jni}/helloworld.h
julia.mlinnik.helloworld.HelloWorldActivity
such arguments will result in
creating HelloWorld/jni/helloworld.h header.
You can use –d option instead of –o:
-d ${workspace_loc:/HelloWorld/jni}
julia.mlinnik.helloworld.HelloWorldActivity
that will generate TestJni/jni/julia_mlinnik_helloworld_HelloWorldActivity.h
header.
-
Validate
and position it after Java Builder in the list (because JNI files are generated
from Java .class files).
helloworld.h should have the
following content:
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>
/* Header for class julia_mlinnik_helloworld_HelloWorldActivity */
#ifndef _Included_julia_mlinnik_helloworld_HelloWorldActivity
#define _Included_julia_mlinnik_helloworld_HelloWorldActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: julia_mlinnik_helloworld_HelloWorldActivity
* Method: getMyData
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_julia_mlinnik_helloworld_HelloWorldActivity_getMyData
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
4. Write the C implementation of the native method
Create helloworld.c file under jni directory:
#include "helloworld.h"
JNIEXPORT jstring Java_julia_mlinnik_helloworld_HelloWorldActivity_getMyData
(JNIEnv* pEnv, jobject pThis)
{
return (*pEnv)->NewStringUTF(pEnv,
"My native project talks C++");
}
5. Compile C code and generate native library
Let’s convert our project to C/C++ project. Open menu File | New | Other....
Create helloworld.c file under jni directory:
#include "helloworld.h"
JNIEXPORT jstring Java_julia_mlinnik_helloworld_HelloWorldActivity_getMyData
(JNIEnv* pEnv, jobject pThis)
{
return (*pEnv)->NewStringUTF(pEnv,
"My native project talks C++");
}
5. Compile C code and generate native library
Let’s convert our project to C/C++ project. Open menu File | New | Other....
Open your project Properties. In the C/C++ Build section, uncheck Use default build command and enter ${NDKROOT}/ndk-build.cmd as a Build command. NDKROOT is environment variable containing the path to Android NDK in your system.
Validate by clicking on OK:
But now, we notice that the include statement of jni.h file is underlined in yellow. This is because it was not found by the CDT Indexer for code completion. Note that the compiler itself resolves them since there is no compilation error. Indeed, the indexer is not aware of NDK include paths, contrary to the NDK compiler.
Go to section C/C++ General/Paths and Symbols and then in Includes tab.
Click on Add... and enter the path to the directory containing this include file which is located inside NDK's platforms directory:
${NDKROOT}/platforms/android-9/arch-arm/usr/include
${NDKROOT}/sources/cxx-stl/gnu-libstdc++/include
${NDKROOT}/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/lib/gcc/arm-linux-androideabi/4.4.3/include
${ProjDirPath}/../../sdk/native/jni/include
When Eclipse proposes to rebuild its index, say Yes
Finally check that Builders have the following order:
Main idea:
javah after Java Builder
CDT Builder after javah and before Android Package Build
6. Run application
After all you see the following screen:
Hi Julia, are you able to do step/line debugging of your C/C++ Android app code from eclipse? That would be a great blog post.
ReplyDeleteHi michels, there is detailed description about debugging Android application from Eclipse under Linux OS in this book - http://www.packtpub.com/android-ndk-beginners-guide/book
DeleteFor Windows ndk-gdb script could be run under Cygwin, and I don't know how to debug from Eclipse in this case
I'm very surprised still google has not made debugging a priority, but considering the various operating systems for development, differences in eclipse versions, and various ndk versions and toolchains - it's a large set of variables. It is still surprising there is not a "de facto" document describing and showing how to do step debugging, I think a lot of people would read it. I am using Eclipse Juno and Mac OS X by the way.
Delete