Skip to content
Search

Android:NDK:Sample

lastmod 2023-05-09created 2016-06-223 edits

Android NDK Samples.

Compiling with cygwin bash on Windows

To compile, the following environment variables must be set first.

  • CYGWIN_HOME: the directory where cygwin is installed.
  • NDK_HOME: the directory where the NDK is installed. (It must be added to the PATH variable.)
%CYGWIN_HOME%\bin\bash.exe --login -c "ndk-build -C '${build_project}'"

Basic structure of Android.mk

The basic form of Android.mk, read by the Makefile, is as follows.

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# 여기 이후에 추가 설정 정보를 입력해야 한다.

# LOCAL_DEFAULT_CPP_EXTENSION := cpp
LOCAL_MODULE := [LIBRARY_NAME]
LOCAL_SRC_FILES := [SRC_FILES]

# 여기 이전에 추가 설정 정보 입력을 완료해야 한다.
include $(BUILD_SHARED_LIBRARY)
  • $(LOCAL_MODULE): name of the output library file.
    (The file name gets the prefix lib and the suffix .so.)
  • $(LOCAL_SRC_FILES): list of source files to compile.

Android.mk Macro List

The predefined macros in Android.mk, read by the Makefile, are as follows.

  • $(NDK_PROJECT_PATH): ndk project path.
  • $(NDK_APP_APPLICATION_MK): specifies the *.mk file that ndk-build will read.

Adding C/C++ usage to Android.mk

Add the CPP file extension as shown below. Note that it must be inserted after include $(CLEAR_VARS). (When compiling directly in Cygwin, c is compiled with gcc and cpp with g++.)

LOCAL_DEFAULT_CPP_EXTENSION := cpp

Linking a JNI Library to a Java class

In the class you want to link the JNI library to, load the library using System.loadLibrary() as shown below. (Note that the library name must be the same as $(LOCAL_MODULE) in Android.mk, with the prefix lib and the suffix .so removed.)

package com.example;

public class TestNdkActivity extends Activity {
  static {
    System.loadLibrary("libraryname");
  }
}

Linking a Method

When using a C function of JNI from Java, add the native keyword as shown below.

private native String getJniTestString();

Note that the function name must be written exactly on the Native code side, i.e., the C side, under the following conditions.

  • When using C++, make it C using extern "C".
  • When using C++, add JNIEXPORT before the return type.
  • When using C++, add JNICALL between the return type and the function name.
  • Write the function name in the following order.
    1. Write Java_ as the prefix.
    2. Write the package name in order, converting each period (.) to an underscore (). (Do not use an underscore () or a hyphen (-) in the package name.)
    3. Write the class name to use. (Prefix it with an underscore (_) to separate it from the package name.)
    4. Write the Method name to use. (Prefix it with an underscore (_) to separate it from the package name.)
  • The first parameter is fixed as JNIEnv* env.
  • The second parameter is fixed as jobject thiz.
  • From the third parameter on, use the order of the parameters passed from Java.

Example

To help understanding, here is an example of a function that meets the following conditions.

Language(C++), Package(com.example), class(TestNdkActivity) Method(private native String getJniTestString):

#include <jni.h>

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jstring JNICALL
Java_com_example_TestNdkActivity_getJniTestString(JNIEnv* env, jobject thiz) {
  return env->NewStringUTF("Hello, NDK!");
}

#ifdef __cplusplus
}
#endif

Differences between C and C++ implementations

When using the NDK, C and C++ are used differently.

C implementation:

#include <string.h>
#include <jni.h>

jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz ) {
  return (*env)->NewStringUTF(env, "Hello from JNI !");
}

C++ implementation:

#include <string.h>
#include <jni.h>

JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz ) {
  return env->NewStringUTF("Hello, NDK!"); 
}

About the Android NDK Samples

Description of the sample projects included when installing the NDK:

  • hello-jni: example that loads a string from a shared library implementing a native method and displays it in the application UI.
  • two-libs: example that dynamically loads a shared library and calls the native method it provides. The native method is implemented in a static library and imported into the shared library.
  • san-angeles: example that renders 3D graphics using the native OpenGL ES API. During rendering, the activity lifecycle is managed by a GLSurfaceView Object.
  • hello-gl2: example that renders a triangle using OpenGL ES 2.0 vertex & fragment shaders.
  • hello-neon: example that checks CPU capabilities at runtime with the cpufeature library (when the CPU supports NEON intrinsics). This example is implemented in two versions: a C version (tiny benchmark for a FIR filter loop) and a NEON-optimized version.
  • bitmap-plasma: example showing how to access the pixel buffer of an Android Bitmap Object from native code.
  • native-activity: example showing how to create a native activity with the native-app-glue static library.
  • native-plasma: the bitmap-plasma example implemented as a native activity.

See also