Android SDK assetsの内容を全てローカルにコピーする
AndroidNDKでアプリ内のリソースファイルを利用しようと思った場合、
ローカル(/data/data/<パッケージ名>/files/)のファイルを利用するしかない。
そのため、起動時にassetsに置いてあるファイルを全てローカルにコピーする関数を作った。
更に、初回起動時のみこの更新処理を発生させるような処理が必要かと思う。
例えばこの関数に成功したらプリファレンスにアプリのバージョンコードを記録することにして、
実行前に現在のバージョンコードと比較して差異があったら実行とかね。
お。適当に考えたけどこのロジック良さそうだな。
ともあれ、とりあえずは以下のようなコードを書いてみました。
private void copy2Local() throws IOException{ // assetsから読み込み、出力する String[] fileList = getResources().getAssets().list("resource"); if(fileList == null || fileList.length == 0){ return; } AssetManager as = getResources().getAssets(); InputStream input = null; FileOutputStream output = null; for(String file : fileList) { input = as.open("resource" + "/" + file); output = openFileOutput(file, Context.MODE_WORLD_READABLE); int DEFAULT_BUFFER_SIZE = 1024 * 4; byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; int n = 0; while (-1 != (n = input.read(buffer))) { output.write(buffer, 0, n); } output.close(); input.close(); } }
この場合、「assets」以下に「resource」フォルダを作成し、その下に
コピーしたいファイルを置くことになります。
結構適当に書いてるソースコードだけど、そこそこ汎用的に利用できるかな?
output.write失敗したらストリームが閉じられずに関数抜けそうだけど。 気にしない。
ファイルストリームを使って出力すると、デフォルトでローカルに出力されます。
後はNDK内に書いたコードに「"/data/data/" + this.getPackageName() + "/files/"」のパスを
渡してあげて、+利用したいファイル名でファイルを利用することが出来ると思う。
ちなみに、ファイル名を指定してコピーする場合はこんな感じで書いてました。
private void copy2Local(String fileName) throws IOException { // assetsから読み込み、出力する AssetManager as = getResources().getAssets(); InputStream input = as.open(fileName); FileOutputStream output = openFileOutput(fileName, Context.MODE_WORLD_READABLE); int DEFAULT_BUFFER_SIZE = 1024 * 4; byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; int n = 0; while (-1 != (n = input.read(buffer))) { output.write(buffer, 0, n); } output.close(); input.close(); }
意外にこういうロジック用意しておくと便利かもしれない。