Skip to content

Instantly share code, notes, and snippets.

@venkateshshukla
Last active August 29, 2015 13:57
Show Gist options
  • Save venkateshshukla/9737838 to your computer and use it in GitHub Desktop.
Save venkateshshukla/9737838 to your computer and use it in GitHub Desktop.
Setting up Eclipse for Android Application Development using Native Development Kit (NDK)

Setting up Eclipse for NDK

To make eclipse compatible for android application development. (Please note. These steps are implemented on Linux. For other OS, steps may differ)

####Preparation

Visit https://gist.github.com/venkateshshukla/9736261 for detailed instruction on preparation. Besides those steps, do this for NDK integration.

  • In eclipse, go to Help > Install New Software.
  • Chose Juno - http://download.eclipse.org/releases/juno or equivalent for your eclipse version.
  • In the resulting tree that is shown, expand Programming Languages option and navigate to CDT Plugins.
  • Select C/C++ Development Tools, C/C++ Library API Documentation, Autotools support for CDT, and other C/C++ plugins that may be required.
  • Follow the procedure and install these packages.
  • Reboot eclipse.

####Sample Project

  • Make a sample project on eclipse.

    • Go to File > New > New Project > Android Application Project.
    • Give suitable name and icon. Chose default view and navigation.
    • A default hello world application is made.
    • This setup is for Java applications.
  • Make a new folder in the root project directory named "jni"

    • This folder contains all the native code for your project.
    • Make a new file in it - Android.mk
    • This file is the make file which gives info to ndk-build command about the project, modules, locations and C source files to compile, etc.
    • An example of Android.mk file is attached
  • In the MainActivity, add some native functions. They are declared like abstract functions without any body and are implemented on the native side. For ex

	public native String getNativeString();
	public native int getNativeInt();
  • Also add a static reference to the C library to be loaded. These libraries are build by ndk-build command using Android.mk file. Do this by adding lines such as these to your MainActivity.java.
	static {
	    System.loadLibrary("samplelibrary");
	}
  • A sample MainActiviy.java file is attached

####Convert to C/C++ hybrid project

  • Go to File>New>Other.
  • Chose Convert to a C/C++ Project.
  • Chose C Project in Convert options.
  • Chose MakeFile Project - Other Toolchains in Project Type and finish.
  • The perspective changes to C/C++ perspective.

####Add ndk-build command to your project

  • Go to Project>Properties>C/C++ Build

    • Under the Builder Settings tab
    • Uncheck "Use default build command" and set the build command to
  • ndk-build

    • Chose the build location to point to your project directory. For ex.

    ${workspace_loc:/SampleProject}/

  • Under Behaviour tab

    • Check the "Build on resource save" and leave the entry to "all"
    • Under Refresh policy tab
    • Add the folders you want to refresh after ndk-build command.
    • For example set SampleProject folder to refresh

####Add a javah command for building C headers javah command is very useful for generating C header files for JNI applications. As Android NDK is built on JNI, this command is highly useful here.

For understanding this command, open a terminal, navigate to your project file and enter this command

javah -jni -d jni -classpath src com.sampleproject.MainActivity

For the provided MainActivity.java, A com_sampleproject_MainActivity.h is created in the jni folder. It contains prototype declaration of the native functions declared in MainActivity.java. A sample is attached.

Now, the javah command

Option Usage
-jni tells that Java Native Interface is to be used
-d sets the output directory to jni folder. All outputs are redirected to this folder
-classpath tells where tha java package is stored for generating the header files - in this case src folder
argument com.sampleproject.MainActivity is the Java code for which native header files are to be generated

Rather than manually entering this command each time, a builder can be made in eclipse. For doing this,

  • Go to Project > Properties > Builders
  • Make a new Builder of Program type.
  • In the location, navigate to the bin folder of jdk installation directory

    For ex: /usr/java/jdk1.7.0_51/bin/javah

  • Leave the "working directory" empty.
  • In the "arguments" add something like this:

-classpath ${workspace_loc:/sampleproject/src} -d ${workspace_loc:/sampleproject/jni} com.sampleproject.MainActivity

  • Go to refresh tab and select "Refresh the selected project"
  • Click OK to save. Reorder the builder to be placed below the Java Builder.
  • The order of builders in my config is Java Builder > Javah > CDT Builder > Android Package Builder

Now, every time your project is built, javah command will be run. And the native header files will be generated

####Including necessary folders for build and compilation

Lastly, some folders are to be included for proper header includes and usage of JNI commands in the C files in eclipse. For this,

  • Go to Project > Properties > C/C++ General > Paths and Symbols

  • In the includes tab, add two folders for assembly

    1. /android_ndk/platforms/android-19/arch-arm/usr/include
    2. /android_ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.8/include
  • Change the folders according to the chipset of your android device, your OS and target android version.

  • Save and exit.

After these steps, you are done. You can dive into Android NDK coding immediately.

Goodluck.

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := samplelib
LOCAL_SRC_FILES := com_sampleproject_MainActivity.c
include $(BUILD_SHARED_LIBRARY)
package com.sampleproject;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
static {
System.loadLibrary("samplelibrary");
}
public native String getNativeString();
public native int getNativeInt();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle(getNativeString() + String.valueOf(getNativeInt()));
}
}
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_learnjni_MainActivity */
#ifndef _Included_com_learnjni_MainActivity
#define _Included_com_learnjni_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_learnjni_MainActivity
* Method: getNativeString
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_learnjni_MainActivity_getNativeString
(JNIEnv *, jobject);
/*
* Class: com_learnjni_MainActivity
* Method: getNativeInt
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_learnjni_MainActivity_getNativeInt
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment