【Unity】Androidのトーストやダイアログ、通知、音声認識、ハード音量操作など基本的な機能を使えるプラグインを作ってみた 
2017/10/09 Mon [edit]
元々は GearVR のように、Cardboard/ハコスコVR でも BlueToothコントローラ を使って手元で音量操作できたら便利だろうな~って思って色々試してたんだけど、そのついでにAndroidに標準で備わっているトースト(Toast)やダイアログ(AlertDialog)、通知(Notification)、音声認識(SpeechRecognizer)なども使える簡単なプラグインを作ってみた。単純な機能しかないが、ブラウザなどでURL先を開く機能なども付けておいたので、アプリ内に書ききれない説明ページやサポートページなどのHPを開くボタンなどを作るのも良いだろう。簡単なものだがパッケージにはサンプルも付けておいたので、コピペするなり改造するなりして自由に使って欲しい。
※AssetStore版 FantomPluginのセットアップはこちら
(Google Drive を利用)
>>機能一覧のキャプチャ
※基本的にアセットストアのものとコードは同じになりますが、
アセットストア版は審査のためリリースが少し遅れるのと、規定上英語でのコメントが中心になります。
※とりあえず試してみたい方には、最新版をビルドした apk デモをダウンロードできます。動作確認にもどうぞ。


Android 4.2以上(5.0以上推奨)
※「提供元不明アプリのインストール」許可が必要です。
※CPU モニタデモは Android 8.0 以降では動作しません(OS の仕様変更でステータス取得できなくなった) ※Android11 以降では音声認識(SpeechRecognizer)や テキスト読み上げ(Text-to-speech)はパーミッションが必要になったようです。 |
|
■プラグインのセットアップ(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 デモをダウンロードできます。動作確認にもどうぞ。


Android 4.2以上
※「提供元不明アプリのインストール」許可が必要です。
■ユニティちゃんと音声認識でじゃんけん(Android 版)
せっかくなので、このプラグインを使って音声認識でじゃんけんゲームを作ってみた。音声認識の箇所はパッケージに入っている「Assets/_Test/Scripts/SpeechRecognizerTest.cs」をほぼそのまま使っている。具体的には、受け取った結果は改行("\n")で連結されてくるのでそれを分割し、それらの最初の1文字でグー、チョキ、パーを判定する処理(いくつか候補をデータ化してある)を追加しただけだ。
(※) Unity 2017.1.1f1 / Windows10(x64) でビルド。Galaxy S7 Edge (Android 7.0) で確認。
|


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】【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 を使ってみる

- 関連記事
トラックバック
トラックバックURL
→http://fantom1x.blog130.fc2.com/tb.php/273-7485d817
この記事にトラックバックする(FC2ブログユーザー)
| h o m e |