Android アプリのあれこれ
なんとなくAndroid 環境をいじって遊んでいます。
少しずつですが勝手がわかってきて、やりたいことができるようになってきました。
色々と気になることがあったのでblogにまとめを書いていきたいのですが、なかなかまとまった時間がとれませんね...
とはいえ放置してしまうとそのまま何も書かない日々が続いてしまうので、備忘録程度にやったことを書いてみたいと思います。
Java層からNative層の呼び出し
コードの要点だけ抜き出してしまうとこんな感じかな...
void CallTest() { ... // 処理 } static const JNINativeMethod meths[] = { {"onCallTest", "()V", (void*)CallTest}, }; /// NativeInterface クラスへ native 呼び出しをバインドする bool RegistNativeInterface(JNIEnv* env, const char* class_path) { jclass cls = env->FindClass(class_path); if (env->RegisterNatives(cls, meths, sizeof(meths)/sizeof(meths[0]))) { return false; } return true; } ||< 引数にJavaのオブジェクトが渡ってくるときとか、戻り値の設定とかがわかりづらい感じですね。 ** WebTo の実装 Intent を利用して、WebTo みたいなことを実装してみました。 コードはこんな感じ >|| static public void webTo(String url) { if (parent_act != null) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); actitivy.startActivity(intent); } }
コードだけ抜き出しちゃうと面白くないけど、Intent ってのは面白い仕組みだと思いました。
Native層からJava層の呼び出し
WebTo の機能をC++側から呼び出したくて実装してみました。
要点だけ抜き出すとこんな感じ
void WebTo(const std::string& uri) { JavaVM* vm = GetVM(); JNIEnv* env = GetJNIEnv(); if (!env) return ; jclass cls = env->FindClass(g_native_class_path.c_str()); if (cls == 0) { return ; } jmethodID method = env->GetStaticMethodID(cls, "webTo", "(Ljava/lang/String;)V"); if (method == 0) { return ; } env->CallStaticVoidMethod(cls, method, env->NewStringUTF(uri.c_str())); }
GetVM() / GetJNIEnv() は自前のヘルパー関数なので、まぁ適当に実装していただいて...
JNIEnv::Call*Method を利用すると Java のインターフェースが呼び出せるってのがポイントっちゃポイントかと。
WebToをC++側から呼び出すって点に関しては、もう少しインターフェースを整理したほうが良さそうですが、まぁお手軽実装ということで
Suspend / Resume 時の OpenGL Texture の ロスト問題の対応
サスペンドで OpenGL の Texture がロストするみたいなので対応を行ってみました。
Activity#onPause /Activity#onResume を経由してせっせとロスト対策しても良いですが、GLSurfaceView#setPreserveEGLContextOnPause に true を設定して上げるとPause時にコンテキストが保持するTextureなどのデータを保持するようです。
classs MyGLView extends GLSurfaceView { public MainView(Context context) { super(context); setEGLContextFactory(new ContextFactory()); setEGLConfigChooser(new ConfigChooser(8, 8, 8, 8, 24, 0, 16)); setRenderer(new MainRenderer()); setPreserveEGLContextOnPause(true); } //(略) }
この API は、SdkVersion=21 から追加されたモノなので、AndroidManifest.xml の "uses-sdk" エレメントを適切に設定する必要があります。
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" />