lab/技術情報 最終更新日:2010-11-21 (日) 15:06:00
android NDK revision 4b †
- android NDK r4bについてのメモ。
- android端末で画像処理をする。DalvikVM経由ではいかんせん遅いらしい。JNIを使ってVMを経由せずにコードを実行することで、高速化をはかる。
- NDKでは、androidからJNIを使うためのコンパイラを提供する。cで記述したコードをNDKでコンパイルしてライブラリ化(.so)。ライブラリをandroidアプリからコールする。
目次 †
環境 †
- PC
- ubuntu 10.4 (のハズ)
- eclipse (helios)
- android
- Softbank Desire (root取得し、ANDROID2.2(froyo)をインストール済み)
インストール †
- JDK 1.6 ... 問題無し
- eclipse (helios)
- eclipseのインストールは本家サイトからtar.gzをDLしてくること。ジャンク☆ニュース 臥龍にあるように、apt-getでインストールしたeclipseだとandroid sdkがうまく入らない。
- android sdk ... 問題なし
- android ndk ... 問題なし
てすと †
NDKに付属のテスト”hello-jni”をビルドしてみる。
- DalvikVM上で動作する側のHelloJni?.javaは、eclipseにてAutoBuild?されるようになっている。問題無し。
- 呼び出される側のhello-jni.cのビルドはeclipseではAutoBuild?されない模様。
コマンドラインから
% ndk-build
すると、Android.mkに記述されたコマンドが走り、.soファイルが1つ上位階層のlibsディレクトリに生成される。
- 実機でHelloJni?.javaのコンパイルしたものを走らせてみる。うまくいったぽい。
openCVは動くのか?! †
- Androidの移植が進んでいることは以前から知っていた。実際に手元の実機で試してみる。
- 「なんとなく実験 with SIProp開発記」の2009年10月23日のポスト、OpenCV Ver.1.1 For Android NDK の メンテチームが結成されました。にしたがってみる。
- プロジェクトサイトに上がっているライブラリはNDKのrev.3向けである(last commitは2010/3/9で開発が止まっている)。rev.4でビルドした手順は以下のとおり。
- <android-ndk-root>/samples/testOpenCV/jni/ なるディレクトリを作る。その下にライブラリをDLしてできた中身を展開。つまり、<android-ndk-root>/samples/testOpenCV/jniの下に、cv cvauc ml cxcoreなどのディレクトリができることとなる。
- <android-ndk-root>/samples/hello-jni/AndroidManifest?.xml を <android-ndk-root>/samples/testOpenCV/ にコピー
- <android-ndk-root>/samples/testOpenCV/ にて
ndk-build
すると、<android-ndk-root>/samples/testOpenCV/tests/VideoEmulation?/libs/armeabi/libopencv.so なるライブラリがビルドされる。
画像キャプチャ系サンプルのコンパイル †
- <android-ndk-root>/samples/testOpenCV/tests/CameraConfiguration?をビルドしてみる。このサンプルはandroid1.6あたりのAPIを使っているため、android2.0ではビルドまでできるものの、カメラが動作しない。
- Dev1Camera.javaの244行目あたりに
//-------------- Camera's method --------------
なるセパレータがあるので、これの上あたりに次の2メソッドを追加
protected void setPictureFormat(int format) {
try {
Camera.Parameters params = mCameraDevice.getParameters();
List<Integer> supported = params.getSupportedPictureFormats();
if (supported != null) {
for (int f : supported) {
if (f == format) {
mCameraDevice.setPreviewFormat(format);
mCameraDevice.setParameters(params);
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
protected void setPreviewSize(int width, int height) {
Camera.Parameters params = mCameraDevice.getParameters();
List<Camera.Size> supported = params.getSupportedPreviewSizes();
if (supported != null) {
for (Camera.Size size : supported) {
if (size.width <= width && size.height <= height) {
params.setPreviewSize(size.width, size.height);
mCameraDevice.setParameters(params);
break;
}
}
}
}
- これらのメソッドの呼び出し元であるsetViewFinder?() 、capture()を修正:
mCameraDevice.setParameters(parameters);
となっている箇所を
setParameters(parameters);
に修正。
- surfaceChanged()メソッドに
setPictureFormat(format);
な行を追加。
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// if we're creating the surface, start the preview as well.
boolean preview = holder.isCreating();
setPictureFormat(format);
setViewFinder(w, h, preview);
mCaptureObject = mImageCapture;
startPreview();
}
- 撮影と表示の縦横比を合わせるため、AndroidManifest?.xmlに次の行を追加。
<activity android:name="OpenCVSample" android:screenOrientation="landscape" />
- いけたぽい
画像処理系サンプルのコンパイル †
bad know-how †
JNIメソッド名にアンダースコアを入れるとエラー †
- java側で
package com.hoge;
public class FooBar{
public native String foo_bar();
}
のようにメソッドfoo_bar()を呼び出すと、
- 呼び出されるC側で
jstring Java_com_hoge_FooBar_foo_bar()
のような関数定義となる。
- android-SDK,android-NDKともコンパイルは通る。が実行時に
java.lang.UnsatisfiedLinkError
が投げられて実行時エラー終了する。
- 解決策は、メソッド名のアンダースコアを除去し
//in java source code ...
package com.hoge;
public class FooBar{
public native String foobar();
}
//in C source code ...
jstring Java_com_hoge_FooBar_foobar()
のように定義すればOK。JNIではパッケージ名の区切りにアンダースコアを用いている。その区切りと関数名のアンダースコアがバッティングすると、うまくリンクできないということか。そんなアホな。
ライブラリを再ビルドしてもJavaのビルド(.apkファイル)に反映されない。 †
comments †
#comment_kcaptcha