apkにndk-buildした実行モジュールを同梱する
前回、luacをAndroidから呼び出すために、いろいろとソースを変更したりして力尽きましたが、素のままビルドしてLuaridaから呼び出す方法がわかりました。
その方法は、eclipsのプロジェクトのasstesフォルダに実行モジュールを入れておいて、アプリ(Luarida)実行時に、/data/data/パッケージ名/files/以下にコピーし、実行権限を付けるというものです。
NDKを用いて実行モジュールをビルドする
まず、適当なプロジェクトを作ります。そして、ndkビルドのためにjniフォルダを作り、その下にluacのソースとAndroid.mkを入れます。luacのソースはluaフォルダを作ってその下に入れています。
Android.mkは下記です。include $(BUILD_EXECUTABLE)することで、実行モジュールができます。
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := luac LOCAL_SRC_FILES := lua/luac.c lua/lauxlib.c lua/ldo.c lua/lfunc.c \ lua/lmem.c lua/lobject.c lua/lstring.c lua/lundump.c \ lua/lopcodes.c lua/ldebug.c lua/lgc.c lua/lparser.c \ lua/lstate.c lua/ltable.c lua/ltm.c lua/lvm.c \ lua/lzio.c lua/llex.c lua/lapi.c lua/lcode.c \ lua/print.c lua/ldump.c include $(BUILD_EXECUTABLE)
この状態で、jniフォルダでndk-buildするとluacが生成します。
luacは、libs/armeabi/下に生成されています。
eclipsプロジェクトに入れる
先に作成したプロジェクトは実行モジュールを作るために使っただけです。実際にはビルドしたモジュールだけ(ここではluacだけ)が必要です。
luacをAndroidアプリ(ここではLuarida)のasstesフォルダにコピーします。私の場合、asstes/bin/というフォルダを作り、そこにluacをコピーしました。
実行モジュールの展開プログラム
assets/binフォルダにあるファイルを実行時に本体の/data/data/...以下にコピーするプログラムを作成しました。
chmodがどのpathに居るかが分からないので、スキャンしていますが、これ以外のフォルダも考えられる場合は追加する必要があります。chmodが見つからなかった場合は、実行権限を変更せずにコピーするだけです。
//************************************************** // assets/bin以下にあるコマンドを本体フォルダにコピーします。 //************************************************** private int assetsCopyBin(){ String folder = "bin"; FileOutputStream output = null; int ret = 0; String[] cmdDir = new String[] { "/sbin", "/system/sbin","/system/bin","/system/xbin" }; String[] cmds = new String[] { "", "755", "" }; //chmodコマンド有無チェック。chmodがあれば、cmds[0]にパスが入っており、okFlg=trueである。 boolean okFlg = false; for (String strdir : cmdDir) { cmds[0] = strdir + "/chmod"; File chm = new File(cmds[0]); if( chm.exists() ){ okFlg = true; break; } } try { Runtime runtime = Runtime.getRuntime(); AssetManager as = getResources().getAssets(); String[] binfiles = as.list(folder); //assets/bin/以下にあるファイル名を読み込みます int n; int DEFAULT_BUFFER_SIZE = 1024 * 4; byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; //asset/bin/以下のファイルを /data/data/パッケージ名/files/以下にコピーします for(int i=0; i<binfiles.length; i++ ){ InputStream is = as.open(folder+"/"+binfiles[i]); output = openFileOutput(binfiles[i], Context.MODE_PRIVATE); n = 0; while (-1 != (n = is.read(buffer))) { output.write(buffer,0,n); } output.flush(); output.close(); is.close(); //パーミッションを設定します if(okFlg){ cmds[2] = getFileStreamPath(binfiles[i]).getAbsolutePath(); runtime.exec(cmds); } } } catch (IOException e) { e.printStackTrace(); ret = 1; } return ret; }
権限が変更されていなくても、Luaridaの場合はスクリプト側から、os.execute()を用いてchmodコマンドを実行できるので、後付で権限変更も可能です。
また、openFileOutput(ファイル名, Context.MODE_PRIVATE)としているので、実行モジュール(luac)は、Luaridaの場合、/data/data/com.momoonga.luarida/files/以下にコピーされます。
Luaridaからluacを使う
実行モジュールを使用するサンプルプログラムです。権限変更はしなくても大丈夫なはずです。動作しないときには実行してみればいいと思います。ただし、現在公開中のLuaridaには、まだ、実装していません。luacを実装したLuaridaを公開しました。
LuaridaPath = "/sdcard/luarida" --luaファイルを保存しているPath function main() local BinPath = "/data/data/com.momoonga.luarida/files" os.execute( "chmod 755 "..BinPath.."/*") --実行モジュールに実行権限を与えています os.execute( BinPath.."/luac -s -o "..LuaridaPath.."/luarida.luac "..LuaridaPath.."/luarida.lua") end main()
次バージョンを早く公開しないと。