Activity(アクティビティ)の結果を dependency service の中でハンドルしたい
Xamarin.Forms の Android 側で音声認識やカメラ等を利用する場合、dependency service からそれ用のアクティビティを起動し、その処理結果のハンドルまで行うということをしたくなったりします。
処理結果のハンドルは、MainActivity.cs 内で OnActivityResult をオーバーライドした処理を実装することでも可能です。ですが、なるべくであれば MainActivity に個別の処理を実装することを避け、dependency service の中だけで処理を完結させる方が、「あるべきものがあるべき場所にある」という感じになります。
それを実現するための実装方法を書きます。
デフォルトの MainActivity への追加実装
プロジェクト作成直後の標準の MainActivity.cs には、以下のように実装を追加します。
2行足すだけです。 2行だけでは足りません。すみませんでした。。。
MainActivityの外から参照できるようなイベントハンドラのプロパティを用意し、OnActivityResult でそれを呼びます。
1. usingの追加
using Android.Preferences;
using Android.Content; // なければ追加
2. アクティビティ用のイベントハンドラをプロパティとして宣言
これを宣言することで、dependency service 内にアクティビティのイベントハンドラの実体を実装できるようになります。
public event EventHandler<PreferenceManager.ActivityResultEventArgs> ActivityResult = delegate {};
3. OnActivityResult でイベントハンドラを呼ぶ
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
// resultEventArgsの第1引数(Handled)は、ハンドル後に特に使う用事がなければtrueでもfalseでも問題なさそう
var resultEventArgs = new PreferenceManager.ActivityResultEventArgs(true, requestCode, resultCode, data);
ActivityResult(this, resultEventArgs);
}
dependency service 側の実装
1. usingの追加
using Android.Preferences;
2. MainActivityのインスタンスを持っておくためのフィールドの宣言
これは必ずやらないといけないわけではないですが、MainActivityを保持しておくと便利なので、それ用のフィールドを用意します。
private MainActivity mainActivity;
3. アクティビティ用イベントハンドラの実体の作成
private void HandleActivityResult(object sender, PreferenceManager.ActivityResultEventArgs args)
{
// SOME_REQUEST_CODEは、アクティビティ呼び出しのときに渡した任意のリクエストコード。
if (args.RequestCode == SOME_REQUEST_CODE)
{
if (args.ResultCode == Result.Ok)
{
// アクティビティの処理が成功した場合の処理をここに実装する。
// 必要となる情報は大体 args.Data から取得できる。
}
}
}
4. コンストラクタへの処理の追加
コンストラクタに、「MainActivity のインスタンス取得処理」と「イベントハンドラの処理の実体の紐付け」を実装します。
public SomeDependencyService()
{
(省略)
mainActivity = Forms.Context as MainActivity;
mainActivity.ActivityResult += HandleActivityResult;
(省略)
}
5. アクティビティの開始処理
// someIntentは、アクティビティ呼び出しのための任意のインテント。
// SOME_REQUEST_CODEは任意のint値。
mainActivity.StartActivityForResult(someIntent, SOME_REQUEST_CODE);
サンプルアプリ
上記の実装方法で動かしているアプリです。Xamarin.Formsで音声認識を行っています。
https://github.com/microwavePC/VoiceRecognitionSample