fc2ブログ
ヽ|∵|ゝ(Fantom) の 開発blog? ホーム »音声認識
このページの記事一覧

【Unity】Androidで音声認識を使う  


 今回はプラグイン内に入っている音声認識を改めて Unity 側のコードを中心に書いてみよう。大まかにはダイアログを表示する方法と、自分でUIなどを用意し、コールバックメソッドを使って実装していく方法がある。用途によって使い分けるのも良いだろう。

 プラグインの内部的なコード(Java)を知りたい場合は以前の記事を参照して欲しい。プラグイン自体のセットアップからはじめる場合も以前の記事を参照。

>>プラグイン&サンプルをダウンロード
(Google Drive を利用。画面右上にあるダウンロードアイコンを押す)



(※) Unity 5.6.3p1 / AndroidStudio 2.3.3 / Windows10(x64) / Galaxy S7 Edge (Android 7.0) で確認



■音声認識する際の AndroidManifest.xml について

※Android11 以降では音声認識(SpeechRecognizer)に専用パーミッションが必要になったようです。

 プラグインのセットアップにも書いてあるが、ここではもう少し詳細に解説しておこう。Googleの音声認識など別のアプリケーションから結果を受け取る際には Unity で通常使われるアクティビティ「UnityPlayerActivity」をオーバーライドした、「ReceiveResultsOnUnityPlayerActivity」(他のアプリケーションから結果を受信するアクティビティ:プラグイン内に入っている)または「FullPluginOnUnityPlayerActivity」(プラグイン機能のすべてが入っている)を使う必要がある。これらのアクティビティ(Activity)はこのプラグイン独自のアクティビティで、他のアプリケーションから何らかのメッセージを受信できるコードが含まれている(Java コードは以前の記事に掲載してある)。インポートした「Assets/Plugins/Android/」にはマニフェストファイルのテンプレとして「AndroidManifest-Speech~.xml」または「AndroidManifest-FullPlugin~.xml」が含まれているので、これらの中から適切なものを選んで(「縦置き・横置き」とか「API Level」とか)、「AndroidManifest.xml」にリネームしてビルドすることで利用することが可能になる。


 なお、ダイアログを表示せず、音声認識のコールバックイベントを実装して結果を受信するなら、オーバーライドしたアクティビティを使う必要はない。具体的には例えば、後述する「StartSpeechRecognizer()」を使って音声認識の音声待機・開始・結果取得・エラーのコールバックを実装するなら、これらマニフェストファイルは必要ない(Unity がデフォルトのマニフェストファイルを用意してくれる)。Unity ではキャラなどを出したいことも多いと思うので、少し大変だが、コールバックイベントを実装していく方法はオススメだ。

(※) 音声認識にはマニフェストファイルに録音パーミッション "RECORD_AUDIO" が必要(「AndroidManifest-Speech~.xml」または「AndroidManifest-FullPlugin~.xml」には含まれている)。

(※) 独自のマニフェストファイルでビルドすると警告「Unable to find unity activity in manifest. You need to make sure orientation attribute is set to sensorPortrait manually.」が出るが、「UnityPlayerActivity」以外のアクティビティを使うと出るものなので気にしなくて良い(orientation=画面回転はUnity側のアプリの設定に合わせた方が良い)。



■ダイアログを使用した音声認識の利用方法


 サンプルシーン「SpeechRecognizerTest」には2つの方法が含まれているが、こちらは「Speech Dialog」のボタンを押したとき出てくる Googleの音声認識ダイアログを利用する方法だ。簡単に言えば、このダイアログは別のアプリケーションであって、それを呼び出して結果だけを受け取る方法であり、音声認識中の待機や開始、失敗(エラー)のときなどは任せっきりで、結果を受け取るだけなので実装は非常に楽だ。しかし、前述した「別のアプリケーションから結果を受け取る特別なアクティビティ」が必要なのと、ダイアログの性質上、画面にオーバーレイで重ねられて表示されるので、Unity でキャラなどが表示されている場合見えなくなってしまうのがデメリットだ。なので、InputField の文字入力の代わりに使うなど、見た目を気にする必要がないときに利用する方が良いだろう(受信する結果などは後述するコールバックの方法と何ら変わりはない)。

 それでは、音声認識のダイアログを呼び出す所からやってみよう。

●Unity から音声認識ダイアログを呼び出す
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.ShowSpeechRecognizer(callbackGameObject, resultCallbackMethod, message);
#endif

●引数
callbackGameObject音声認識が成功した際、結果をコールバックするヒエラルキーにある GameObject の名前。
resultCallbackMethod音声認識が成功した際、結果をコールバックするメソッドの名前(callbackGameObject 内)。引数に string 型を1つとる。
messageダイアログに表示されるメッセージ文字列。省略すると(=空文字("")) "なんでも話してみてください" になる(システム/バージョンによるかも)。

 認識された音声は "候補1\n候補2\n候補3" のように改行区切り("\n") でヒエラルキーにある GameObject(callbackGameObject)にあるメソッド(resultCallbackMethod)の引数(string 型)として1つづきの文字列として送られてくる。メソッドの名前は任意だが、シグニチャが違っていると無視されてしまうので気をつけよう。例えば結果のコールバックメソッドの名前を "OnResult" と名付けたとすると、以下のように書けば、認識された1つ1つの候補が列挙できる。

●音声認識された文字列を受信するコード
private void OnResult(string result)
{
string[] words = result.Split('\n');
foreach (var item in words)
{
Debug.Log(item); //各候補の文字列
}
}

 ここでは foreach で認識された各候補を表示しているだけだが、ここであらかじめ作っておいた辞書などと照合して処理を分岐したり、プラグインの選択ダイアログを使ってユーザーに絞り込んで貰って、文字列を InputField に代入して利用するなどでも良いだろう。

 サンプルコード「SpeechRecognizerTest.cs」では「ShowSpeechRecognizer()」「ResultSpeechRecognizer()」になるので、コピペなどして使えば難しくはないだろう。シーン「SpeechRecognizerTest」内で「Web Search」のチェックをオンにしたときには選択ダイアログが出るようにしてあるので、絞り込みをしたいときはこの辺りをまるっとコピペすれば簡単に使えると思う。



■コールバックを実装した音声認識の利用方法


 こちらは前述のダイアログを使用した方法とは異なり、Unity でダイアログを介さずに音声認識の結果やエラーなどを受信する方法となる。サンプルシーン「SpeechRecognizerTest」では「Speech Here」のボタンを押したときがそれだ。少し大変かも知れないが、ダイアログを使うより自由度は高いので、Unity などビジュアルが中心のコンテンツには合っている(ビジネスツールみたいなものは、かえってダイアログを出したほうがわかりやすい気がする)。「一択彼女(加藤恵)」みたいなアプリも内部的には同じものを使ってると思う(このプラグインとは関係ないです)。ちなみに音声認識中の "ピロ♪" という音は消せないそうだ。

 なお、こちらのコールバックを実装する方法では前述した特別なアクティビティは必要ないが、録音パーミッション("RECORD_AUDIO")だけは必要だ。

 それではダイアログなしの音声認識を開始するコードを書いてみよう。また未確認だが、機種によって微妙に挙動が異なるとの話もあるので、実機があるのなら色々テストしておいた方が良いかも知れない。

●Unity からコールバックを実装した音声認識を開始する
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.StartSpeechRecognizer(callbackGameObject, resultCallbackMethod, errorCallbackMethod,
readyCallbackMethod, beginCallbackMethod);
#endif

●引数
callbackGameObject音声認識の結果やエラーなどをコールバックするヒエラルキーにある GameObject の名前。
resultCallbackMethod音声認識が成功した際、結果をコールバックするメソッドの名前(callbackGameObject 内)。引数に string 型を1つとる(結果が返る)。
errorCallbackMethod音声認識が失敗した際、エラーをコールバックするメソッドの名前(callbackGameObject 内)。引数に string 型を1つとる。主なエラーは以下を参照
readyCallbackMethod音声認識が開始され、声の待機をはじめたときコールバックするメソッドの名前(callbackGameObject 内)。UI などを変化させて音声認識がオンになった状態がユーザーにわかるようにしてあげると良い。引数に string 型を1つとる。値は必ず "onReadyForSpeech" になる。タイミングをとるためだけのコールバック。省略可。
beginCallbackMethod音声認識が開始→待機から、はじめの声がマイクに入ったときコールバックするメソッドの名前(callbackGameObject 内)。UI などを変化させて認識中であることをユーザーにわかるようにしてあげると良い。引数に string 型を1つとる。値は必ず "onBeginningOfSpeech" になる。タイミングをとるためだけのコールバック。省略可。

 コールバックは色々あって大変なのだが、特に重要なものは結果(resultCallbackMethod)とエラー(errorCallbackMethod)のコールバックだ。以下に例を載せておこう。

 例えば結果のコールバックメソッド(resultCallbackMethod)の名前を "OnResult" と名付けたとすると、以下のように書けば、認識された1つ1つの候補が列挙できる。

●音声認識された文字列を受信するコード
private void OnResult(string result)
{
string[] words = result.Split('\n');
foreach (var item in words)
{
Debug.Log(item); //各候補の文字列
}
}

 認識された音声は "候補1\n候補2\n候補3" のように改行区切り("\n") でヒエラルキーにある GameObject(callbackGameObject)にあるメソッド(resultCallbackMethod)の引数(string 型)として1つづきの文字列として送られてくる。メソッドの名前は任意だが、シグニチャが違っていると無視されてしまうので気をつけよう。

 ここでは foreach で認識された各候補を表示しているだけだが、ここであらかじめ作っておいた辞書などと照合して処理を分岐したり、プラグインの選択ダイアログを使ってユーザーに絞り込んで貰うのも良いだろう。

 次にエラー時のコールバックメソッド(errorCallbackMethod)の名前を "OnError" と名付けたとすると、以下のように書けば、エラーでの分岐ができる。

●音声認識で失敗したときのエラーを受信するコード
private void OnError(string errmes)
{
switch (errmes) {
case "ERROR_NO_MATCH":
Debug.Log("認識失敗");
break;
case "ERROR_SPEECH_TIMEOUT":
Debug.Log("タイムアウト");
break;
case "ERROR_NETWORK":
Debug.Log("ネットワークに繋がらない");
break;
case "ERROR_AUDIO":
Debug.Log("録音パーミッションがない");
break;
・・・(略)・・・
}
}

 引数で返ってくる値はエラーコードの文字列となる。エラーコードは公式のデベロッパーサイトも参照して欲しいが主に以下のものが出ると考えて良いだろう。

●音声認識でよく出るエラー
ERROR_NO_MATCH音声認識できなかったときに出るエラー。1音のような短いときや、声量が小さすぎるとき、周りの騒音が邪魔で聴き取れないときなどに出やすい。
ERROR_SPEECH_TIMEOUT音声認識が開始→待機中に時間切れしたときに出るエラー。周りの騒音が邪魔で聴き取れないときなどにも出ることがある。
ERROR_NETWORK認識された語句をネットワーク上のデータベースと照合する際に接続できなかったときのエラー。他のアプリがネットワークを専有してたり、何からの理由でネットワークがブロックされているときにも出る。
ERROR_AUDIOマニフェストファイル(AndroidManifest.xml)に録音パーミッション("RECORD_AUDIO")が無いときに出るエラー。パーミッションタグを挿入して再ビルドするしかない。

 他のエラーは以下を参照。
SpeechRecognizer

 その他には音声認識の起動のコールバック(readyCallbackMethod)、声の取得開始(beginCallbackMethod)があるが、それぞれ必ず "onReadyForSpeech", "onBeginningOfSpeech" の文字列が返る。これらはタイミングをとるためのコールバックなので、ここで UI を変化させたり、アニメーションを開始したりすると良いだろう。

 これらのサンプルコードは「SpeechRecognizerTest.cs」の「StartSpeechRecognizer()」「OnReady」「OnBegin」「OnResult」「OnError」とほぼ同じだ。コピペして中身だけ入れ替えれば簡単に利用できるだろう。

 もう1つ、中断する方法を書いておこう、これはリリース(オブジェクト解放)と同じものになる。未確認だが、この中断の挙動が実機の機種によって微妙に違うという話を見たので、使う際は気をつけた方が良いかも知れない。基本的にこの音声認識は放っておいても認識失敗("ERROR_NO_MATCH")かタイムアウト("ERROR_SPEECH_TIMEOUT")で停止するので、必要ないなら中断機能を付けないのも手だ。ともあれ、とりえあず例を載せておこう。といっても音声認識のオブジェクトをリリースするだけだ。

●音声認識を中断・リリースする
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.ReleaseSpeechRecognizer();
#endif

 内部的なコード(Java)には「SpeechRecognizer.destroy()」を使っている。他にも「SpeechRecognizer.cancel()」とか「SpeechRecognizer.stopListening()」も試してみたが、なぜか私の環境(Galaxy S7 Edge)では上手く行かなかった。この辺りが「停止は機種によって微妙に挙動が違う」と言われる所以なのかも知れない。なので確実に停止させるためには、オブジェクトをリリースするのが一番と考えてこの方法のみを実装してある。

 中断のサンプルは「SpeechRecognizerTest.cs」の「StopSpeechRecognizer()」になるが、同時に UI を止めているくらいで、それほど見る必要もないかも知れない。



■ユニティちゃんと音声認識でじゃんけん(Android 版)

 せっかくなので、このプラグインを使って音声認識でじゃんけんゲームを作ってみた。音声認識の箇所はパッケージに入っている「Assets/_Test/Scripts/SpeechRecognizerTest.cs」をほぼそのまま使っている。具体的には、受け取った結果は改行("\n")で連結されてくるのでそれを分割し、それらの最初の1文字でグー、チョキ、パーを判定する処理(いくつか候補をデータ化してある)を追加しただけだ。

(※) Unity 2017.1.1f1 / Windows10(x64) でビルド。Galaxy S7 Edge (Android 7.0) で確認。

デモアプリのダウンロード (Google Drive を利用)


Android 4.2以上
※「提供元不明アプリのインストール」許可が必要です。


 じゃんけん自体のアルゴリズム・作成方法を知りたければ以下の書籍を参考にすると良いだろう。アイコンがそっくりなのは、実際にこの本を以前読んでいたためである(笑)(※アプリ内のアイコンは新たに作ったものです)。また音声認識は以下の本も参考にしている(※ただし少し古い。実際のビルドは AndroidStudio 2.3.3 でやった)。なのでこのサンプルは2つをミックスしただけとも言える(笑)。

(じゃんけん画像素材)
LiveMaker 指南番

(じゃんけんゲーム/音声認識 参考)



※この記事のUnityアセットはプラグインとして配布されています。


※とりあえず試してみたい方は、最新版をビルドした apk デモをダウンロードできます。動作確認にもどうぞ。

プラグインデモをダウンロード
(Google Drive を利用)


Android 4.2以上
※「提供元不明アプリのインストール」許可が必要です。


(関連記事)
【Android】【Java】音声入力(音声認識)で文字列を取得する
【Unity】Androidのトーストやダイアログ、通知、音声認識、ハード音量操作など基本的な機能を使えるプラグインを作ってみた
【Unity】Androidのテキスト読み上げ(TextToSpeech)を使う
【Unity】Androidでカスタマイズしたダイアログを動的生成できるプラグインを作ってみた
【Unity】Androidでスライダーで設定を変更するダイアログを使う
【Unity】Androidでスイッチで設定を変更するダイアログを使う
【Unity】Androidの選択ダイアログを使う
【Unity】Androidで日付・時刻選択ダイアログ(DatePicker, TimePicker)を使う
【Unity】Androidで数値・半角英数・パスワード入力ダイアログを使う
【Unity】Androidでテキスト入力ダイアログを使う


このコンテンツの一部には『ユニティちゃんライセンス』で許諾されたアセットが使用されています。
Portions of this work are licensed under Unity-Chan License


関連記事
スポンサーサイト



category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityライブラリ  Unityプラグイン  FantomPlugin  音声認識  ユニティちゃん 
tb: 0   cm: --

【Unity】Androidのトーストやダイアログ、通知、音声認識、ハード音量操作など基本的な機能を使えるプラグインを作ってみた  


 元々は GearVR のように、Cardboard/ハコスコVR でも BlueToothコントローラ を使って手元で音量操作できたら便利だろうな~って思って色々試してたんだけど、そのついでにAndroidに標準で備わっているトースト(Toast)やダイアログ(AlertDialog)、通知(Notification)、音声認識(SpeechRecognizer)なども使える簡単なプラグインを作ってみた。単純な機能しかないが、ブラウザなどでURL先を開く機能なども付けておいたので、アプリ内に書ききれない説明ページやサポートページなどのHPを開くボタンなどを作るのも良いだろう。簡単なものだがパッケージにはサンプルも付けておいたので、コピペするなり改造するなりして自由に使って欲しい。

※AssetStore版 FantomPluginのセットアップはこちら

>>プラグイン&サンプルをダウンロード
(Google Drive を利用)

>>機能一覧のキャプチャ

※基本的にアセットストアのものとコードは同じになりますが、
アセットストア版は審査のためリリースが少し遅れるのと、規定上英語でのコメントが中心になります。


※とりあえず試してみたい方には、最新版をビルドした apk デモをダウンロードできます。動作確認にもどうぞ。

(Google Drive を利用)


Android 4.2以上(5.0以上推奨)
※「提供元不明アプリのインストール」許可が必要です。

※CPU モニタデモは Android 8.0 以降では動作しません(OS の仕様変更でステータス取得できなくなった)
※Android11 以降では音声認識(SpeechRecognizer)
テキスト読み上げ(Text-to-speech)はパーミッションが必要になったようです。


■プラグインのセットアップ(GoogleDrive 版)
■プラグインのセットアップ(AssetStore 版)
■トーストを使う(Toast)
■Yes/No ダイアログを使う(AlertDialog)
■OK ダイアログを使う(AlertDialog)
■チェックボックス付き Yes/No ダイアログを使う
■チェックボックス付き OK ダイアログを使う
■単一選択ダイアログ①を使う(AlertDialog) [確認ボタン無し]
■単一選択ダイアログ②を使う(AlertDialog) [確認ボタン有り]
■複数選択ダイアログを使う(AlertDialog)
■単一行テキスト入力ダイアログを使う(AlertDialog)
■複数行テキスト入力ダイアログを使う(AlertDialog)
■数値入力のテキストダイアログを使う(AlertDialog)
■半角英数入力のテキストダイアログを使う(AlertDialog)
■パスワード入力のテキストダイアログを使う(AlertDialog)
■日付選択ダイアログを使う(DataPickerDialog)
■時刻選択ダイアログを使う(TimePickerDialog)
■スイッチダイアログを使う
■スライダーダイアログを使う
■カスタムダイアログを使う
■通知を使う(Notification) [タッチでアプリに戻る]
■通知を使う(Notification) [タッチでURLを開く]
■URLを開く [任意のアクション]
■音声認識のダイアログを使う(SpeechRecognizer)
■音声認識をダイアログなしで使う(SpeechRecognizer)
■テキスト読み上げ機能を使う(TextToSpeech)
■ハードウェア音量の取得・設定など [メディア音量のみ]
■ハードウェア音量操作のイベントを取得する [メディア音量のみ]
■ハードウェア音量キーの無効化をする
■ピンチ操作の取得
■スワイプ(フリック)操作の取得
■長押し(ロングタップ)操作の取得
■ゼンサーを使う(歩数計・心拍数など)
■Android ビルドをもう少し詳しく
 ●パーミッションの設定
 ●センサー利用時のフィルタリング(Google Play)
 ●画面回転の設定
■Firebase のプッシュ通知と FantomPlugin の共存(Firebase と他のプラグインの共存方法)
■更新履歴
■ユニティちゃんと音声認識でじゃんけん(Android 版デモ)
■ユニティちゃんがアキバ上空を飛ぶ!(SmoothFollow3 デモ)

(※) Unity 5.6.3p1 - 2018.4.8f1 / AndroidStudio 2.3.3 - 3.1.3 / Windows10(x64) / Galaxy S7 Edge (Android 7.0/8.0) で確認



■プラグインのセットアップ

 まずはアーカイブを解凍したら、「FantomPluginAndroid.unitypackage」をプロジェクトにインポートしよう。もちろん機能を使うには「Build Settings..」を「Andrdoid」にする必要があるが、どのみちエディタ上では動作確認はできないので、最終的にはビルドして実機で確認する必要がある。


 プラグインの実体は「Assets/Plugins/Android/」にある「fantomPlugin.aar」になる。プラグインは「Minimum API Level:Android 4.2 (API 17) 」で作られているので、ビルドする際には API17 以上に設定して欲しい。


 また、同じフォルダに複数の「AndroidManifest-~.xml」があるが、これは使いたい機能や画面の回転方向("_Landscape"または"_Portrait")、テーマ("_API17"または"_API21")などの設定テンプレで、ビルドする際に適切なものを選んで「AndroidManifest.xml」にリネームして使って欲しい。例えば、「ハードウェア音量のイベント取得」には "-HardVolKey" が付いたものを、「音声認識のダイアログ」を使うには "-Speech" が付いたものを使う必要がある。これら機能を利用するには元のアクティビティ「UnityPlayerActivity」をオーバーライドした、「HardVolKeyOnUnityPlayerActivity」(ハードウェア音量イベント取得用アクティビティ:プラグイン内に入っている)、「ReceiveResultsOnUnityPlayerActivity」(音声認識ダイアログ結果取得用アクティビティ:プラグイン内に入っている)を使う必要があるので、それらを指定したマニフェストファイルとなっている。また、両方使いたい場合は "-FullPlugin" の付いたもの(プラグイン内に入っている)を使えば良い(「FullPluginOnUnityPlayerActivity」にはプラグイン機能のすべてが入っている)。これらマニフェストファイルは手動で書き換えても構わない(※ただし音声認識を使う場合は、録音パーミッション「RECORD_AUDIO」も必要)。

(参考)UnityPlayerActivity Java コードの拡張

 なお、"_API17"または"_API21"の名前は使えるテーマの API Level で分類されているが、これは主に「Theme.DeviceDefault.Light.NoActionBar.Fullscreen」(API17から)、「Theme.Material.Light.NoActionBar.Fullscreen」(API21から)というだけで内容は同じだ。元の「UnityPlayerActivity」をオーバーライドして起動すると、Unityが完全に起動するまでにアクションバーなどが表示されることがあるので、それを回避するために使っているものだ。これらはダイアログにも適用されるので注意しよう(※ダイアログごとに設定することはできる)。任意に変更しても構わない。ちなみに".Light"が付いているテーマは白系ベースで、付いてないものは黒系ベースとなる。テーマの名前のアンダバー("_")をドット(".")に変更したものを指定する。

(参考)R.Style.Theme

 あと、サンプルデモをビルドするには「AndroidManifest_test.xml」をリネームして「AndroidManifest.xml」にすれば全機能使える(※"-FullPlugin" と内容的には同じ)。「BuildSettings...」に「Assets/_Test/Scenes/」にあるシーンを追加してビルドするのも忘れずに。


(※) ビルドすると警告「Unable to find unity activity in manifest. You need to make sure orientation attribute is set to sensorPortrait manually.」が出るが、独自の「AndroidManifest.xml」(UnityPlayerActivity以外のもの)を使うと出るものなので気にしなくて良い(orientation=画面回転はUnity側のアプリの設定に合わせた方が良い)。
(※) Unity2018 でビルド中にエラー「CommandInvokationFailure: Gradle build failed.~Cannot read packageName~」が出たときは以下の記事を参照して下さい。
【Unity】Unity2018 でビルドエラー「CommandInvokationFailure: Gradle build failed.」が出る

 以下には各機能の使用する際の簡単なC#コードと解説、プラグインとして作った元のJavaコードの一部(簡略化したもの)を書いておこう。簡易説明書のように使って欲しい。JavaでAndroidのアプリを作ったことがあるなら、対応するパラメタを見た方が理解しやすく応用範囲も広いものになるだろう。



■トーストを使う(Toast)


●Unity から Android の Toast を使う C# コード
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.ShowToast(message);
#endif

●プラグイン内の対応する Java コード
import android.content.Context;
import android.widget.Toast;

Toast.makeText(context, message, duration).show();

 トースト(Toast)は画面の下の方に出る、短い時間表示されるメッセージである。

 C# 側の引数はメッセージ文字列(message)と表示長さのフラグ(longDuration)となっている。長さはJava 側で「LENGTH_SHORT」「LENGTH_LONG」しかないので、フラグで置き換えている。context は起動アクティビティのことを指していて、AndroidPlugin のメソッド内で自動取得されるので必要ない。

 サンプルコードは「Assets/_Test/Scripts/PluginTest.cs」の「ShowToast()」「TestToast()」あたりを見て欲しい。



■ダイアログを使う(AlertDialog) [Yes/No 2択]


●Unity から Android の AlertDialog を使う C# コード(Yes/No ダイアログ)
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.ShowDialog(title, message, callbackGameObject, callbackMethod, yesCaption, yesValue, noCaption, noValue, style);
#endif

●プラグイン内の対応する Java コード
import android.app.AlertDialog;
import android.content.DialogInterface;
import static com.unity3d.player.UnityPlayer.UnitySendMessage;

DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which) {
switch(which) {
case DialogInterface.BUTTON_POSITIVE:
UnitySendMessage(callbackGameObject, callbackMethod, yesValue);
break;
case DialogInterface.BUTTON_NEGATIVE:
UnitySendMessage(callbackGameObject, callbackMethod, noValue);
break;
}
}
};

AlertDialog.Builder builder = new AlertDialog.Builder(context, styleId);

builder.setTitle(title)
.setMessage(message)
.setPositiveButton(yesCaption, listener)
.setNegativeButton(noCaption, listener)
.show();

 これは「はい/いいえ」の2択のダイアログ(AlertDialog)である。戻値は「はい」のとき「yesValue」、「いいえ」のとき「noValue」がヒエラルキーにある GameObject 名(callbackGameObject)のメソッド(callbackMethod)に文字列で返ってくる。また Andrdoid のダイアログの場合、範囲外をクリックするとダイアログが消えるが、その場合は何も返って来ない。つまり実質3択のようになる(「はい/いいえ/あとで」→「Yes/No/(なし)」みたいな)。コールバックするメソッドのシグネチャは文字列型(string)固定になる(というより基本的にネイティブ間のメッセージやりとりは全て文字列型と考えて良い→受け取り側で適切に変換して使う)。

 ダイアログにはスタイル(テーマ)を当てられるようにしてある。省略=空文字("")のときはアクティビティのテーマと同じものになる。スタイルの引数は "android:Theme.DeviceDefault.Dialog.Alert" のように、名前のアンダバー("_")をドット(".")に変えたものを指定する。端末の API Level によって使えるものとそうでないものがあるので、アプリのビルドの API Level に合わせて指定する必要があるので注意。

(参考)R.style.theme

 サンプルコードは「Assets/_Test/Scripts/PluginTest.cs」の「TestDialogYesNo()」あたりを見て欲しい。



■ダイアログを使う(AlertDialog) [OK のみ]


●Unity から Android の AlertDialog を使う C# コード(OK ダイアログ)
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.ShowDialog(title, message, callbackGameObject, callbackMethod, okCaption, resultValue, style);
#endif

●プラグイン内の対応する Java コード
import android.app.AlertDialog;
import android.content.DialogInterface;
import static com.unity3d.player.UnityPlayer.UnitySendMessage;

DialogInterface.OnDismissListener listener = new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
UnitySendMessage(callbackGameObject, callbackMethod, resultValue);
}
};

AlertDialog.Builder builder = new AlertDialog.Builder(context, styleId);

builder.setTitle(title)
.setMessage(message)
.setPositiveButton(okCcaption, null)
.setOnDismissListener(listener)
.show();

 これは注意喚起を促すだけの「OK」のみのダイアログ(AlertDialog)である。戻値は必ず「resultValue」がヒエラルキーにある GameObject 名(callbackGameObject)のメソッド(callbackMethod)に文字列で返ってくる。また Andrdoid のダイアログの場合、範囲外をクリックするとダイアログが消えるが、その場合も「resultValue」が返ってくる。つまりダイアログが閉じられたタイミングを受け取るだけの値となる。コールバックするメソッドのシグネチャは文字列型(string)固定になる(というより基本的にネイティブ間のメッセージやりとりは全て文字列型と考えて良い→受け取り側で適切に変換して使う)。

 ダイアログにはスタイル(テーマ)を当てられるようにしてある。省略=空文字("")のときはアクティビティのテーマと同じものになる。スタイルの引数は "android:Theme.DeviceDefault.Dialog.Alert" のように、名前のアンダバー("_")をドット(".")に変えたものを指定する。端末の API Level によって使えるものとそうでないものがあるので、アプリのビルドの API Level に合わせて指定する必要があるので注意。

(参考)R.style.theme

 サンプルコードは「Assets/_Test/Scripts/PluginTest.cs」の「TestDialogOK()」あたりを見て欲しい。



■通知を使う(Notification) [タッチでアプリに戻る(起動してないときは起動する)]


●Unity から Android の Notification を使う C# コード(タッチでアプリに戻る(起動してないときは起動する))
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.ShowNotification(title, message, iconName, tag, showTimestamp);
#endif

●プラグイン内の対応する Java コード
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;

Intent intent = new Intent(context, context.getClass());
PendingIntent pendingIntent = PendingIntent.getActivities(context, 0, new Intent[]{intent}, 0);

Notification notif = new Notification.Builder(context)
.setContentTitle(title)
.setContentText(message)
.setSmallIcon(iconId)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setWhen(System.currentTimeMillis())
.setShowWhen(true)
.build();

NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(tag, 0, notif);

 これは注意喚起を促すだけの通知(Notification)である。タッチでアプリに戻るようにしてある(起動してないときは起動する)。

 Unity の場合、自分でマニフェストファイルを書き換えない限りはアイコン名(iconName)は "app_icon" が使われる。タグは複数回通知したとき、同じタグを持つものは上書きされる(つまり最新のものだけ表示する)というものである。通知時刻は showTimestamp をオフにすれば消すことができる。デフォルトはオンになる。

 サンプルコードは「Assets/_Test/Scripts/PluginTest.cs」の「TestNotification()」あたりを見て欲しい。



■通知を使う(Notification) [タッチでURLを開く]


●Unity から Android の Notification を使う C# コード(タッチでURLを開く)
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.ShowNotificationToOpenURL(title, message, url, tag, showTimestamp);
#endif

●プラグイン内の対応する Java コード
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;

Intent intent = new Intent(action, Uri.parse(url));
PendingIntent pendingIntent = PendingIntent.getActivities(context, 0, new Intent[]{intent}, 0);

Notification notif = new Notification.Builder(context)
.setContentTitle(title)
.setContentText(message)
.setSmallIcon(iconId)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setWhen(System.currentTimeMillis())
.setShowWhen(true)
.build();

NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(tag, 0, notif);

 これはタッチをすると指定したURLを開く(起動アプリは端末による)通知(Notification)である。AndroidPlugin.ShowNotificationToActionURI() でアクションをURLを開くこと専用にしたものでもある。Java コードの引数の「action」が「android.intent.action.VIEW」のときURLを渡すとブラウザ等で開くことになる(※端末のデフォルトアプリの設定による)。タッチによる動作以外は「通知でアプリに戻る」と変わらない。

 AndroidPlugin.ShowNotificationToActionURI() でアクションと URI を組み合わせて使う分には他の使い方もできるかも知れない。アクションについては以下を参照して欲しい(Constant Value を使う)。

(参考)Intent.ACTION~

 サンプルコードは「Assets/_Test/Scripts/PluginTest.cs」の「TestNotification()」あたりを見て欲しい。



■URLを開く [任意のアクション]


●Unity から Android 端末でURLを開く
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.StartOpenURL(url);
#endif

●プラグイン内の対応する Java コード
import android.app.Activity;
import android.content.Context;
import android.content.Intent;

Intent intent = new Intent(action, Uri.parse(url));
startActivity(intent);

 これは直接 URL を開くアクションをするメソッドである。「通知からURLを開く」と動作は変わらないが、Unity のボタンでも画像でも好きなUIなどに付けて使うものとして作ってみた。AndroidPlugin.StartActionURI() でURLを開くこと専用にしたものでもある(引数の「action」が「android.intent.action.VIEW」になっている)。

 AndroidPlugin.StartActionURI() でアクションと URI を組み合わせて使う分には他の使い方もできるかも知れない。アクションについては以下を参照して欲しい(Constant Value を使う)。

(参考)Intent.ACTION~

 サンプルコードは「Assets/_Test/Scripts/PluginTest.cs」の「TestOpenURL()」あたりを見て欲しい。



■音声認識のダイアログを使う(SpeechRecognizer)

※Android11 以降では音声認識(SpeechRecognizer)にパーミッションが必要になったようです。


●Unity から Android の SpeechRecognizer を使う C# コード(ダイアログを表示して取得)
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.ShowSpeechRecognizer(callbackGameObject, resultCallbackMethod, message);
#endif

●プラグイン内の対応する Java コード
//音声入力ダイアログ表示
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.content.Intent;

Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, message);
startActivityForResult(intent, 0);


//認識された文字列の受信とコールバック
import android.speech.RecognizerIntent;
import android.content.Intent;
import java.util.List;
import static com.unity3d.player.UnityPlayer.UnitySendMessage;

public class ReceiveResultsOnUnityPlayerActivity extends UnityPlayerActivity {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (data.hasExtra(RecognizerIntent.EXTRA_RESULTS)) {
List results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);

String str = "";
for (String s : results) {
if (str.length() > 0)
str += "\n";
str += s;
}

UnitySendMessage(callbackGameObject, resultCallbackMethod, str);
}
}
}
}

 これは音声入力のダイアログを表示して、認識できた文字列を受信→Unity へコールバックするやり方である。認識できた文字列またはエラーはヒエラルキーにある GameObject 名(callbackGameObject)のメソッド(resultCallbackMethod)に文字列で返ってくる。認識された文字列は改行("\n")区切りで結合されて、Unity 側へコールバックメソッドの引数で返される。1つずつ取り出すには String.Split() などを使って分割すれば良い(基本的にネイティブ間のメッセージやりとりは全て文字列型と考えて良い→受け取り側で適切に処理して使う)。

 この結果受信の実装は「ReceiveResultsOnUnityPlayerActivity」に書かれていて、元の「UnityPlayerActivity」(デフォルトでAndroidビルドに使用されているアクティビティ)をオーバーライドして使う必要がある(マニフェストファイルの「-Speech」が付いているものに設定されている)

 結果受信の実装方法などは別ページにまとめておいたので、必要あればそちらも参照。
ダイアログを使用した音声認識の利用方法

 サンプルコードは「Assets/_Test/Scripts/SpeechRecognizerTest.cs」の「ShowSpeechRecognizer()」「ResultSpeechRecognizer()」あたりを見て欲しい。

(音声認識 参考)




■音声認識をダイアログなしで使う(SpeechRecognizer)

※Android11 以降では音声認識(SpeechRecognizer)にパーミッションが必要になったようです。


●Unity から Android の SpeechRecognizer ダイアログなしで使う C# コード(イベントを取得して自前で処理する)
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
AndroidPlugin.StartSpeechRecognizer(callbackGameObject, resultCallbackMethod, errorCallbackMethod,
readyCallbackMethod, beginCallbackMethod);
#endif

●プラグイン内の対応する Java コード
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.content.Intent;

Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, context.getPackageName());

SpeechRecognizer recognizer = SpeechRecognizer.createSpeechRecognizer(context);
recognizer.setRecognitionListener(new RecognitionListener() {
@Override
public void onReadyForSpeech(Bundle params) {
UnitySendMessage(callbackGameObject, readyCallbackMethod, "onReadyForSpeech");
}

@Override
public void onBeginningOfSpeech() {
UnitySendMessage(callbackGameObject, beginCallbackMethod, "onBeginningOfSpeech");
}

@Override
public void onError(int error) {
UnitySendMessage(callbackGameObject, errorCallbackMethod, String.valueOf(error));
}

@Override
public void onResults(Bundle results) {
List list = results.getStringArrayList(android.speech.SpeechRecognizer.RESULTS_RECOGNITION);

String str = "";
for (String s : list) {
if (str.length() > 0)
str += "\n";
str += s;
}

UnitySendMessage(callbackGameObject, resultCallbackMethod, str);
}

//・・・(略)・・・
});

recognizer.startListening(intent);

 これは音声入力のダイアログは表示しないで、待機イベント(onReadyForSpeech()→readyCallbackMethod)、入力開始イベント(onBeginningOfSpeech()→beginCallbackMethod)、認識結果イベント(onResults()→resultCallbackMethod)またはエラー(onError()→errorCallbackMethod)のイベントをこの順にコールバックするやり方である。それぞれのイベントで Unity 側でアニメーションしたり、状態表示をすれば良い。なお、待機イベント(onReadyForSpeech)は必ず文字列 "onReadyForSpeech" を、認識開始イベント(onBeginningOfSpeech) は "onBeginningOfSpeech" を返す。これはタイミングを知るためだけのイベントであり、省略しても構わない(結果とエラーだけでも使うことはできる)。

 認識された文字列は改行("\n")区切りで結合されて、Unity 側へコールバックメソッドの引数で返される。この場合はヒエラルキーにある GameObject 名(callbackGameObject)の結果受信メソッド(resultCallbackMethod)またはエラー受信メソッド(errorCallbackMethod)に引数の文字列で返ってくる。1つずつ取り出すには String.Split() などを使って分割すれば良い(基本的にネイティブ間のメッセージやりとりは全て文字列型と考えて良い→受け取り側で適切に処理して使う)。

 コールバックの実装方法などは別ページにまとめておいたので、必要あればそちらも参照。
コールバックを実装した音声認識の利用方法

 サンプルコードは「Assets/_Test/Scripts/SpeechRecognizerTest.cs」の「StartSpeechRecognizer()」「OnReady()」「OnBegin()」「OnResult()」「OnError()」あたりを見て欲しい。

(音声認識 参考)




■ハードウェア音量の取得・設定など [メディア音量のみ]


●Unity から Android のハードウェア音量を取得・設定する(メディア音量のみ)
using FantomLib;

#if UNITY_ANDROID && !UNITY_EDITOR
int max = AndroidPlugin.GetMediaMaxVolume(); //最大音量の取得
int vol = AndroidPlugin.GetMediaVolume(); //現在音量の取得
vol = AndroidPlugin.AddMediaVolume(1, showUI); //現在の音量+1
vol = AndroidPlugin.AddMediaVolume(-1, showUI); //現在の音量-1
vol = AndroidPlugin.SetMediaVolume(0, showUI); //ミュート:音量=0
#endif

●プラグイン内の対応する Java コード
import android.media.AudioManager;

//現在音量の取得
AudioManager audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
return audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);

//現在音量の設定
AudioManager audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, showUI ? AudioManager.FLAG_SHOW_UI : 0);

 これは端末のハードウェア音量(メディア音量のみ)を操作するメソッドである。BlueToothコントローラなどでも音量操作できるものは多いので、Cardboard/ハコスコVRアプリなどに実装すると便利かも知れない(Cardboard アプリを Unity5.6.3p1 以前でビルドした場合ハードウェア音量キーが無効になるので。Unity5.6.3p2 以降だとハードウェア音量キーが効く→UIが出る)。

 引数の showUI は音量操作をしたとき、端末上のUIを表示するか否かのフラグである。VRアプリでは非表示にして自前でUIを実装した方が良いだろう(端末のUIは2眼にはならないので)。元々そのために作ったものである(笑)。

 またちょっとしたことだが、ネイティブ呼び出しは非常に負荷が高い動作なので、最大音量(GetMediaMaxVolume())など通常途中で変わらないものは、値をキャッシュして利用する仕組みなどを作った方が良いだろう。こういう手法を常にやるクセを付けておくと高速な処理が書けるようになる(※ただしネイティブ関連のオブジェクトはアプリが落ちたときのことを考慮して、あまりキャッシュしない方が良いかも知れない。またある程度JNIが高速化してくれているらしい。マニュアル参照)。

(参考)Unity で Java プラグインを 使用する上でのヒント

 同梱されているハードウェア音量操作をするプレファブとスクリプト「HardVolumeController」の詳細は以下の記事にまとめて置いたので、必要あればそちらも参照して欲しい。

【Unity】Androidのハードウェア音量操作・ハードウェアキーの無効化をする

 サンプルコードは「Assets/FantomLib/Scripts/Module/HardVolumeController.cs」の「VolumeUp()」「VolumeDown()」「VolumeMute()」「VolumeNow()」「volume プロパティ」「maxVolume プロパティ」あたりを見て欲しい。またプレファブ「Assets/FantomLib/Prefabs/System/HardVolumeControllerWithToast」にはトースト(Toast)で操作したときの音量を表示できるようにセットアップしてある(デモに使っているものと同じ)。少し改造すればVRにも応用できるだろう。



■ハードウェア音量操作のイベントを取得する [メディア音量のみ]


●Unity で Android のハードウェア音量操作のイベントを取得する(メディア音量のみ)
using FantomLib;

void OnEnable()
{
#if UNITY_ANDROID && !UNITY_EDITOR
//ハードウェア音量キーのリスナー登録
AndroidPlugin.HardKey.SetKeyVolumeUpListener(gameObject.name, "HardVolumeKeyChange", "VolumeUp");
AndroidPlugin.HardKey.SetKeyVolumeDownListener(gameObject.name, "HardVolumeKeyChange", "VolumeDown");
#endif
}

void OnDisable()
{
#if UNITY_ANDROID && !UNITY_EDITOR
//ハードウェア音量キーの全リスナー解除
AndroidPlugin.HardKey.RemoveAllListeners();
#endif
}

//ハードウェア音量キーのイベントハンドラ(Android ネイティブから呼ばれる)
void HardVolumeKeyChange(string message)
{
if (message == "VolumeUp")
{
if (OnHardVolumeKeyUp != null)
OnHardVolumeKeyUp.Invoke();
}
else if (message == "VolumeDown")
{
if (OnHardVolumeKeyDown != null)
OnHardVolumeKeyDown.Invoke();
}
}

●プラグイン内の対応する Java コード
import android.view.KeyEvent;
import com.unity3d.player.UnityPlayerActivity;
import static com.unity3d.player.UnityPlayer.UnitySendMessage;

public class HardVolKeyOnUnityPlayerActivity extends UnityPlayerActivity {
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_VOLUME_UP: //音量大キー
UnitySendMessage(callbackGameObjectUp, callbackMethodUp, returnValueUp);
break;
case KeyEvent.KEYCODE_VOLUME_DOWN: //音量小キー
UnitySendMessage(callbackGameObjectDown, callbackMethodDown, returnValueDown);
break;
}
return super.onKeyDown(keyCode, event);
}
}

 これは端末のハードウェア音量(メディア音量のみ)を操作したとき、Android → Unity へイベントメッセージを送るためのリスナー登録メソッドである。このリスナーの実装は「HardVolKeyOnUnityPlayerActivity」に書かれていて、簡単に言えばアクティビティのUIスレッドからイベントを検知したら Unity へ知らせるだけのものである。そのために元の「UnityPlayerActivity」(デフォルトでAndroidビルドで使用されている)をオーバーライドして使う必要がある(マニフェストファイルの「-HardVolKey」が付いているものに設定されている)

 受け取ったイベントは Unity 側で更に「OnHardVolumeKeyUp」「OnHardVolumeKeyDown」でコールバックされるが、これはインスペクタで登録できるようにしてあるので、元々ハードウェア音量キーが有効なアプリでは表示するメソッド(VolumeNow() 等)を登録し、VR(Cardboard/ハコスコ)など元はハードウェアキーが無効になっているアプリでは音量増減メソッド(VolumeUp()/VolumeDown())を登録すれば良い(Unity5.6.3p1 以前でビルドした場合。Unity5.6.3p2 以降だとハードウェア音量キーが効く→UIが出る。※どうやらバグだったらしい。Unity5.6.3p2のリリースノートにFixされたとあった。しかしかえってUIが出るのは良くない(笑))。VRでは2眼になるので showUI はオフにして、自前でUIを実装した方が良いだろう。

 同梱されているハードウェア音量操作をするプレファブとスクリプト「HardVolumeController」の詳細は以下の記事にまとめて置いたので、必要あればそちらも参照して欲しい。

【Unity】Androidのハードウェア音量操作・ハードウェアキーの無効化をする

 サンプルコードは「Assets/FantomLib/Scripts/Module/HardVolumeController.cs」の「OnEnable()」「OnDisable()」「HardVolumeKeyChange()」あたりを見て欲しい。またプレファブ「Assets/FantomLib/Prefabs/System/HardVolumeControllerWithToast」にはトースト(Toast)で操作したときの音量を表示できるようにセットアップしてある(デモに使っているものと同じ)。少し改造すればVR(Cardboard/ハコスコ)にも応用できるだろう(→「UnityChan Flyer」と「SapphiartChan Live Show!」の音量操作にはこのプラグインを使って uGUI で実装している)。

(実際に動作確認した機器)





■更新履歴

17/10/01(新規リリース)
トースト(Toast)
Yes/Noダイアログ(AlertDialog)
OKダイアログ(AlertDialog)
通知(Notification)
任意のURIに対するアクション
音声認識(SpeechRecognizer)
ハードウェア音量操作
17/10/28(機能追加・一部修正)
・[追加]選択ダイアログ(単一/複数:AlertDialog/SingleChoice/MultiChoice)
・[追加]テキスト読み上げ(TextToSpeech)
・[修正]音声認識の戻り値の区切り文字(改行("\n"))が最後に付かないようにした(Split('\n')で分割しやすくするため)。
17/11/03(機能追加)
・[追加]テキスト入力ダイアログ(単一行/複数行)
17/11/06(機能追加)
・[追加]選択ダイアログ(単一/複数:AlertDialog/SingleChoice/MultiChoice)の各アイテムごとに戻り値を指定できるオーバーロードを追加。
17/11/10(機能追加・一部修正)
・[追加]数値/半角英数/パスワード入力のテキストダイアログを追加。
・[追加]テキスト入力ダイアログ(単一行/複数行)にメッセージを入れるオーバーロードを追加。
・[修正]テキスト入力ダイアログ(単一行/複数行)の初期値にも文字数制限がかかるように修正。
・[修正]テキスト入力ダイアログ(単一行/複数行)が表示されたときに全選択とソフトキーボードが出るようにした。
17/11/16(機能追加)
・[追加]日付/時刻選択ダイアログを追加。
・[追加]チェックボックス付きのダイアログ(Yes/No, OK)を追加。
・[追加]Android の色形式(int値:ARGB)と Unity の Color 形式の相互変換「XColor」クラスをライブラリとして追加。
17/11/22(機能追加)
・[追加]スイッチダイアログを追加。
・[追加]スライダーダイアログを追加。
・[追加]真偽値、オブジェクト(クラス・構造体)、配列、リスト、辞書、キー&値ペアを保存する「XPlayerPrefs」クラスをライブラリとして追加。
17/12/03(機能追加)
・[追加]カスタムダイアログを追加。
・[追加]パラメタを簡単に扱うための辞書ラッパー「Param」クラスをライブラリとして追加。
・[追加]ハードウェアキーによる端末自身での音量操作可否メソッド(SetVolumeOperation())を追加。
17/12/16(一部修正)
・[修正]XColor の RedValue(Color), GreenValue(Color), BlueValue(Color), AlphaValue(Color), ToIntARGB(Color) の処理を計算式に変更。
18/01/09(機能追加・一部修正) [アセットストア版:ver.1.1]
・[追加]ピンチスワイプ(フリック)長押し(ロングタップ)をライブラリとして追加(デモシーン: PinchSwipeTest も追加)。
・[追加]モバイル操作にも対応したカメラスクリプト(SmoothFollow3)をライブラリとして追加。
・[修正]XDebug(ランタイム時の Debug.Log 表示スクリプト)に行数制限機能を追加。
18/01/18(一部修正)
・[修正]複数選択ダイアログの初期値が無視されていた不具合を修正。
18/02/03(機能追加・一部修正) [アセットストア版:ver.1.2]
・[追加]おおよそ全ての機能のプレファブ&「~Controller」スクリプトを追加。
・[追加]単一選択(SingleChoiceDialog)複数選択(MultiChoiceDialog)スイッチダイアログ(SwitchDialog)カスタムダイアログのアイテムに値変化のコールバックを追加。
・[修正]XDebug の自動改行フラグ(newline)が無視されていた不具合を修正。また、行数制限を使用しているときに、OnDestory() でテキストのバッファ(Queue)をクリアするようにした。
18/02/15(機能追加) [アセットストア版:ver.1.3]
・[追加]WIFIのシステム設定を開く機能を追加。
・[追加]Bluetoothの接続要求(ダイアログ表示)をする機能を追加。
・[追加]アプリChooserを利用してテキストを送信する(簡易シェア)機能を追加。
・[追加]ストレージアクセスフレームワーク(API19以上)を利用して、テキストファイルの保存と読み込み機能を追加。
・[追加]ギャラリーアプリを起動して、画像ファイルのパスを取得する機能を追加(サンプルとしてテクスチャへのロードとスクリーンショットを追加)。
・[追加]ファイルパスをMediaScannerに登録(更新)する機能を追加。
18/02/19(機能追加・一部修正) [アセットストア版:ver.1.4]
・[追加]バイブレーター(振動)機能(StartVibrator())を追加。
・[追加]通知(Notification)にもバイブレーター(振動)機能のオーバーロードを追加。
・[修正]全ての拡張エディタスクリプトを「SerializedProperty」に置き換え(エディタ上で設定が保存されないことがあったので)。
18/02/25(機能追加) [アセットストア版:ver.1.5]
・[追加]バッテリーの温度、コンディション(オーバーヒート、良好、等)、残量、接続状態のステータス取得(リスニング)を追加。
18/03/16(機能追加) [アセットストア版:ver.1.6]
・[追加]デバイスの回転のイベント取得を追加。
・[追加]おおよそ全てのセンサーの値取得機能を追加(※センサーのサポート自体は端末のモデルに依ります)。
18/03/21(機能追加) [アセットストア版:ver.1.7]
・[追加]各システム設定画面を開くプレファブとデモを追加。
・[追加]AndroidActionControllerに「ActionType.ActionOnly」とアクションの入力支援機能を追加。
・[追加]MailerController, DialerController 等、専用のアクションコントローラをいくつか追加。
18/03/26(機能追加) [アセットストア版:ver.1.8]
・[追加]デバイス認証(指紋・パターン・PIN・パスワード等。ユーザーの設定による)の利用機能を追加。
・[追加]実行中デバイスの API Level(int型)の取得機能を追加。
18/04/04(機能追加・修正) [アセットストア版:ver.1.9]
・[追加]パーミッション付与のチェック(AndroidPlugin.CheckPermission(), ~Controller.IsPermissionGranted)機能を追加。
・[修正]いくつかの「~Controller」[*] に、起動時(Start())にサポートのチェック(IsSupported~)とパーミッションの付与チェック(IsPermissionGranted)を追加。不可のとき「OnError」コールバックにエラーメッセージを返すようにした。
18/04/08(機能追加) [アセットストア版:ver.1.10]
・[追加]QRコード(バーコード)スキャナを起動しテキストを取得する(ShowQRCodeScanner())機能を追加。
・[追加]センサー値の一般的な定数(SensorConstant)を追加。
18/04/10(機能追加・修正) [アセットストア版:ver.1.11]
・[追加]StartAction(), StartActionWithChooser(), StartActionURI() に複数パラメタオーバーロードを追加。AndroidActionController も複数パラメタ対応。
・[修正]MailerController を複数パラメタアクションに変更(より多くのメーラーが対応できるため)。
・[追加]マーケット(Google Play)検索機能を追加(MarketSearchController)。
・[追加]アプリのインストールチェック(IsExistApplication())、アプリ名(GetApplicationName())、アプリバージョン番号(GetVersionCode())、アプリバージョン名(GetVersionName())の取得機能を追加。
18/04/25(機能追加・修正) [アセットストア版:ver.1.13]
・[追加]テキスト送信(SendTextController)、メーラー送信(MailerController)に画像を添付する機能を追加。
・[追加]スクリーンショット部分のみデモから独立して、ライブラリ(Screenshot)として追加(※旧デモはそのまま)。
・[追加]LocalizeStringResource にアイテムの追加・削除、IDの重複・空のチェックのエディタツール(インスペクタ上)を追加。
・[追加]いくつかのコントローラの動的テキスト設定メソッド(.Show(),.Send() 等)に「LocalizeString」引数のオーバーロードを追加。
18/05/03(機能追加・修正) [アセットストア版:ver.1.13]
・[追加]ローカライズの言語変更機能(LocalizeLanguageChanger)を追加。
・[追加]音声認識(SpeechRecognizerController, SpeechRecognizeDialogrController)とテキスト読み上げ(TextToSpeechController)に言語ロケール指定機能を追加。
18/05/14(機能追加・修正) [アセットストア版:ver.1.14]
・[追加]単一選択ダイアログ、複数選択ダイアログ、スライダーダイアログ、スイッチダイアログ、カスタムダイアログにキャンセルコールバックを追加(SingleChoiceDailogController, MultiChoiceDialogController, SliderDialogController, SwitchDialogController, CustomDialogController)。
・[修正]音量スライダーダイアログ(VolumeSliderDialogController)でキャンセルボタンが押されたとき、音量が変更前に戻るように修正。
・[追加]カスタムダイアログのアイテム種類にチェックボックス(CheckItem)を追加。
・[追加]バッテリー情報に電圧を追加(BatteryInfo.voltage)。
・[修正]LocalizeString.FontSizeByLanguage() の言語検索を「システム言語→デフォルト言語」に修正(LocalizeString.TextByLanguage() と合わせるため)。
・[追加]LocalizeLanguageChanger にエディタ確認用の簡易言語表示切替機能を追加(.debugLanguage, .debugApplyOnStart)。
・[追加]UI等の等間隔整列ツール(ObjectArrangeTool)[補助ツール] を並べ替えリストに変更し、ドラッグ&ドロップや平行移動機能も追加。
18/05/29(機能追加・修正) [アセットストア版:ver.1.15]
・[追加]ギャラリーから動画情報(パス等)も取得できるように機能追加(GalleyPickController)。
・[追加]ImageInfo(画像情報取得用クラス)に「size」(ファイルサイズ)、「mimeType」(MIME Type)、「orientation」(画像回転角度) のフィールドを追加。
18/07/03(機能追加) [アセットストア版:ver.1.16]
・[追加]ストレージアクセス機能にて画像、音声、動画、それ以外のファイル、フォルダの情報を取得する機能を追加(StorageOpenImageController, StorageOpenAudioController, StorageOpenVideoController, StorageOpenFileController, StorageOpenFolderController)。
・[追加]ストレージアクセス機能にてファイル保存の機能を追加(StorageSaveFileController)。
・[追加]AndroidActionController に「UriWithMimeType」(MIME type指定でのURIへのアクション)を追加。サンプルとして ExternalStorageTest に様々なファイルを開くデモを追加。
・[追加]簡易的な音楽プレイヤーのサンプルスクリプト(EasyMusicPlayer)とシーン(MusicPlayerExample)を追加。
18/07/16(機能追加・修正) [アセットストア版:ver.1.17]
・[追加]パーミッションのリクエスト(+その根拠のダイアログの表示)をする機能を追加。「PermissionCheckController」に「requestWhenNotGranted」オプションを追加。
・[修正]センサーコントローラのベーススクリプト「SensorControllerBase」でセンサーのサポートチェック機能をリアルタイム(キャッシュなし)に変更。
18/08/23(機能追加・修正)[アセットストア版:ver.1.18]
・[追加]CPU使用率のステータス取得機能を追加(CpuRateController)。またそのCPU使用率をバーとして表示するスクリプト「CpuRateBar」(単一CPU)と一覧で表示する「CpuRateBarView」(複数CPU)を追加。
・[追加]UI-Text 上で FPS(Frame Per Second)を表示するスクリプト「FpsText.cs」を追加。またそのプレファブ「FpsMonitor」を追加。
・[追加]球・箱・線・メッシュ状の簡易ギズモを表示する「XGizmo」を追加。
・[追加]StorageLoadTextController と StorageSaveTextController に直接 UI.Text に読み書きするフィールド(targetText)を追加。
・[追加]EasyMusicPlayer に CurrentIndex と IsPlaying のプロパティを追加。
・[追加]EasyMusicPlayer の曲追加時のストレージオープン機能を同クラスに内包した(以前の StorageOpenAudioController から追加もそのまま使えます)。
・[修正]SceneLoadWithKey のインスペクタで「Use Name」の項目を「Scene Specification」で「Scene Name / Scene Build Index」で切り替えるように変更(内部的には bool 値のまま)。
・[修正]Android以外の無効コードパスを修正(Androidでビルドしている場合は影響ありません)。


※とりあえず試してみたい方には、最新版をビルドした apk デモをダウンロードできます。動作確認にもどうぞ。

(Google Drive を利用)


Android 4.2以上
※「提供元不明アプリのインストール」許可が必要です。




■ユニティちゃんと音声認識でじゃんけん(Android 版)

 せっかくなので、このプラグインを使って音声認識でじゃんけんゲームを作ってみた。音声認識の箇所はパッケージに入っている「Assets/_Test/Scripts/SpeechRecognizerTest.cs」をほぼそのまま使っている。具体的には、受け取った結果は改行("\n")で連結されてくるのでそれを分割し、それらの最初の1文字でグー、チョキ、パーを判定する処理(いくつか候補をデータ化してある)を追加しただけだ。

(※) Unity 2017.1.1f1 / Windows10(x64) でビルド。Galaxy S7 Edge (Android 7.0) で確認。

(Google Drive を利用)


Android 4.2以上
※「提供元不明アプリのインストール」許可が必要です。


 じゃんけん自体のアルゴリズム・作成方法を知りたければ以下の書籍を参考にすると良いだろう。アイコンがそっくりなのは、実際にこの本を以前読んでいたためである(笑)(※アプリ内のアイコンは新たに作ったものです)。また音声認識は以下の本も参考にしている(※ただし少し古い。実際のビルドは AndroidStudio 2.3.3 でやった)。なのでこのサンプルは2つをミックスしただけとも言える(笑)。

(じゃんけん画像素材)
LiveMaker 指南番

(じゃんけんゲーム/音声認識 参考)




 実際の Java コードは色々値をチェックしたり条件分岐したり、高速化のためにキャッシュしたり、StringBuilderを使ったりしているが、長くなるのでここでは簡略化したものを書いてあると考えて欲しい。Java を知っている人なら中身は非常に簡単なものばかりだとわかるだろう。AndroidStudio を使ったことあるなら AAR プラグインをビルドするのは簡単なので、挑戦してみるのも良いかも知れない。以下に参考資料を載せておこう。この2つの記事で基本的なプラグイン作成方法は十分だ(→実際にこれらプラグインはそのまんまの方法で作った(笑)。※AndroidStudio 2.3.3 でビルド)。

(参考)
Unity : Androidプラグインを作る一番簡単な方法
AndroidプラグインからUnityの関数を呼び出す - UnitySendMessage


※この記事のUnityアセットはプラグインとして配布されています。






(関連記事)
【Unity】【C#】プロジェクト内で Android(Java)プラグインをビルドする
【Unity】Firebase のプッシュ通知と FantomPlugin の共存(Firebase と他のプラグインの共存方法)
【Unity】AssetStore版 FantomPlugin のセットアップ
【Unity】標準以外のセンサー(歩数計や心拍数など)を使う(Android)
【Unity】AssetStore版 FantomPlugin のセットアップ
【Unity】標準以外のセンサー(歩数計や心拍数など)を使う(Android)
【Unity】カスタムダイアログを簡単に生成するプレファブを作ってみた(CustomDialogController)
【Unity】Androidでカスタマイズしたダイアログを動的生成できるプラグインを作ってみた
【Unity】Androidでスライダーで設定を変更するダイアログを使う
【Unity】Androidでスイッチで設定を変更するダイアログを使う
【Unity】Androidの選択ダイアログを使う
【Unity】Androidで日付・時刻選択ダイアログ(DatePicker, TimePicker)を使う
【Unity】Androidで数値・半角英数・パスワード入力ダイアログを使う
【Unity】Androidでチェックボックス付きのアラートダイアログ(AlertDialog)を使う
【Unity】Androidでテキスト入力ダイアログを使う
【Unity】Androidのテキスト読み上げ(TextToSpeech)を使う
【Unity】Androidで音声認識を使う
【Unity】Androidのハードウェア音量操作・ハードウェアキーの無効化をする
【Android】【Java】音声入力(音声認識)で文字列を取得する
【Android】【Java】AlertDialog を使ってみる


このコンテンツの一部には『ユニティちゃんライセンス』で許諾されたアセットが使用されています。
Portions of this work are licensed under Unity-Chan License



関連記事

category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityライブラリ  Unityプラグイン  音声認識  FantomPlugin 
tb: 0   cm: --

【Android】【Java】音声入力(音声認識)で文字列を取得する  


 いずれネイティブプラグイン作ったりするときのための布石。最近はVRでも音声入力できるものあるので Cardboard などでもできたら面白いかもね(Cardboard の場合、ハンディマイクでも付けない限り、構造的な問題が大きいが…)。とりあえずいつものように一番簡単にしたコードを書いておく。簡略のため細かいチェックなどは入れてないが、実際のアプリに使う場合は、色々と手を加えた方が良いだろう。


(※) Android Studio 2.3.3 / Windows10(x64) / Galaxy S7 Edge (Android 7.0) で確認

●簡単な構成

 例えばオブジェクト(ウィジェット)の構成が以下のようになっているものとする。配置などは任意で構わないが、とりあえず音声入力を開始するボタンと入力されたテキストを表示できるものがあれば良い。ここではそれぞれ ButtonTextView を使っている。


 仕様としては、「音声入力」のボタンを押したとき、音声入力のウィジェットが表示され入力開始→入力終了したらテキストビューに認識された文字列が列挙されるといった具合だ。その実装クラスを MainActivity とすると、コードは以下のようになる(テンプレートとしては「Empty Activity」を使っている)。

●音声入力された文字列を表示する
import android.content.Intent;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import java.util.List;

public class MainActivity extends AppCompatActivity {

private TextView textDisplay;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

textDisplay = (TextView)findViewById(R.id.text_display);
}

public void onClick(View v) {
//音声入力がサポートされているか?
if (getPackageManager().queryIntentActivities(new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0).size() == 0) {
Log.d("tag", "Voice Input is not supported.");
return; //サポートされてないとき無視
}

Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
startActivityForResult(intent, 0); //0:requestCode
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 0 && resultCode == RESULT_OK) {
if (data.hasExtra(RecognizerIntent.EXTRA_RESULTS)) {
//ここで認識された文字列を取得
List<String> results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
if (results.size() > 0) {
String str = "";
for (String s : results) {
str += s + "\n";
}
textDisplay.setText(str);
}
}
}
}
}

 ここではコードを減らすため、ボタンのクリック動作をレイアウトの「activity_main.xml」で「Button」の属性に「android:onClick="onClick"」を追加しているので注意。自分で実装するなら「View.OnClickListener」を implements し、ボタンに setOnClickListener() を付ける必要がある。

 また本来 onClick の引数の Viewid を調べて音声入力のボタンかどうかをチェックする必要もあるが、ここでは1つしかボタンがないので省略している。また、システムが音声入力をサポートしているかどうかもここで判別しているが、OnCreate() で判別して使用できなかったら、ボタンを無効にするのも良いだろう。

 ボタンを押下したときの動作は、音声入力の Intent を生成し startActivityForResult() でシステムに処理を委ねているだけである。音声が認識されたら、onActivityResult() で受信し、TextView に表示することになる。ここでの注意点は onActivityResult() は他の Intent のやり取りも含まれるので、予め音声入力用の requestCode を合わせておくことと、認識されたデータ(文字列)があるか否かというくらいだ。ここではデータがないときは単に無視している。

 この例では認識された文字列を拡張for文(foreach)で結合して TextView に表示しているだけだが、ここで各々の文字列によって処理を分岐すれば、音声認識でアクションを起こせるアプリが作れる。

(実装例)
ユニティちゃんと音声認識でじゃんけん(Android 版)

(音声認識 参考)



(関連記事)
【Unity】Androidで音声認識を使う
【Unity】Androidのトーストやダイアログ、通知、音声認識、ハード音量操作など基本的な機能を使えるプラグインを作ってみた
【Unity】Androidのテキスト読み上げ(TextToSpeech)を使う


関連記事

category: Android

thread: プログラミング

janre: コンピュータ

tag: 音声認識 
tb: 0   cm: --


プロフィール

Social

検索フォーム

全記事一覧

カテゴリ

ユーザータグ

最新記事

リンク

PR

▲ Pagetop