CrossRoad

XRを中心とした技術ブログ。 Check also "English" category.

【2016/11/27 更新】UnityでBing Speech to Text API(Android用)を使う方法(Android Studio側の構築手順)

以前紹介した、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プロジェクトサンプルを入手し、動作確認

まずはMicrosoftが提供しているサンプルコードを入手します。

GitHub - Azure-Samples/Cognitive-Speech-STT-Android: Android SDK for the Microsoft Speech-to-Text API, part of Cognitive Services

これを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上ではこのように配置されます。

Android Studio上で見た、classes.jarの配置場所

メッセージウインドウが2回出ますが、どちらもOKを選択してください。

2-2. build.gradleを修正

applicationではなくlibraryとしてビルドするため、先頭を変更します。

また、末尾(でなくてもよいですが)に、android.libraryVariants.all を使って、ビルド時の条件を追加します。

それ以外は元のMicrosoftのサンプルと同様です。下記のようになります。


gist1df4689cfea9d7484a04147b83e01c8b

2-3. Unityと通信するためのI/Fクラスを追加

Project Viewにして、com.microsoft.CognitiveServicesExampleで右クリックし、New / Java Class を選択して、新しくクラスを追加します。

私の場合、クラス名をNativeBridgeとしました。

クラス名をNativeBridgeとしたときのAndroid Studioの画面例

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