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

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

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()

次バージョンを早く公開しないと。