rksoftware

Visual Studio とか C# とかが好きです

Google Home に OK, Google と呼びかけるのが恥ずかしいのでアプリで解決してみた

Google Home に OK, Google と呼びかけるのが恥ずかしいのでアプリで解決してみました。

アプリは Xamarin.Forms でシュッと作ってしまいます。

DependencyService

今回のアプリは、DependencyService を使ってプラットフォーム毎に個別実装が必要な部分を実装し、Android・iOS に対応しています。
参考:DependencyService

簡単にいうと、共通コードプロジェクトでインタフェースを定義し、各プラットフォームのプロジェクトでインタフェースの実装をすると、共通コードでインタフェースを扱うだけで実装を扱えるすごいやつです。とても便利なので覚えておくとよいと思います。
※今回は DependencyService を使って実装しましたが、今回扱う機能であれば NuGet にある Xam.Plugins.TextToSpeech を使えば OK だったりします。

また、今回のコードは API ドキュメントのコードほぼそのままです。コードの解説は次のドキュメントを参照してください。
https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/dependency-service/text-to-speech/

コード

早速コードを書いて行きます。

プロジェクトの作成

今回作成したプロジェクトは次のようになっています。
・Xamarin.Forms
・iOS、Android のみ
・.NET Standard
・プロジェクト名は OKGoogleHelper

共通コード(コードを変更)

MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:OKGoogleHelper"
             x:Class="OKGoogleHelper.MainPage">

    <Button Text="Say 'OK, Google!'" 
           VerticalOptions="Center" 
           HorizontalOptions="Center" x:Name="say"/>

</ContentPage>

MainPage.xaml.cs

using Xamarin.Forms;

namespace OKGoogleHelper
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();

            say.Clicked+=(sender,e)=> DependencyService.Get<ITextToSpeech>().Speak("OK, Google!");
        }
    }
}

共通コード(インタフェース追加)

ITextToSpeech.cs

namespace OKGoogleHelper
{
    public interface ITextToSpeech
    {
        void Speak(string text);
    }
}

Android プロジェクト(クラス追加)

TextToSpeechImplementation.cs

using Android.Speech.Tts;
using Java.Util;
using OKGoogleHelper.Droid;
using Xamarin.Forms;

[assembly: Dependency(typeof(TextToSpeechImplementation))]
namespace OKGoogleHelper.Droid
{
    public class TextToSpeechImplementation : Java.Lang.Object, ITextToSpeech, TextToSpeech.IOnInitListener
    {
        TextToSpeech speaker;
        string toSpeak;

        public void Speak(string text)
        {
            toSpeak = text;
            if (speaker == null)
            {
                speaker = new TextToSpeech(Forms.Context, this);
            }
            else
            {
                speaker.SetLanguage(Locale.Japan);
                speaker.Speak(toSpeak, QueueMode.Flush, null, null);
            }
        }

        public void OnInit(OperationResult status)
        {
            if (status.Equals(OperationResult.Success))
            {
                speaker.SetLanguage(Locale.Japan);
                speaker.Speak(toSpeak, QueueMode.Flush, null, null);
            }
        }
    }
}

iOS プロジェクト(クラス追加)

TextToSpeechImplementation.cs

using AVFoundation;
using OKGoogleHelper.iOS;
using Xamarin.Forms;

[assembly: Dependency(typeof(TextToSpeechImplementation))]
namespace OKGoogleHelper.iOS
{
    public class TextToSpeechImplementation : ITextToSpeech
    {
        //public TextToSpeechImplementation() { }

        public void Speak(string text)
        {
            var speechSynthesizer = new AVSpeechSynthesizer();
            var speechUtterance = new AVSpeechUtterance(text)
            {
                Rate = AVSpeechUtterance.MaximumSpeechRate / 4,
                Voice = AVSpeechSynthesisVoice.FromLanguage("en-US"),
                Volume = 0.5f,
                PitchMultiplier = 1.0f
            };

            speechSynthesizer.SpeakUtterance(speechUtterance);
        }
    }
}

言語について

Android では日本語設定でもなんか悪くない感じだったので、日本語を指定しています。iOS は日本語設定だとかなり厳しいものがあったので英語を指定しています。

実行

実行すると次のような画面が表示されます。(画面は Android)

課題解決!

ボタンをタップすると、あなたに代わってスマートフォンが「OK, Google」と Google Home に語り掛けてくれます。
これで、恥ずかしくないですね。