コンピュータを楽しもう!!

今、自分が面白くていろいろやってみたことを書き綴りたいと思います。連絡先はtarosa.yでgmail.comです。

AndroidでCプログラムを使ってみる

Androidアプリ開発にCのソースを使う方法について、自分用の防備録として書いておく。

Android NDKのインストール

AndroidでCのプログラムを使う場合は、NDKが必要です。NDKのインストール方法はgoogleさんで出てくるので、ここでは省略。
基本的に、android-ndkをダウンロードして、解凍するだけ。2010.9.9現在だと、android-ndk-r4bでした。

cygwinのインストール

Android用にCプログラムをコンパイルするには、cygwin上でクロスコンパイルします。cygwinのインストール方法もgoogleさんで出てくるので省略。

コンパイルするための環境設定

  • 解凍した android-ndk-r4b を、適当なフォルダにコピーします。cygwinにログインしたときに見えた方がよさそうなので、とりあえず、cygwinの自分のホームディレクトリ下にコピー。
  • .bashrcに設定を追加

android-ndk-r4bを置いた場所を示すために、下記の設定を追加。
export ANDROID_NDK_ROOT=C:/cygwin/home/minao/android-ndk-r4b
export PATH=$PATH:/cygdrive/c/cygwin/home/minao/android-ndk-r4b

新規プロジェクトを作ってみる

  • 自分のhome下にprojectsフォルダを作成します。
  • eclipsから新規のandroidプロジェクトを作ります。

プロジェクト名をCtestとして、Use default locationのチェックを外し、cygwinのhome下に今作ったprojectsの中にCtestというフォルダを指定します。下図のように指定して完了。プロジェクトができます。

jniフォルダの作成

プロジェクトができたフォルダ(Ctest)にCソース用のjniフォルダを作ります。jniフォルダにCのソースとmakeファイル(*.mak)を作ります。今回は、hello-jniのサンプルを真似します。

ctest.cプログラムの作成

hello-jniのソースを少し改造して、CプログラムからCatLogができるように、log.hをインクルードしました。LOGI, LOGEをdefineします。関数は1つだけです。関数名が特徴的ですね。

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

#define  LOG_TAG    "Ctest"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

jstring
Java_com_example_momoonga_ctest_CtestActivity_stringFromJNI( JNIEnv* env, jobject thiz )
{
	LOGI("Infomation Message CTest");
	LOGE("Error Message CTest");

    return (*env)->NewStringUTF(env, "Return Message of C test");
}

Makefileの作成

Android.makを作成します。LOCAL_MODULEがjavaから読み込むライブラリ名になります。log.hをインクルードしたので、-llogオプションを付けています。

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := ctest_module
LOCAL_SRC_FILES := ctest.c
LOCAL_LDLIBS    := -llog

include $(BUILD_SHARED_LIBRARY)

Cプログラムのビルド

cygwinを用いて、プログラムをビルドします。ログインして、cd projects/Ctestフォルダに移動します。そして、ndk-buildを実行します。これで、ctest_module.soがCtest/libs/armeabi下に生成されます。

CtestActivity.javaの編集

自動生成されたCtestActivity.javaをCプログラムを読み込むように編集します。これもhello-jniサンプルを流用します。System.loadLibrary("ctest_module")としてライブラリ名を指定します。後はpublic nativeで関数を指定すれば使えます。

package com.example.momoonga.ctest;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class CtestActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.main);

        TextView  tv = new TextView(this);
        tv.setText( stringFromJNI() );
        setContentView(tv);
    }
    
    public native String  stringFromJNI();
    public native String  unimplementedStringFromJNI();

    static {	System.loadLibrary("ctest_module");	}
}

実行してみる

画面に Return Message of C test と表示されました。

CatLogも表示されているようです。

ちょっとメモ

eclipsでjavaプログラムを修正しながら、Cのプログラムも修正していると、ライブラリがうまく見えなくなってしまうことがあるようです。そんなときには、Cのモジュール名を変えてやれば、再認識してくれることが多いです。
例えば、ctest_module1とかして、もう一度、ndk-build します。当然、javaのSystem.loadLibrary()も書き換えなくてはなりませんが、これでうまく行くことが多いです。

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := ctest_module1
LOCAL_SRC_FILES := ctest.c
LOCAL_LDLIBS    := -llog

include $(BUILD_SHARED_LIBRARY)

今日はこの辺で。