LoginSignup
24
23

UnityのAndroidJavaProxyを使ってActivityを使いやすくする

Last updated at Posted at 2015-03-06

UnityのAndroidJavaProxyってなんぞ

検索してもなかなか資料がありませんが、簡単に言えば、
JavaのinterfaceをC#で実装ができるものです。

最近日本語マニュアルに訳されたものがでましたね。
Unityマニュアル:AndroidJavaProxy

2015/02/26 マニュアルのC#ソース間違ってるので正しいはずのもの載せておきます

using UnityEngine;
using System.Collections;

public class SelectedDate : MonoBehaviour {
    public static Date date = System.DateTime.Now;
}

public class DateCallback : AndroidJavaProxy {
    public DateCallback()
        :base("android.app.DatePickerDialog$OnDateSetListener")
    {
    }

    void onDateSet(AndroidJavaObject view, int year, int monthOfYear, int dayOfMonth) {
        SelectedDate.date = new Date(year, monthOfYear + 1, dayOfMonth);
    }
}

public class ExampleClass : MonoBehaviour {
    void OnGUI() {
        if (GUI.Button(new Rect(10, 10, 450, 100), String.Format("{0:yyyy-MM-dd}", SelectedDate.date))) {
            AndroidJavaObject activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity");
            activity.Call(
                "runOnUiThread",
                AndroidJavaRunnable(
                    new AndroidJavaObject(
                        "android.app.DatePickerDialog",
                        activity,
                        new DateCallback(),
                        SelectedDate.date.Year,
                        SelectedDate.date.Month - 1,
                        SelectedDate.date.Day
                    ).Call("show");
                )
            );
        }
    }
}

思ったよりわかりづらかった。

ActivityのListenerを作る

まず、プラグインとなるjarを作ります。
Activityをつくるので、AndroidManifest.xmlも用意しないといけないですが、説明は省略させていただきます。

ExActivityListener.java
public interface ExActivityListener
{
    public void onRestart();

    public void onStart();

    public void onResume();

    public void onPause();

    public void onStop();

    public void onActivityResult(int requestCode, int resultCode, Intent data);
}
ExActivity.java
public class ExActivity extends com.unity3d.player.UnityPlayerActivity
{
    private ExActivityListener listener;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
    }

    public void setListener(ExActivityListener listener)
    {
        this.listener = listener;
    }

    @Override
    public void onRestart()
    {
        super.onRestart();
        if(listener != null) listener.onRestart();
    }

    @Override
    public void onStart()
    {
        super.onStart();
        if(listener != null) listener.onStart();
    }

    @Override
    public void onResume()
    {
        super.onResume();
        if(listener != null) listener.onResume();
    }

    @Override
    public void onPause()
    {
        super.onPause();
        if(listener != null) listener.onPause();
    }

    @Override
    public void onStop()
    {
        if(listener != null) listener.onStop();
        super.onStop();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        if(listener != null) listener.onActivityResult(requestCode, resultCode, data);
    }
}

こんな感じに、Listenerをセットする関数を用意し、
それぞれでListenerの対応した関数を呼びます。

次に、C#からListenerをセットし、コールバックを受け取れるようにします。
その時に使用するのが、AndroidJavaProxyです。

hoge.cs
public class Hoge : MonoBehavior
{
    public class ActivityListener : AndroidJavaProxy
    {
        public ActivityListener()
            : base("com.hoge.ExActivityListener")
        {
        }

        public void onRestart()
        {
        }

        public void onStart()
        {
        }

        public void onResume()
        {
        }

        public void onPause()
        {
        }

        public void onStop()
        {
        }

        public void onActivityResult(int requestCode, int resultCode, AndroidJavaObject data)
        {
        }
    }

    void Awake()
    {
        AndroidJavaObject activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity");

        activity.Call("setListener", new ActivityListener());
    }
}

C#で作るものは同関数名で、引数もそのまま対応するものにします。
javaのクラスが引数の場合、AndroidJavaObjectを指定します。

currentActivityを取得し、Listenerをセットして完成です。

便利になること

いくつかプラグインを入れると、onActivityResultで処理を入れないといけないことが多々あります。
そのたび、プラグイン追加して、呼び出すjarファイル更新して・・・と手間がかかります。
これならUnity上で、onActivityResultを使用するプラグインも追加が容易になります。

この例ではActivityですが、引数がそのまま使用出来るので、ライブラリのコールバックとしても使いやすいです。
UnitySendMessageのように、文字列1つだけの引数で悩む必要もなくなります。

デメリット

javaコードから呼ばれるListenerは、java側でコールされたスレッドになるので、ほとんどの場合、UnityAPIが使用出来ません。
使用する場合、一時的にAction等持たせて、Updateで呼ぶ等が必要です。
その場合はロック処理もしておくといいでしょう。

onPause、onResumeは
void OnApplicationPause(bool isPause)
でもいい気はしますが、スレッドの違いでもしかしたら何かに使えるかもしれません。

24
23
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
23