Edited at

【Google home】API.AIのAndroid SDKのサンプルを動かしてみる/API.AIのGithubをざっくり日本語訳

More than 1 year has passed since last update.


API.AIのAndroid用SDKのサンプルを動かしてみる


初めに

今回の記事は、API.AIサービス上で作成したエージェントをAndroidから呼び出しが可能になるサンプルのgitのread.meの翻訳です。

API.AIで作成したエージェントをAndroidのSDKのHTTPリクエストを使って呼び出しているイメージです。


GitHubより翻訳しながら動作を確認

※参考のリンクAPI.AI github

verは8212c36 on 9 Mar


Android SDK for api.ai

API.AI Android SDKはAPI.AIの言語プロセスを使用することで、Android機器上で容易にインテグレートできる。

API.AIは特定のエージェントの音声認識コマンドやインテグレーションが可能。

以下2つのパーミッションが必要



  • android.permission.INTERNET for internet access


  • android.permission.RECORD_AUDIO for microphone access

以下のdependenciesを追加

compile 'ai.api:libai:1.4.8'

compile 'ai.api:sdk:2.0.5@aar'
// api.ai SDK dependencies
compile 'com.android.support:appcompat-v7:23.2.1'
compile 'com.google.code.gson:gson:2.3.1'
compile 'commons-io:commons-io:2.4'

現在、音声認識はGoogleのAndroid SDKによりクライアント機器またはクラウド上で使用可能。

HTTPのリクエストを通してAPI.AIに認識されたテキストが渡される。また、Speaktoit recognition engine も使用可能(AIConfiguration.RecognitionEngine.Speaktoit).

認証はAIConfiguration objectの初期化のタイミングで行われる。

それにより、どのエージェントが使われるかを判定する。

Note: API.AI Android SDKはqueryリクエストのみ作成できる。そして、entityやintentを使用する際には使用できない。

しかし、その代わりにAPI.AI user interfaceまたはREST APIをentityやintentの作成、取得、更新、削除の際に使用できる。


Sample Code実行

API.AI Android SDKは簡単なサンプルで、どのようにしてAPI.AI.を使い開発できるかを説明している。

以下のステップでsample codeを実行できる:


  1. API.AIのエージェントを作成する(entityとintentを持つものを作ること). 参考:API.AI documentation
     ※エージェントの作成方法は別途記載するかも

  2. 起動: Android Studio.


  3. api-ai-android-master のディレクトリをインポート
     GitHubからダウンロードまたはクローン

  4. SDKマネージャの起動(Android Build Tools 19.1.がインストールされていること)

  5. プロジェクト上でapiAISampleApp/src/main/java/ai.api.sample/Configを開く

  6. ファイルの一番上に定数(static final string)で定義されたACCESS_TOKENがある. そこに、1で作成したエージェントのトークンをセットする API.AI-設定っぽいマーク(歯車)-General-Client access token にあるよ!

  7. Android機器を接続(PCだったら、AndroidにUSBをさしてデバッグ許可する)もしくはAndroid Emulatorの起動


  8. Runメニュー(起動?), Debug (もしくはDebugマークをクリック). 接続機器を選択。

  9. アプリの起動後に左記のようなボタンが現れる(サービスサンプル service sample内): Listen, StopListen, and Cancel.


  10. Listen をクリックしエージェント認識のフレーズを機器に話しかける。数秒後にAPI.AI serviceが応答を返す。.


自作Appで開始する

このセクションはAPI.AI Android SDKを使用するには何が必要かを説明している。1つ目にはSDKをどう使用するのかの全体像、2つ目にアプリ作成を段階的に説明しているチュートリアルがある。

もし、開発経験があれば先を使用することも可能 簡易インストラクション.


全体像

音声認識や自然言語処理の特色を実装するためには、API.AI SDKのライブラリを追加する必要がある。追加の方法は2通り

最初のやつがお勧め:



  1. build.gradleにdependencyを追加. 下の行をbuild.gradleに追加. (サンプルappでは, apiAISampleApp/build.gradleがサンプルとなっている)

    compile 'ai.api:libai:1.4.8'
    
    compile 'ai.api:sdk:2.0.5@aar'
    // api.ai SDK dependencies
    compile 'com.android.support:appcompat-v7:23.2.1'
    compile 'com.google.code.gson:gson:2.3'
    compile 'commons-io:commons-io:2.4'


  2. (おすすめじゃないやつ)githubからライブラリをダウンロードしてプロジェクトに追加


これで、自作またはインテグレートした音声認識をAPI.AI serviceを通してapp上で使用できる。


インテグレートした音声認識の使用

SDKのライブラリを追加したら、以下を実行:



  1. AndroidManifestにパーミッションを追加:


    • android.permission.INTERNET

    • android.permission.RECORD_AUDIO




  2. AIListenerの実装クラスを実装する. このクラスがAPI.AI.のレスポンスを処理する

    public interface AIListener {
    
    void onResult(AIResponse result); // here process response
    void onError(AIError error); // here process error
    void onAudioLevel(float level); // callback for sound level visualization
    void onListeningStarted(); // indicate start listening here
    void onListeningCanceled(); // indicate stop listening here
    void onListeningFinished(); // indicate stop listening here
    }



  3. AIConfigurationのインスタンスを作成, アクセストークン, locale, recognition engineを特定

    final AIConfiguration config = new AIConfiguration("CLIENT_ACCESS_TOKEN",
    
    AIConfiguration.SupportedLanguages.English,
    AIConfiguration.RecognitionEngine.System);



  4. query requestを作成するAIServiceを参照するためにAIConfiguration使用

    AIService aiService = AIService.getService(context, config);
    



  5. AIService インスタンスにAIListenerインスタンスを設定

    aiService.setListener(yourAiListenerInstance);
    



  6. startListeningメソッドを使用してマイクからのリスニングを起動。SDKがモバイルのマイクからの読み込みを開始する。

    aiService.startListening();
    



  7. リスニングを停止し結果リクエストをAPI.AI送信するためにAIServiceクラスのstopListeningメソッドを呼び出します。

    aiService.stopListening();
    



  8. API.AIサービスにリクエストを送らずに停止をする場合をAIServiceクラスのcancelメソッドを使用します。

    aiService.cancel();
    



  9. エラーがない場合、AIResponse.getResultを使用し結果を取得できます。そして、そこからアクションとパラーメータも取得可能です。

    public void onResult(final AIResponse response) {
    
    Log.i(TAG, "Action: " + result.getAction());
    // process response object
    }



独自の音声認識を使用する

このセクションは自作の音声認識とその自然言語処理が適切かの確認を行うことができる。SDKライブラリを追加したのちに以下のステップを実行する:



  1. AndroidManifestにパーミッションを追加:


    • android.permission.INTERNET



  2. AIConfigurationのインスタンスを作成し、アクセストークン・ロケール・認識エンジンを特定する。使用されていない認識エンジンを特定することができる。


  3. Objectのコンフィグで使用するAIDataServiceインスタンスを作成


  4. 空のAIRequestインスタンスを作成。リクエストテキストをsetQueryメソッドを使用して設定。


  5. aiDataService.request(aiRequest)を使用しAPI.AIにリクエストを送信。


  6. レスポンスの処理を行う。


下記のコードはテキスト「Hello」を送信している。

初めに、aiDataServiceaiRequestのインスタンスを初期化している

final AIConfiguration config = new AIConfiguration(ACCESS_TOKEN, 

AIConfiguration.SupportedLanguages.English,
AIConfiguration.RecognitionEngine.System);

final AIDataService aiDataService = new AIDataService(config);

final AIRequest aiRequest = new AIRequest();
aiRequest.setQuery("Hello");

そして、aiDataService.requestメソッドを読んでいる。注意してもらいたいのは、バックグラウンドのスレッドからAsyncTaskクラスなどを使用してaiDataService.requestメソッドを呼び出さなければいけない。

例えば:

new AsyncTask<AIRequest, Void, AIResponse>() {

@Override
protected AIResponse doInBackground(AIRequest... requests) {
final AIRequest request = requests[0];
try {
final AIResponse response = aiDataService.request(aiRequest);
return response;
} catch (AIServiceException e) {
}
return null;
}
@Override
protected void onPostExecute(AIResponse aiResponse) {
if (aiResponse != null) {
// process aiResponse here
}
}
}.execute(aiRequest);


結果の取得

AIListenerインターフェースの実装後、リスナー内部のapi.aiからレスポンスを取得できる。

例えば:

public void onResult(final AIResponse response) {

// Use the response object to get all the results
}

下記がどのように違う個所の結果オブジェクトを取得するかの説明である。


  • ステータスの取得

   final Status status = response.getStatus();

Log.i(TAG, "Status code: " + status.getCode());
Log.i(TAG, "Status type: " + status.getErrorType());


  • resolved queryの取得

   final Result result = response.getResult();

Log.i(TAG, "Resolved query: " + result.getResolvedQuery());


  • actionの取得

   final Result result = response.getResult();

Log.i(TAG, "Action: " + result.getAction());


  • speechの取得

   final Result result = response.getResult();

final String speech = result.getFulfillment().getSpeech();
Log.i(TAG, "Speech: " + speech);


  • metadataの取得

   final Result result = response.getResult();

final Metadata metadata = result.getMetadata();
if (metadata != null) {
Log.i(TAG, "Intent id: " + metadata.getIntentId());
Log.i(TAG, "Intent name: " + metadata.getIntentName());
}


  • parametersの取得

   final Result result = response.getResult();

final HashMap<String, JsonElement> params = result.getParameters();
if (params != null && !params.isEmpty()) {
Log.i(TAG, "Parameters: ");
for (final Map.Entry<String, JsonElement> entry : params.entrySet()) {
Log.i(TAG, String.format("%s: %s", entry.getKey(), entry.getValue().toString()));
}
}


Tutorial

このセクションは自作の新規アプリケーションをAPI.AIに接続する詳細なチュートリアルである。


Appの作成

下記の手順に従い、環境構築を行い、API.AIのインテグレーションを使用してアプリを作成する:


  1. API.AIエージェントを使用してentityやintentを作成する。もしくは、既に作成しているものを使用する。API.AIのドキュメントを読み進めてください。


  2. Android Studioを開く. (もし持っていなければダウンロードしてね)

  3. スタート画面(もしくはFileメニュー)から , New Project...を選択.
    New Project

  4. 新規プロジェクトダイアログの中のApplication nameCompany Domainを記載, Nextをクリック.
    New project dialog

  5. プロジェクトの最低限のSDKを選択, 最低限のAPI.AIのSDKとは9 Gingerbreadです。Nextをクリック.
    Min SDK


  6. Blank Activityを選びNextをクリック.

  7. main activity名を入力しFinish押下.


SDKを使用しインテグレート

次は呼び出し可能にするためにSDKを使用しインテグレートする。 以下を参考:



  1. AndroidManifest.xml(app/src/main配下)を開く.


  2. <application>タグの上に下記を追加し、インターネットアクセスとモバイルのマイクにアクセス可能にする:

    <uses-permission android:name="android.permission.INTERNET"/>
    
    <uses-permission android:name="android.permission.RECORD_AUDIO" />


  3. AndroidManifest.xml保存.


  4. 次にAI.APIのライブラリ用のDependencyを追加する。プロジェクトナビゲータのモジュール名上で右クリック(app内にあるはず)、そしてOpen Module Settingsを選択. Dependenciesタブをクリック. ボタン左の+マークを選択しLibrary dependencyをクリック.
    Add dependency

  5. ダイアログ検索内でai.apiを検索, ai.api:sdk:2.0.5末尾に@aarを付けたものを入力しOKをクリック。(ここらへんは本家に画像がついてるから見て)
    Add dependency


    • SDKのライブラリも追加が必要 : com.android.support:appcompat-v7, com.google.code.gson:gson, commons-io:commons-io. (同じ方法で追加してね).



  6. MainActivity.java(app/src/main/java/com.example.yourAppName.app内)を開く, もしくは何でもいいので自分のパッケージを開く。



  7. 下記API.AIクラスをimportして機能拡張:

    import ai.api.AIListener;
    
    import ai.api.android.AIConfiguration;
    import ai.api.android.AIService;
    import ai.api.model.AIError;
    import ai.api.model.AIResponse;
    import ai.api.model.Result;
    import com.google.gson.JsonElement;
    import java.util.Map;



ユーザインタフェースの作成



  1. activity_main.xml(app/src/main/res/layout配下)を開く. designer内のlayout を開く。
    activity_main.xml in Designer

  2. "Hello World"のTextViewを削除.

  3. Widget下のボタンを画面上部にドラッグ。 プロパティidを"listenButton"に変更し、そのtextを"Listen"に変更
    Listen button

  4. Widget下のTextViewをそのボタンの下にドラッグ。開くと、残りスクリーンをそのテキストビューが埋める。プロパティidを"resultTextView"に変更し、プロパティtextを空にする
    Result TextView


  5. MainActivity.javaのファイルを開き(さっき開いてるかな?). 下記をimportし、作成したステートメントにアクセスするようにする:

    import android.view.View;
    
    import android.widget.Button;
    import android.widget.TextView;



  6. MainActivity に下記のprivateメンバーを追加する(widget操作用):

    private Button listenButton;
    
    private TextView resultTextView;



  7. OnCreateの最後尾あたりに下記のwidget初期化分を追加:

    listenButton = (Button) findViewById(R.id.listenButton);
    
    resultTextView = (TextView) findViewById(R.id.resultTextView);



AIサービスとリスナーの作成



  1. イベント起動の際に呼び出されるMainActivityクラス(AIListenerクラスをimplementしたやつ)を使う。クラス宣言を下記に置き換える:

    public class MainActivity extends ActionBarActivity implements AIListener {
    



  2. MainActivity クラス内でprivateメンバーとしてaiService(AIServiceクラス)を生成。

    private AIService aiService;
    



  3. 音声認識システム使用のコンフィグを設定するためにOnCreateメソッド内に下記を追加。CLIENT_ACCESS_TOKENを自分のアクセストークンに追加(API.AIのサービスの設定みたいなとこからクライアントのアクセストークンをとってきてね)

     final AIConfiguration config = new AIConfiguration("CLIENT_ACCESS_TOKEN",
    
    AIConfiguration.SupportedLanguages.English,
    AIConfiguration.RecognitionEngine.System);

    Api keys



  4. 下記でAIのサービスを初期化し、リスナーとしてインスタンスをハンドルイベントに追加

    aiService = AIService.getService(this, config);
    
    aiService.setListener(this);



  5. ボタンクリックでリスニング開始のメソッドを追加:

    public void listenButtonOnClick(final View view) {
    
    aiService.startListening();
    }



  6. activity_main.xmlに移り、Listenボタンをクリック。プロパティぺーん内にonClickのプロパティとしてlistenButtonOnClickを設定する。リスニングが終わった時の結果を表示するために下記を追加する:

    public void onResult(final AIResponse response) {
    
    Result result = response.getResult();

    // Get parameters
    String parameterString = "";
    if (result.getParameters() != null && !result.getParameters().isEmpty()) {
    for (final Map.Entry<String, JsonElement> entry : result.getParameters().entrySet()) {
    parameterString += "(" + entry.getKey() + ", " + entry.getValue() + ") ";
    }
    }

    // Show results in TextView.
    resultTextView.setText("Query:" + result.getResolvedQuery() +
    "\nAction: " + result.getAction() +
    "\nParameters: " + parameterString);
    }




  7. エラーハンドルように追加:

    @Override
    
    public void onError(final AIError error) {
    resultTextView.setText(error.toString());
    }



  8. AIListenerインターフェースを実装するために下記の空メソッドを追加:

    @Override
    
    public void onListeningStarted() {}

    @Override
    public void onListeningCanceled() {}

    @Override
    public void onListeningFinished() {}

    @Override
    public void onAudioLevel(final float level) {}




App起動


  1. Android機器をPCに接続または仮想機を起動

  2. ドロップダウンにモジュールが選択されていることを確認し、デバッグボタンをクリック
    Debug button

  3. 機器または仮想機で起動しているはず。。。Listenボタンをクリックしintentを起動するフレーズを言う。数秒後、TextViewに結果が表示される
    Result



ユーザ特定のcontext

RequestExtrasオブジェクトを使ったクエリ内のユーザのcontextsを特定するには

まず、必要なcontextの一覧を作成:

List<AIContext> contexts = new ArrayList<>();

contexts.add(new AIContext("firstContext"));
contexts.add(new AIContext("secondContext"));

そしてRequestExtrasインスタンスを作成し、リクエストで使用

RequestExtras requestExtras = new RequestExtras(contexts, null);

aiService.startListening(requestExtras);


ユーザの特定のentityの場合

RequestExtrasオブジェクトを使ったクエリ内のentityの特定を行うために

必要なentityの一覧を作成:

final Entity myDwarfs = new Entity("dwarfs");

myDwarfs.addEntry(new EntityEntry("Ori", new String[] {"Ori", "Nori"}));
myDwarfs.addEntry(new EntityEntry("Bifur", new String[] {"Bofur","Bombur"}));
final List<Entity> entities = Collections.singletonList(myDwarfs);

リクエストとしてRequestExtrasインスタンスを使うためにインスタンスを作成

RequestExtras requestExtras = new RequestExtras(null, entities);

aiService.startListening(requestExtras);

メソッドを使用してアップロードできる。

aiService.uploadUserEntities(entities);


Bluetooth support

Bluetooth機器を使用しSDKのワークをするために下記の手順を行う:



  1. アプリケーションクラス付近でBluetoothControllerの実装作成を行う

    private class BluetoothControllerImpl extends BluetoothController {

    public BluetoothControllerImpl(Context context) {
    super(context);
    }

    @Override
    public void onHeadsetDisconnected() {
    Log.d(TAG, "Bluetooth headset disconnected");
    }

    @Override
    public void onHeadsetConnected() {
    Log.d(TAG, "Bluetooth headset connected");

    if (isInForeground() && !bluetoothController.isOnHeadsetSco()) {
    bluetoothController.start();
    }
    }

    @Override
    public void onScoAudioDisconnected() {
    Log.d(TAG, "Bluetooth sco audio finished");
    bluetoothController.stop();

    if (isInForeground()) {
    bluetoothController.start();
    }
    }

    @Override
    public void onScoAudioConnected() {
    Log.d(TAG, "Bluetooth sco audio started");
    }

    }




  2. ApplicationクラスにActivityを数えるintとBlueTooth管理のためのBluetoothControllerをフィールドとして追加

    private int activitiesCount;
    
    private BluetoothControllerImpl bluetoothController;



  3. helperメソッドをApplicationに追加

    protected void onActivityResume() {
    
    if (activitiesCount++ == 0) { // on become foreground
    bluetoothController.start();
    }
    }

    protected void onActivityPaused() {
    if (--activitiesCount == 0) { // on become background
    bluetoothController.stop();
    }
    }

    private boolean isInForeground() {
    return activitiesCount > 0;
    }




  4. 全てのActivityのonPauseonResumeからこのメソッドを呼び出す必要がある。そして、すべてのactivityの基底クラスとできる

    public class BaseActivity extends ActionBarActivity {

    private AIApplication app;

    private static final long PAUSE_CALLBACK_DELAY = 500;

    private final Handler handler = new Handler();
    private Runnable pauseCallback = new Runnable() {
    @Override
    public void run() {
    app.onActivityPaused();
    }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    app = (AIApplication) getApplication();
    }

    @Override
    protected void onResume() {
    super.onResume();
    app.onActivityResume();
    }

    @Override
    protected void onPause() {
    super.onPause();
    handler.postDelayed(pauseCallback, PAUSE_CALLBACK_DELAY);
    }
    }



Sample Applicationにソースがある.


Troubleshooting


  • インストール中に"INSTALL_FAILED_OLDER_SDK"のエラーが出た場合は、Android SDK 19があるか、ビルドツールの19.1がインストールされているか確認してね