Android アプリのあれこれ

なんとなくAndroid 環境をいじって遊んでいます。

少しずつですが勝手がわかってきて、やりたいことができるようになってきました。

色々と気になることがあったのでblogにまとめを書いていきたいのですが、なかなかまとまった時間がとれませんね...

とはいえ放置してしまうとそのまま何も書かない日々が続いてしまうので、備忘録程度にやったことを書いてみたいと思います。

  • Java層からNative層の呼び出し
  • WebTo の実装
  • Native層からJava層の呼び出し
  • Suspend / Resume 時の OpenGL Texture の ロスト問題の対応
  • その他

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" />

まとめ

かなり手抜きですが、最近Androidで遊んだことを書いてみました。
もう少し丁寧にまとめなおしたいですね...

ちょっと面白くなってきたので、もう少しスペックの良いAndroid端末が欲しくなってきました。
う~ん、悩ましいっ