I did not find any easy to read tutorials on how to exactly build an Android app with some native code component. Its true that the NDK package comes with some docs, but for Android beginners, this may not be an exciting prospect. However, I still maintain that the docs in the package are a must-read.
The following app simply prints out a small string returned from a C function on the LogView.
1. Create a Normal Android app. Lets call it 'native1'.
2. The main source file should look like this.
3. If you are using Eclipse, the class files built will be in the 'bin' directory.
4. Navigate to it and run 'javah' on the class file that contains the native method.
javah -jni com.earl.native1.NativeLib
5. After this, you will get one header file. This file contains the JNIEXPORTs generated from the java source.
6. Copy this file and paste it in a folder in the 'sources' dir of the Android NDK. I'm calling the folder 'earl'.
7. Now, create the C implementation file - earl.c It should look like this.
8. Now you have to create the Android.mk file. This file describes your native code module to the build system. This file is created in the same dir as the source file.
9. Now, navigate to the 'apps' dir in the NDK home and create a folder of your choice. This will hold the Android Application you built using Eclipse earlier. I am calling it earl_jni. In this folder, create another one and call it 'projects'. In this, copy your ENTIRE eclipse project 'native1'. Then, navigate one level up to earl_jni and create the Application.mk file.
10. Now, navigate to the NDK home and run the make command.
$ make APP=earl_jni
11. You should see this output if everything works correctly.
12. Now, a folder called 'libs' will be created in apps/earl_jni/projects. This contains the .so file i.e the native library. Copy this into the eclipse project root. Compile and run. You should see something like on the LogView
Congratulations!!! You have just built your first JNI app for Android.
The following app simply prints out a small string returned from a C function on the LogView.
1. Create a Normal Android app. Lets call it 'native1'.
2. The main source file should look like this.
package com.earl.native1;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class native1 extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.i("--EARL--", new NativeLib().getHelloWorld());
}
}
class NativeLib
{
public native String getHelloWorld();
static {
System.loadLibrary("helloworld");
}
}
3. If you are using Eclipse, the class files built will be in the 'bin' directory.
4. Navigate to it and run 'javah' on the class file that contains the native method.
5. After this, you will get one header file. This file contains the JNIEXPORTs generated from the java source.
6. Copy this file and paste it in a folder in the 'sources' dir of the Android NDK. I'm calling the folder 'earl'.
7. Now, create the C implementation file - earl.c It should look like this.
#include "com_earl_native1_NativeLib.h"
JNIEXPORT jstring JNICALL Java_com_earl_native1_NativeLib_getHelloWorld
(JNIEnv * env, jobject obj)
{
return (*env)->NewStringUTF(env, "Greetings from Earlence !");
}
8. Now you have to create the Android.mk file. This file describes your native code module to the build system. This file is created in the same dir as the source file.
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := helloworld
LOCAL_SRC_FILES := earl.c
include $(BUILD_SHARED_LIBRARY)
9. Now, navigate to the 'apps' dir in the NDK home and create a folder of your choice. This will hold the Android Application you built using Eclipse earlier. I am calling it earl_jni. In this folder, create another one and call it 'projects'. In this, copy your ENTIRE eclipse project 'native1'. Then, navigate one level up to earl_jni and create the Application.mk file.
APP_PROJECT_PATH := $(call my-dir)/project
APP_MODULES := helloworld
10. Now, navigate to the NDK home and run the make command.
$ make APP=earl_jni
11. You should see this output if everything works correctly.
Android NDK: Building for application 'earl_jni'
Compile thumb : helloworld <= sources/earl/earl.c
SharedLibrary :
libhelloworld.so
Install : libhelloworld.so => apps/earl_jni/project/libs/armeabi
12. Now, a folder called 'libs' will be created in apps/earl_jni/projects. This contains the .so file i.e the native library. Copy this into the eclipse project root. Compile and run. You should see something like on the LogView
I/ActivityManager( 564): Starting activity: Intent { action=android.intent.acti
on.MAIN categories={android.intent.category.LAUNCHER} flags=0x10200000 comp={com
.earl.native1/com.earl.native1.native1} }
I/--EARL--( 699): Greetings from Earlence !
I/ActivityManager( 564): Displayed activity com.earl.native1/.native1: 704 ms
Congratulations!!! You have just built your first JNI app for Android.
Can you then just copy the .so file into the original eclipse project folder and load up the debugger? Or do I need to reload eclipse pointing to the new project folder?
ReplyDeleteyes, copy the 'lib' folder that gets created in the NDK directory. Then, refresh your eclipse project.
ReplyDeleteHi
ReplyDeleteI tried the example given above exactly as you've described. I got the following error.
$make APP=earl_jni
Android NDK: Building for appplication 'earl_jni'
sources/earl/Android.mk: build/cor/clear-vars.mkLOCAL_MODULE: No such file or directory
sources/earl/Android.mk:13: :=: No such file or directory
sources/earl/Android.mk:13: helloworld: No such file or directory
build/core/buile-shared-library.mk:24: *** Android NDK: Missing LOCAL_MODULE before including BUILD_SHARED_LIBRARY in sources/earl/Android.mk .
Stop.
where is this 'helloworld' library we are trying to load..?
ouch...
ReplyDeleteEverything seemed to go to plan (other than some confusion around the project vs projects directory name) until the last step. After copying the .so file to the eclipse project root folder, refreshing and running, the app crashes with the DDMS LogCat output saying..
ERROR/AndroidRuntime(1113): Caused by: java.lang.UnsatisfiedLinkError: Library helloworld not found
any ideas?
I copied the whole libs directory over instead of the libhelloworld.so file and it works now.
ReplyDeleteThanks
Im getting this error:
ReplyDeleteException Ljava/lang/UnsatisfiedLinkError; thrown during Lcs/washington/tester/NativeLib
any ideas?
Great tutorial! Got my first "hello world" C app up and running. :)
ReplyDeleteHowever, you don't actually need to move your Eclipse library or header file anywhere. You can use soft links to "fake" that. This should make app development simpler.
1. Make a folder in your Eclipse project (eg NativeTest) and put everything that needs to go in the NDK sources/ directory there: Android.mk, *.h, *.c. Then, ln -s /.../youreclipseproject/NativeTest/ /.../android-ndk/sources/NativeTest/
2. Instead of copying your Eclipse project into the apps/ directory, just make a symbolic link inside apps/ that points to your Eclipse project. That way the "libs" directory will get created inside your Eclipse project, so you can run & debug your project just as usual from inside Eclipse without needing to duplicate or move files. I made a file Application.mk inside the top level directory of my Eclipse folder.
I love u
ReplyDelete4. Navigate to it and run 'javah' on the class file that contains the native method.
ReplyDeleteWhen I do this I get
"'javah' is not recognized as an internal or external command
How do i navigate to the project bin folder and be able to ust javah thats in my JDK bin folder?
Hi,
ReplyDeleteI have crated library i.e .so file everything is fine until then. when i try to run my application, ddms thowing error msg "No JNI_OnLoad found in /data/data/com.wishu.jnijava/lib/libtest_jni_lib.so 0x4329c140"
Please let me know what could be the problem...
Thank You
Vishal
Where do i need to go and write the make command...as in inside windows command prompt or inside cygwin.
ReplyDeleteinside command prompt it is giving me the error that make command is not found, and inside cygwin it says APP=earl_ini is not a command.
please guide me
thank you
thanks for the tutorial! Very helpful.
ReplyDeleteI'm kind of curious why you're copying the entire eclipse project into the ndk directory though. If you create a jni folder in your eclipse project directory and put your NativeLib.h and hello.c files into it, you should be able to just call ndk-build in your project root and not have to do as much moving around and copying of files and folders. The only snags I hit when trying that were making sure my project path didn't have any spaces in it and updating my eclipse project (f5 in the Package Explorer) to make it see the new lib and jni directories.
Vish: Are you sure that's an error message? I receive the same thing on LogCat when I run, but it's listed as a debug message. I just assumed it meant that there's an expected onLoad function that we're not defining (because we don't expressly need one).
draffodx: I got the same thing at first too. Along with the basic Java stuff you need to install for eclipse, you also need to install the Java JDK. Assuming default options, javah can then be found in C:\Program Files\java\jdk1.whateverVersion\bin\javah.exe The default JDK install should also automatically add this to your path.
Very Very Excellent job done, it helped me allot, thanks.
ReplyDeletefree android app
Latest reviews and news about android phones, free droid app and android mobile
ReplyDeletefree android appe
lsndel06@lsndel06-PC /cygdrive/c/android-ndk-r5b
ReplyDelete$ make APP=ndk_demo
Android NDK: There is no Android.mk under apps/ndk_demo/project/jni
Android NDK: If this is intentional please define APP_BUILD_SCRIPT to point
Android NDK: to a valid NDK build script.
build/core/add-application.mk:126: *** Android NDK: Aborting... . Stop.
I GOT THIS ERROR EVERY TIME WHEN I RUN THE MAKE COMMAND.
the system has changed with the new NDK. most of these steps may or may not be applicable. things have become easier. d.android.com should provide enough information.
ReplyDeleteHi,
ReplyDeleteI want to write JNI for existing c code, I have c code and header, i
created the .so file using cygwin, I wrote the Android.mk file and
using cygwin created the shared library first it was showing
"undefined reference to function name" error, then I removed "include $
(CLEAR_VARS)" and again run the ndk-build command then shared library
was created but while running it was showing UnsatisfiedLinker
Error.my make file is
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILES := libtest.so
include $(PREBUILT_SHARED_LIBRARY)
#LOCAL_PATH := $(call my-dir)
#include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_MODULE := jni_anand
LOCAL_CPP_EXTENSION := .cpp
LOCAL_SRC_FILES := anand.cpp
LOCAL_SHARED_LIBRARY := test
include $(BUILD_SHARED_LIBRARY)
Thanks...
Actual acceptable and informative article absolutely . It helps me a lot to enhance my knowledge, I absolutely like the way the presented presented his views , a lot of thanks for all your admired assignment on this article.
ReplyDeleteAndroid developers
A Plain Text Editor
ReplyDeletePlain Text files
That's right, if you're writer on a budget, you don't need to spend any money buying expensive writing software or apps. Instead, you can use the text editor that comes free with your operating system.
Just open up Notepad on Windows or TextEdit on a Mac. I like plain text editors for writing something short quickly and easily, without thinking much about it. I wrote a blog post about the benefits of using plain text editors as writing software.
Use for: writing whatever, wherever