Android
Xamarin
Xamarin.Android
音声認識
SpeechRecognition

ようやく重い腰を上げ、Xamarinはじめました。
Xamarin.Forms使わなきゃXamarinやる意味がないという声も ちらほら聞こえますが
とりあえず、初心者としてはXamarin.Androidで音声認識使うサンプルから始めてみます。

苦戦したこととして、Android側の音声認識はすぐ動いてくれたのですが、
OnActivityResult で結果が受け取れない。。。

以下の行を挿入することで解決したのですが
public event EventHandler<PreferenceManager.ActivityResultEventArgs> ActivityResult = delegate { };
これ何で必要なんでしょうか??
ActivityResultを空メソッドにしているみたいだけど、、、
ご存知の方コメントお待ちしております。。。

以下、詳細です。

開発環境

まずは開発環境です。

OS:Windows10
IDE:VisualStudio2017
Xamarin:4.8
Xamarin.Android SDK:8.1.0.24

参考元

下記の記事を参考にしてます。
【Xamarin.Forms】音声認識の使い方
https://qiita.com/microwavePC/items/40b1016cf84ea89c4ed1

UI

UIのほうはTextViewとButton1個ずつのシンプルなもの
screenshot-1513316414975.jpg screenshot-1513316423190.jpg

ソースコード

Main.axml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/relativeLayout1"
        android:background="#545454">
        <TextView
            android:text="This is sample of Speech Recognize."
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/txt1"
            android:layout_marginLeft="10dp"
            android:textStyle="bold"
            android:textColor="@android:color/white"
            android:layout_marginTop="10dp"
            android:layout_centerHorizontal="true" />
        <Button
            android:text="Start"
            android:id="@+id/btn1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:width="165dp"
            android:layout_below="@id/txt1"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:layout_centerHorizontal="true" />
    </RelativeLayout>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/txt2" />
</LinearLayout>
MainActivity.cs
using System;
using Android.App;
using Android.Widget;
using Android.Content;
using Android.OS;
using Android.Speech;

using Android.Preferences;

namespace App1
{
    [Activity(Label = "Speech Recognize Sample App", MainLauncher = true)]
    public class MainActivity : Activity
    {
        #region Constant, MainActivity

        // 定数・MainActivity
        private readonly int REQUEST_CODE_VOICE = 10;       // 音声認識のリクエストコード
        private readonly int INTERVAL_1500_MILLISEC = 1500; // 1.5秒(ミリ秒単位)

        #endregion

        public event EventHandler<PreferenceManager.ActivityResultEventArgs> ActivityResult = delegate { };

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);
            Button button1 = FindViewById<Button>(Resource.Id.btn1);

            button1.Click += Button_Click;
        }

        private void Button_Click(object sender, System.EventArgs e)
        {
            Toast.MakeText(this, "speech recognize started.", ToastLength.Short).Show(); // トースト表示

            try
            {
                // 音声認識のアクティビティを呼び出すためのインテントを用意する。
                var voiceIntent = new Intent(RecognizerIntent.ActionRecognizeSpeech);

                // 諸々のプロパティを設定する。
                voiceIntent.PutExtra(RecognizerIntent.ExtraLanguageModel, RecognizerIntent.LanguageModelFreeForm);
                voiceIntent.PutExtra(RecognizerIntent.ExtraPrompt, "Speak to me!");
                voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputCompleteSilenceLengthMillis, INTERVAL_1500_MILLISEC);
                voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputPossiblyCompleteSilenceLengthMillis, INTERVAL_1500_MILLISEC);
                voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputMinimumLengthMillis, INTERVAL_1500_MILLISEC);
                voiceIntent.PutExtra(RecognizerIntent.ExtraMaxResults, 1);

                // 認識言語の指定。端末の設定言語(Java.Util.Locale.Default)で音声認識を行う。
                voiceIntent.PutExtra(RecognizerIntent.ExtraLanguage, Java.Util.Locale.Default);

                // 音声認識のアクティビティを開始する。
                StartActivityForResult(voiceIntent, REQUEST_CODE_VOICE);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        // 音声認識のアクティビティで取得した結果をハンドルする処理の本体
        protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            base.OnActivityResult(requestCode, resultCode, data);

            if (requestCode == REQUEST_CODE_VOICE)
            {
                if (resultCode == Result.Ok)
                {
                    // 認識が成功した場合、認識結果の文字列を引き出し、RecognizedTextに入れる。
                    var matches = data.GetStringArrayListExtra(RecognizerIntent.ExtraResults);
                    if (matches.Count != 0)
                    {
                        FindViewById<TextView>(Resource.Id.txt2).Text += matches[0] + "\n";
                    }
                }
            }
        }
    }
}