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

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

最近日本語マニュアルに訳されたものがでましたね。
[Unityマニュアル：AndroidJavaProxy](http://docs.unity3d.com/ja/current/ScriptReference/AndroidJavaProxy.html)

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

```csharp
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も用意しないといけないですが、説明は省略させていただきます。

```java: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);
}
```

```java: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```です。

```csharp: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)```
でもいい気はしますが、スレッドの違いでもしかしたら何かに使えるかもしれません。