Android – Invoke JNI based methods (Bridging C/C++ and Java)
Here’s a screen shot

Step By Step Instructions below:
Step #1: Compile the project using ant. Some snippets are shown below.
NativeAdd.java class (with Native method)
package org.apache;
import android.util.Log;
public class NativeAdd {
static {
try {
Log.i("JNI", "Trying to load libNativeAdd.so");
System.loadLibrary("NativeAdd");
}
catch (UnsatisfiedLinkError ule) {
Log.e("JNI", "WARNING: Could not load libNativeAdd.so");
}
}
public static native long add(long a, long b);
}
Snippet that shows how this class/method is invoked from the main activity
public void onClick(View view) {
Log.i(LOG_TAG, "onClick");
EditText a = (EditText) findViewById(R.id.a);
EditText b = (EditText) findViewById(R.id.b);
EditText c = (EditText) findViewById(R.id.c);
Log.i(LOG_TAG, "calling native method");
long sum = NativeAdd.add(Long.parseLong(a.getText().toString()),
Long.parseLong(b.getText().toString()));
Log.i(LOG_TAG, "back from native method");
String text = Long.toString(sum);
c.setText("Native add returns = " + text.subSequence(0, text.length()));
}
Step #2: Generate header files using java by running the following command.
javah -classpath ../../android.jar;../bin/classes; org.apache.NativeAdd
Here’s how the header file (org_apache_CallNative.h) looks like
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class org_apache_NativeAdd */
#ifndef _Included_org_apache_NativeAdd
#define _Included_org_apache_NativeAdd
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_apache_NativeAdd
* Method: add
* Signature: (JJ)J
*/
JNIEXPORT jlong JNICALL Java_org_apache_NativeAdd_add
(JNIEnv *, jclass, jlong, jlong);
#ifdef __cplusplus
}
#endif
#endif
Step #3: Code a tiny C file (org_apache_NativeAdd.c) as shown below:
#include "org_apache_NativeAdd.h"
JNIEXPORT jlong JNICALL Java_org_apache_NativeAdd_add
(JNIEnv *env, jclass c, jlong a, jlong b)
{
return a + b;
}
Step #4: Please read the following article before you try the next step.
Shared library “Hello World!” for Android
Step #5: Compile and link the org_apache_NativeAdd.c/org_apache_NativeAdd.h into a shared library.
arm-none-linux-gnueabi-gcc -I/usr/lib/jvm/java-1.5.0-sun/include -I/usr/lib/jvm/java-1.5.0-sun/include/linux -fpic -c org_apache_NativeAdd.c arm-none-linux-gnueabi-ld -T armelf_linux_eabi.xsc -shared -o libNativeAdd.so org_apache_NativeAdd.oNOTE: details on armelf_linux_eabi.xsc are in the Step #4. Step #6: copy the library to the emulator. Copy the Application as well.adb push native/libNativeAdd.so /system/lib adb install bin/CallNative.apkStep #7: Run the app to try some values. That's it!
Download the sources and Application - CallNative.zip
[...] http://euedge.com/blog/2007/12/06/google-android-runs-on-sharp-zaurus-sl-c760http://davanum.wordpress.com/2007/12/09/android-invoke-jni-based-methods-bridging-cc-and-java [...]
Android Internals « $HOME
December 30, 2007 at 11:49 pm
[...] capture video or use location based services, you may however try to use JNI. Davanum Srinivas presents how to achieve this step by step. This way one can make part of his app partially native to gain performance, for instance in case [...]
Do Android dream of something more than Java? « Mantrid’s Weblog
April 28, 2008 at 3:53 am
thanks for the infomation
the CallNative.zip download is not work, can you fix that?
thanks
Yael
Yael
December 7, 2008 at 6:16 am
[...] example [...]
Yu-Teh Wiki: Jni
January 31, 2009 at 8:36 pm
[...] Android by Davanum [...]
Hello World на Си для андроида | Androider
March 14, 2009 at 6:31 am
[...] some C (or C++) code (perhaps for speed-sensitive code paths)? A. One can do that, using JNI. A blog post on this topic. « Porting Android kernel to the TS-72xx [...]
A few “Android FAQs for Beginners” Answered « KaiwanTech’s Blog
March 23, 2009 at 3:02 am
can you Explain this?
“javah -classpath ../../android.jar;../bin/classes; org.apache.NativeAdd”
what do you mean by “bin/classes”? and where should I store android.jar?
paresh
April 2, 2009 at 7:16 am
Thanks for this very good introdurction to using JNI on Android.
I am using Windows XP with JDK1.6.0 and I got some problems which I could solve. So here is a short description of how I got it running:
Rewriting …/include/linux to …/include/win32 did not work:
[code]
arm-none-linux-gnueabi-gcc -I%JAVA_HOME%/include -I%JAVA_HOME%/include/win32 -fpic -c org_apache_NativeAdd.c
[/code]
The problem seems to be the declaration for __int64 (as long long) and the __stdcall and __declspec(x) compiler directive in “include/win32/jni_md.h”.
I solved this by definig them on the command line:
[code]
arm-none-linux-gnueabi-gcc -D__int64="long long" -D"__declspec(x)"=" " -D"__stdcall"=" " -I %JAVA_HOME%/include -I %JAVA_HOME%/include/win32 -fpic -c org_apache_NativeAdd.c
[/code]
Now it works!
For linking the file “armelf_linux_eabi.xsc” is needed.
It can be found under the Sourcery G++ Lite program dir: …\arm-none-linux-gnueabi\lib\ldscripts\armelf_linux_eabi.xsc
Using the default installation of Sourcery G++ Lite the link command is as follows:
[code]
arm-none-linux-gnueabi-ld -T "C:\Programme\CodeSourcery\Sourcery G++ Lite\arm-none-linux-gnueabi\lib\ldscripts\armelf_linux_eabi.xsc" -shared -o libNativeAdd.so de_hechler_jni_NativeAdd.o
[/code]
Next suprise: No acces right to copy into “/system/lib” using adb push
Copied it to “/data”
[code]
adb push libNativeAdd.so /data
[/code]
and changed the loadLibrary in NativeAdd.java
[code]
// OLD: System.loadLibrary("NativeAdd");
System.load("/data/libNativeAdd.so");
[/code]
And… SUCCESS!!!
Hope this might help others to get things working under windows,
Best regards,
Feri
Ferenc Hechler
April 2, 2009 at 9:37 am
The above step by Ferenc Hechler also worked fine for me too. Thanks for that. Just to add to that you can get arm-none-linux-gnueabi-gcc from https://support.codesourcery.com/GNUToolchain for free having evaluation period of 30 days.
Want to know, if the same .so library, that worked on windows will work on device?
shruthirap
May 18, 2009 at 7:32 am
Thanks for the infomation!!!
the CallNative.zip download is not work, can you fix that?
thanks!!!
david
May 20, 2009 at 4:03 am
With emulator,I have push libNativeAdd.so in to System/lib is OK, but with G1, i can’t push System/lib,
Please help How to push libNativeAdd.so into System/lib or using System.loadLibrary(”NativeAdd”);
can't push libNativeAdd.so in System/lib
June 3, 2009 at 8:40 pm
I have big problem . When I try to “push” my library on /system/lib, The emulator is OK, but The production T-mobile G1 tell me that partition is read only.
Then, i’ve tried to push the library on another location and use the method system.load instead of system.loadlibrary. In this way I can load the library.
Please tell me, How to do push my library in to System/lib in T-mobile G1 or using System.loadLibrary(”NativeAdd”) with T-mobile G1.
thanks,
p-d-Quang
pdquang
June 3, 2009 at 9:30 pm
It works in my G1 puting my library inside apk zip file and extracting that on /data/data/MY_PACKAGE (based on this code http://www.netmite.com/android/mydroid/external/androidmono/MonoBridge/src/com/koushikdutta/mono/MonoActivity.java)
victor
June 15, 2009 at 8:08 am
also using System.load(”/data/data/MY_PACKAGE/MY_LIBRARY”) instead of System.loadLibrary
victor
June 15, 2009 at 8:11 am
[...] Davanum Srinivas [...]
Android JNI Blogs « Heejin Kim
June 17, 2009 at 12:46 pm
Screenshot doesn’t work
Mohammed Khoory
June 20, 2009 at 12:42 am