Skip to content

Instantly share code, notes, and snippets.

@gnuanu
Last active January 24, 2024 08:20
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gnuanu/252fd406f48f7da2c1c7 to your computer and use it in GitHub Desktop.
Save gnuanu/252fd406f48f7da2c1c7 to your computer and use it in GitHub Desktop.
Creating a simple Hello World application Using Android NDK with C++

Prerequisites

  1. I am using GNU/Linux
  2. My IDE is IntelliJ IDEA
  3. The project is Ant based.
  4. My working directory is $JNI
  5. My C++ IDE is QtCreator (I'll mention the build steps inline).
  6. NDK should be installed and ndk-build should be available in $PATH
  7. javah should be available in $PATH

Step 1 - Create The Android Project

  1. Create and Empty Project Named JNI (at location $JNI)
  2. Create a new Android application module named JNIHelloWorld.
  3. Package Name - com.jnisample.JNIHelloWorld
  4. Create one activity JNIActivity and define one native function getNativeMessage()
  5. Build the project
package com.jnisample.JNIHelloWorld;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import org.w3c.dom.Text;
public class JNIActivity extends Activity {
public native String getNativeMessage();
static {
System.loadLibrary("mynative");
}
Button btnInvokeJNI;
TextView tvNativeMsg;
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnInvokeJNI = (Button) findViewById(R.id.btnInvokeJni);
tvNativeMsg = (TextView) findViewById(R.id.txtJniText);
btnInvokeJNI.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tvNativeMsg.setText(getNativeMessage());
}
});
}
}

Step 2 - Create the JNI Header file

  1. Create a folder jni inside $JNI/JNIHelloWorld
  2. In Terminal(command line) move to $JNI/out/production/JNIHelloWorld directory (This is where the java files get compiled to class files by IDEA; Verify the directory structure is same as the package name com/jnisample/JNIHelloWorld/JNIActivity.class)
  3. Create the header for the native function using javah
$ javah $JNI/JNIHelloWorld/jni com.jnisample.JNIHelloWorld.JNIActivity

The Above command will generate a header file with name com_jnisample_JNIHelloWorld_JNIActivity.h inside the jni directory.

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_jnisample_JNIHelloWorld_JNIActivity */
#ifndef _Included_com_jnisample_JNIHelloWorld_JNIActivity
#define _Included_com_jnisample_JNIHelloWorld_JNIActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_jnisample_JNIHelloWorld_JNIActivity
* Method: getNativeMessage
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_jnisample_JNIHelloWorld_JNIActivity_getNativeMessage
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif

Step 3 - Add a C++ Class

  1. Create a C++ class with name HelloWorld
  2. Create define a member function getNativeString() which returns a string
#ifndef HELLOWORLD_H
#define HELLOWORLD_H
#include <string>
using namespace std;
class HelloWorld
{
public:
HelloWorld();
string getNativeString();
};
#endif // HELLOWORLD_H
#include "helloworld.h"
HelloWorld::HelloWorld()
{
}
string HelloWorld::getNativeString()
{
return "Hello World from JNI";
}

Step 4 - Implement JNI Entry (or Entries)

Implement the entry method com_jnisample_JNIHelloWorld_JNIActivity_getNativeMessage defined in header com_jnisample_JNIHelloWorld_JNIActivity.h

#include "com_jnisample_JNIHelloWorld_JNIActivity.h"
#include "helloworld.h"
JNIEXPORT jstring JNICALL Java_com_jnisample_JNIHelloWorld_JNIActivity_getNativeMessage
(JNIEnv* pEnv, jobject pThis)
{
HelloWorld hello;
return pEnv->NewStringUTF(hello.getNativeString().c_str());
}

Step 5 - Configure make

Define Android.mk and Application.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mynative
LOCAL_SRC_FILES := helloworld.cpp jni_entry.cpp
include $(BUILD_SHARED_LIBRARY)
# This variable enables the inclusion of STL classes
APP_STL := stlport_static

Step 6 - Build Shared Object

  1. In Terminal, move to directory $JNI/JNIHelloWorld
  2. Build the Shared Object using the command ndk-build
$ ndk-build

On successful build, the Shared Object file libmynative.so will be copied to $JNI/JNIHelloWorld/libs/armeabi

Step 7 - Build APK

  1. Build the android project in IntelliJ IDEA
  2. Deploy and Run
@rifatcakir
Copy link

nice work

@ademcan
Copy link

ademcan commented Mar 22, 2018

Thank you for sharing, it was really helpful 👍
Just one thing: it seems that you are missing the
#include <jni.h>
declaration on the jni_entry.cpp file.

@tfmeneses
Copy link

tfmeneses commented Jan 30, 2019

Hi,
I've a problem with string included.

helloworld.h:3:10: fatal error: 'string' file not found

My Application.mk
APP_STL := stlport_static

@tfmeneses
Copy link

Hi,
I've a problem with string included.

helloworld.h:3:10: fatal error: 'string' file not found

My Application.mk
APP_STL := stlport_static

Solved. I make a directory "jni" in application folder and put the *.mk. Also, I downloaded the new stable Android NDK.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment