Functions written in C or C++ are called
native code.
For example,
we will create a native function named
stringFromJNI
that will return the string
"Hello from JNI !"
TextView
.
JNI stands for “Java Native Interface”.
Declare a native function
as a method in a
.java
file with the Java keyword
native
.
public native String stringFromJNI();Define a native function in a
.c
or
.cpp
file in the
jni
folder of your project.
To open the above
.zip
file,
see
here.
If Eclipse complains about
Override
in
HelloJni.java
,
right-click the name of the project in the Package Explorer,
Android Tools → Fix Project Properties
I downloaded the NDK into the
/Users/myname/Downloads
/Users/myname/Downloads/android-ndk-r5b
ndk-build
and
ndk-gdb
:
cd /Users/myname/Downloads/android-ndk-r5b pwd ls -l lowercase LS minus L ndk-build --help ndk-gdb --help
The folder
/Users/myname/Downloads/android-ndk-r5b
OVERVIEW.html
and
INSTALL.html
,
which says that we need GNU make 3.81 or later
(not to mention
awk
).
Open a Mac Terminal window and say
which make /usr/bin/make make -v GNU Make 3.81 This program built for i386-apple-darwin10.0
Windows people:
the comments in
ndk-build
suggest you can use the
make
that comes with
Cygwin.
When I installed the NDK, the sample application was installed into
the folder
/Users/myname/Downloads/android-ndk-r5b/samples/hello-jni
cd /Users/myname/Downloads/android-ndk-r5b/samples/hello-jni pwd
I see familiar subfolders such as
src
and
res
,
and unfamiliar ones such as
jni
.
ls -l -rw-r-----@ 1 myname staff 695 Nov 12 18:53 AndroidManifest.xml -rw-r-----@ 1 myname staff 364 Nov 12 18:53 default.properties drwxr-x---@ 4 myname staff 136 Nov 12 18:53 jni drwxr-x---@ 3 myname staff 102 Nov 12 18:53 res drwxr-x---@ 3 myname staff 102 Nov 12 18:53 src drwxr-x---@ 5 myname staff 170 Nov 12 18:53 tests
The
jni
folder contains the file
hello-jni.c
,
written in the language C.
The header files
string.h
and
jni.h
are in the folder
/Users/myname/Downloads/android-ndk-r5b/platforms/android-9/arch-arm/usr/include
.
The name of the C function
Java_com_example_hellojni_HelloJni_stringFromJNI
consists of three parts, separated by underscores.
I’m afraid it’s right up there with the
Maher-Shalal-Hash-Baz.
in Isaiah 8:1.
com_example_hellojni
HelloJni
stringFromJNI
thiz
is a pointer (of type
jobject
)
to the
HelloJni
object in
HelloJni.java
.
It has a z because the word
this
is a keyword in C++.
If the
HelloJni
had any fields, we could have used
thiz
to access the fields.
jni.h
tells us that a
jobject
is a pointer to a very minimal object,
which means it can point to any object:
really means:
//Class _jobject has no members at all. class _jobject {}; //A jobject is a pointer to a _jobject object. typedef _jobject* jobject;
The return type of
Java_com_example_hellojni_HelloJni_stringFromJNI
is
jstring
,
which is a bit more complicated:
//Class _jobject has no members at all. class _jobject {}; //Class _jstring is derived from class _jobject. class _jstring: public _jobject {}; //A jstring is a pointer to a _jstring object. typedef _jstring *jstring;
The word
JNIEnv
is a pointer to a structure in C,
a structure in C++.
The folder
/Users/myname/Downloads/android-ndk-r5b/samples/hello-jni/jni
also contains the
“make”
file
Android.mk
,
which is read by the program
ndk-build
.
my-dir
is the current directory,
i.e., the directory that holds
Android.mk
.
CLEAR_VARS
and
BUILD_SHARED_LIBRARY
are the names of make macros that hold the names of the makefiles
clear-vars.mk
and
build-shared-library.mk
in the directory
/Users/nyuuser/Downloads/android-ndk-r5b/build/core
.
Let’s run
ndk-build
.
cd /Users/myname/Downloads/android-ndk-r5b/samples/hello-jni ndk-build Gdbserver : [arm-linux-androideabi-4.4.3] libs/armeabi/gdbserver Gdbsetup : libs/armeabi/gdb.setup Compile thumb : hello-jni <= hello-jni.c SharedLibrary : libhello-jni.so Install : libhello-jni.so => libs/armeabi/libhello-jni.so
To remove the files you just created,
ndk-build clean
To create the same files again, this time with terrifying verbosity,
ndk-build -B V=1
What folders and files did we just create?
With Unix
`
back quotes`
,
we can
list all the folders and files starting at the current
folder and working downwards,
listing them from newest to oldest:
ls -ldt `find . -print` | more drwxr-xr-x 5 myname staff 170 May 11 11:35 ./libs/armeabi -rwxr-xr-x 1 myname staff 1588 May 11 11:35 ./libs/armeabi/libhello-jni.so drwxr-xr-x 4 myname staff 136 May 11 11:35 ./obj/local/armeabi -rwxr-xr-x 1 myname staff 21226 May 11 11:35 ./obj/local/armeabi/libhello-jni.so drwxr-xr-x 4 myname staff 136 May 11 11:35 ./obj/local/armeabi/objs-debug/hello-jni -rw-r--r-- 1 myname staff 23316 May 11 11:35 ./obj/local/armeabi/objs-debug/hello-jni/hello-jni.o -rw-r--r-- 1 myname staff 1138 May 11 11:35 ./obj/local/armeabi/objs-debug/hello-jni/hello-jni.o.d drwxr-x---@ 10 myname staff 340 May 11 11:35 . drwxr-xr-x 3 myname staff 102 May 11 11:35 ./libs -rw-r--r-- 1 myname staff 318 May 11 11:35 ./libs/armeabi/gdb.setup drwxr-xr-x 3 myname staff 102 May 11 11:35 ./obj drwxr-xr-x 3 myname staff 102 May 11 11:35 ./obj/local drwxr-xr-x 3 myname staff 102 May 11 11:35 ./obj/local/armeabi/objs-debug
To examine the library
/Users/myname/Downloads/android-ndk-r5b/samples/hello-jni/libs/armeabi/libhello-jni.so
that
ndk-make
just created,
cd /Users/myname/Downloads/android-ndk-r5b/samples/hello-jni/libs/armeabi ls -l libhello-jni.so
file libhello-jni.so libhello-jni.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, stripped
To see the contents of
libhello-jni.so
,
I had to copy it to
oit2.scps.nyu.edu
and run the following command on oit2.scps.nyu.edu.
I couldn’t get the Macintosh
nm
to display the contents of the file.
nm -D libhello-jni.so | awk 'NR == 3 || NR == 5 || /stringFromJNI/' libhello-jni.so: [Index] Value Size Type Bind Other Shndx Name [49] | 2961| 52|FUNC |GLOB |0 |7 |Java_com_example_hellojni_HelloJni_stringFromJNI
File →
New →
Project… →
Android →
Android Project
Next
• Create project from existing source
Location: /Users/myname/Downloads/android-ndk-r5b/samples/hello-jni
Build Target: Android 2.3.3
Finish
▼ HelloJni ▼ src ▼ com.example.hellojni ► HelloJni.java
The
Activity
in
HelloJni.java
has a static initialization block
that loads the C library
hello-jni
from the shared object file
libhello-jni.so
.
Then the
onCreate
calls the C function
stringFromJNI
.
I had to do a
Project → Clean…
to get it to compile.
adb shell # cd /data/data/com.example.hellojni/lib # pwd # ls -l libhello-jni.so # exit