AndroidNDKでHelloWorld

基本的な実装方法を忘れがちなのでメモ。
開発環境はEclipse Mars(4.5)を想定。

プロジェクト作成

とりあえず今回はプロジェクト名をHelloWorldNdkとして作成

jniディレクトリ作成

プロジェクトを作成したら、プロジェクトを右クリックして、[新規]->[フォルダ]でjniディレクトリを作成

Cソースコード実装

以下のコードを実装してjniディレクトリ以下に作成。今回はhelloworldndk.cとして作成する。
関数名は、Javaを接頭辞にして

パッケージ名_クラス名_メソッド名
として定義する。パッケージ名はcom.example.hogeならJava_com_example_hogeになる。クラス名はデフォルトだとMainActivityなので、そのまま用いることにする。

#include <jni.h>
#include <android/log.h>

void Java_com_example_hellondk_MainActivity_sayHello(JNIEnv *env, jobject thiz)
{
    __android_log_write(ANDROID_LOG_INFO, __FILE__, "Hello World!")
}

Android.mkの作成

以下のコードを実装して、jniディレクトリ以下に配置。

  • CLEAR_VARS
    • 変数のクリア
  • LOCAL_PATH
    • Android.mkが存在するパスを格納する変数。
  • LOCAL_MODULE
    • 生成される共有ライブラリ(.so)名
  • LOCAL_SRC_FILES
    • 生成元ソースファイル
  • LOCAL_LDLIBS
    • 動的リンクするライブラリを指定
  • BUILD_SHARED_LIBRARY
    • 共有ライブラリとしてビルドすることを指定
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE	:= helloworldndk
LOCAL_SRC_FILES	:= helloworldndk.c
LOCAL_LDLIBS	:= -llog

include $(BUILD_SHARED_LIBRARY)

共有ライブラリのビルド

jniディレクトリに移動して以下のコマンドをたたく。
パスが通ってない場合は、環境変数であらかじめndkライブラリのパスを通しておく。

ndk-build
ビルドするとlibs/armeabi以下に共有ライブラリが生成される。
[armeabi] Compile thumb  : helloworldndk <= helloworldndk.c
[armeabi] SharedLibrary : libhelloworldndk.so
[armeabi] Install : libhelloworldndk.so => libs/armeabi/libhelloworldndk.so

Javaコード実装

共有ライブラリの呼び出し・宣言・メソッド呼び出しのコードをJavaコードに追加する。

package com.example.helloworldndk;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends Activity {
        static {
		System.loadLibrary("helloworldndk");
	}

	public native void sayHello();
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		sayHello();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();
		if (id == R.id.action_settings) {
			return true;
		}
		return super.onOptionsItemSelected(item);
	}
}

実行

コンソールにHello World!と表示されればOK