以前紹介した、MicrosoftのBing Speech To TextをUnityで使えるようにしてみました。
(1) Android StudioでUnity向けmoduleを作る方法 - Cross Technology
ただ、Android nativeアプリ開発に不慣れだったこともあり、色々とつまづきました。せっかくなので、修正過程を整理しておこうと思います。
なお、以下の環境で動作を確認しています。
- MacOS X 10.11.6
- Android Studio 2.1.2
- 1. Android Studioプロジェクトサンプルを入手し、動作確認
- 2. Module に変更して、Serviceから起動できるようにする
- 3. ビルドしてUnityで使うためのモジュールを生成する
1. Android Studioプロジェクトサンプルを入手し、動作確認
まずはMicrosoftが提供しているサンプルコードを入手します。
これをAndroid Studioで開きます。開いた後、下記の手順に従って、Androidスマートフォンで動くように設定します。
【Android】Bing Speech APIを使う手順をまとめました - Cross Technology
この記事でも紹介しましたが、私の環境では、アプリインストール直後は、ほぼ必ず1,2回動作に失敗しました。
(Login Failedというエラーが出ます)
この場合、アプリの再インストールか再起動を繰り返してみてください。
2. Module に変更して、Serviceから起動できるようにする
Microsoftが提供するサンプルコードは、アプリ(app)になっています。これだとUnityでアプリ化できないので、モジュール(library)に変更します。アプリとモジュールの違いについては、下記を参照ください。また、以後は下記を確認済みとして解説します。
(1) Android StudioでUnity向けmoduleを作る方法 - Cross Technology
2.1 classes.jarを追加する
以下のclasses.jarでctrl+cした後、Android Studioを開いてlibフォルダで、ctrl+pします。
Macの場合
/アプリケーション/Unity/PlaybackEngine/AndroidPlayer/Variations/mono/Release/Classes/classes.jar
Windowsの場合
C:\Program Files\Unity\Editor\Data/PlaybackEngines/AndroidPlayer/Varitations/mono/Release/Classes/classes.jar
classes.jarをドラッグ&ドロップすると、copyではなくmove扱いになって、Unityの本来のフォルダからclasses.jarが消えてしまうので注意してください。コピーすると、Android Studio上ではこのように配置されます。
メッセージウインドウが2回出ますが、どちらもOKを選択してください。
2-2. build.gradleを修正
applicationではなくlibraryとしてビルドするため、先頭を変更します。
また、末尾(でなくてもよいですが)に、android.libraryVariants.all を使って、ビルド時の条件を追加します。
それ以外は元のMicrosoftのサンプルと同様です。下記のようになります。
2-3. Unityと通信するためのI/Fクラスを追加
Project Viewにして、com.microsoft.CognitiveServicesExampleで右クリックし、New / Java Class を選択して、新しくクラスを追加します。
私の場合、クラス名をNativeBridgeとしました。
2-4. I/Fクラス NativeBridge.javaにbindServiceの機能を実装
色々試しましたが、最終的に元のMicrosoftの機能をService化することで、動作させることができました。以下はNativeBridge側の機能です。
ざっくり説明すると、元の機能をServiceとして呼び出し、bindServiceによってUnity側のActivityとつなぎ、Service化した機能をUnityに渡しています。bindServiceの書き方は少し複雑ですが、いくつか調べたところ、決まったフォーマットで書けばよいことがわかったので、それに倣って書きました。
下記はNativeBridge.javaの実装例です。
gist47c7cb56bd156593badcefcca2a80827
なお、これだけを書いた時点では多数のエラーが出ます。それはMainActivity.java側を変更していないためなので、この時点では無視して問題ありません。
2-5. Activityクラスを修正
Serviceとして呼ぶためにActivityの記述を削除すること、およびUnityに音声認識結果を返すためにUnitySendMessage関数を仕込むこと、の2つが大きな修正目的です。個別に説明すると相当多くなるので、ここでは主な修正箇所をざっと解説します。余力があればgithubで全体を公開します。
(2016/11/27 追記:Githubで公開しました。)
import
以下を追加。
import android.os.IBinder; import android.util.Log; import com.unity3d.player.UnityPlayer; import android.content.Intent; import android.app.Service; import android.os.Binder;
bindService
以下を追加。
public class MyServiceLocalBinder extends Binder { MainActivity getService() { return MainActivity.this; } } private final IBinder mBinder = new MyServiceLocalBinder(); @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public void onRebind(Intent intent){} @Override public boolean onUnbind(Intent intent){ //onUnbindをreturn trueでoverrideすると次回バインド時にonRebildが呼ばれる return true; }
元のサンプルコードでボタンやラジオボタンで処理が分かれる箇所
基本的に全てtrueで返し、ボタン関係の処理はコメントアウトします。
認識対象の言語
下記のようにgetDefaultLocaleメソッドを修正し、日本語対応させます。
private String getDefaultLocale() { return "ja-jp"; }
onCreateメソッドの削除
全てコメントアウトします。
StartButton_Clickメソッドの変更
このメソッドの中では、Activityを引数に持つメソッドを呼び出す箇所が何個かあります。ただ、今回はServiceにしているので、Activityを引数に持たないようにします。幸い、呼び出したいメソッドを調べるとActivityが引数にない場合の宣言もあるので、こっちを使います。
また、StartButton_Clickメソッドの引数はなしにしておきます。
onFinalResponseReceivedメソッドにUnitySendMessageを追加
このメソッドは、音声認識が完了すると呼ばれます。そこで、ここにUnitySendMessageを挟むことで、認識結果の文字列をUnity側に送ることができます。
具体的には、
for (int i = 0; i < response.Results.length; i++) { UnityPlayer.UnitySendMessage("TestObject","onCallBackShowResult",response.Results[i].DisplayText); // this.WriteLine("[" + i + "]" + " Confidence=" + response.Results[i].Confidence + // " Text=\"" + response.Results[i].DisplayText + "\""); }
のように記述します。
3. ビルドしてUnityで使うためのモジュールを生成する
Terminalを開いて、
./gradlew :samples:SpeechRecoExample:clean :samples:SpeechRecoExample:assembleRelease
を実行します。Terminalの場所については、下記の2-5を参照ください。
(1) Android StudioでUnity向けmoduleを作る方法 - Cross Technology
ここまで実行すると、Android Studio側の対応が完了します。Unity側の対応は下記をご確認ください。
【2017/3/1更新】(4-2) UnityでBing Speech to Text API(Android用)を使う方法(Unity側の構築手順) - Cross Technology