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実行
- 自作Appで開始する
- Tutorial
- Brief Integration Instruction (for experienced developers)
- Feature examples
- Troubleshooting
Sample Code実行
API.AI Android SDKは簡単なサンプルで、どのようにしてAPI.AI.を使い開発できるかを説明している。
以下のステップでsample codeを実行できる:
- API.AIのエージェントを作成する(entityとintentを持つものを作ること). 参考:API.AI documentation ※エージェントの作成方法は別途記載するかも
- 起動: Android Studio.
- api-ai-android-master のディレクトリをインポート GitHubからダウンロードまたはクローン
- SDKマネージャの起動(Android Build Tools 19.1.がインストールされていること)
- プロジェクト上でapiAISampleApp/src/main/java/ai.api.sample/Configを開く
- ファイルの一番上に定数(static final string)で定義されたACCESS_TOKENがある. そこに、1で作成したエージェントのトークンをセットする API.AI-設定っぽいマーク(歯車)-General-Client access token にあるよ!
- Android機器を接続(PCだったら、AndroidにUSBをさしてデバッグ許可する)もしくはAndroid Emulatorの起動
- Runメニュー(起動?), Debug (もしくはDebugマークをクリック). 接続機器を選択。
- アプリの起動後に左記のようなボタンが現れる(サービスサンプル service sample内): Listen, StopListen, and Cancel.
- Listen をクリックしエージェント認識のフレーズを機器に話しかける。数秒後にAPI.AI serviceが応答を返す。.
自作Appで開始する
このセクションはAPI.AI Android SDKを使用するには何が必要かを説明している。1つ目にはSDKをどう使用するのかの全体像、2つ目にアプリ作成を段階的に説明しているチュートリアルがある。
もし、開発経験があれば先を使用することも可能 簡易インストラクション.
全体像
音声認識や自然言語処理の特色を実装するためには、API.AI SDKのライブラリを追加する必要がある。追加の方法は2通り
最初のやつがお勧め:
-
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'
(おすすめじゃないやつ)githubからライブラリをダウンロードしてプロジェクトに追加
これで、自作またはインテグレートした音声認識をAPI.AI serviceを通してapp上で使用できる。
インテグレートした音声認識の使用
SDKのライブラリを追加したら、以下を実行:
-
AndroidManifestにパーミッションを追加:
- android.permission.INTERNET
- android.permission.RECORD_AUDIO
-
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 }
-
AIConfigurationのインスタンスを作成, アクセストークン, locale, recognition engineを特定
final AIConfiguration config = new AIConfiguration("CLIENT_ACCESS_TOKEN", AIConfiguration.SupportedLanguages.English, AIConfiguration.RecognitionEngine.System);
-
query requestを作成するAIServiceを参照するためにAIConfiguration使用
AIService aiService = AIService.getService(context, config);
-
AIService インスタンスにAIListenerインスタンスを設定
aiService.setListener(yourAiListenerInstance);
-
startListeningメソッドを使用してマイクからのリスニングを起動。SDKがモバイルのマイクからの読み込みを開始する。
aiService.startListening();
-
リスニングを停止し結果リクエストをAPI.AI送信するためにAIServiceクラスのstopListeningメソッドを呼び出します。
aiService.stopListening();
-
API.AIサービスにリクエストを送らずに停止をする場合をAIServiceクラスのcancelメソッドを使用します。
aiService.cancel();
-
エラーがない場合、AIResponse.getResultを使用し結果を取得できます。そして、そこからアクションとパラーメータも取得可能です。
public void onResult(final AIResponse response) { Log.i(TAG, "Action: " + result.getAction()); // process response object }
独自の音声認識を使用する
このセクションは自作の音声認識とその自然言語処理が適切かの確認を行うことができる。SDKライブラリを追加したのちに以下のステップを実行する:
-
AndroidManifestにパーミッションを追加:
- android.permission.INTERNET
AIConfigurationのインスタンスを作成し、アクセストークン・ロケール・認識エンジンを特定する。使用されていない認識エンジンを特定することができる。
Objectのコンフィグで使用するAIDataServiceインスタンスを作成
空のAIRequestインスタンスを作成。リクエストテキストをsetQueryメソッドを使用して設定。
aiDataService.request(aiRequest)を使用しAPI.AIにリクエストを送信。
レスポンスの処理を行う。
下記のコードはテキスト「Hello」を送信している。
初めに、aiDataService
とaiRequest
のインスタンスを初期化している
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のインテグレーションを使用してアプリを作成する:
- API.AIエージェントを使用してentityやintentを作成する。もしくは、既に作成しているものを使用する。API.AIのドキュメントを読み進めてください。
- Android Studioを開く. (もし持っていなければダウンロードしてね)
- スタート画面(もしくはFileメニュー)から , New Project...を選択.
- 新規プロジェクトダイアログの中のApplication nameとCompany Domainを記載, Nextをクリック.
- プロジェクトの最低限のSDKを選択, 最低限のAPI.AIのSDKとは9 Gingerbreadです。Nextをクリック.
- Blank Activityを選びNextをクリック.
- main activity名を入力しFinish押下.
SDKを使用しインテグレート
次は呼び出し可能にするためにSDKを使用しインテグレートする。 以下を参考:
- AndroidManifest.xml(app/src/main配下)を開く.
-
<application>
タグの上に下記を追加し、インターネットアクセスとモバイルのマイクにアクセス可能にする:<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.RECORD_AUDIO" />
AndroidManifest.xml保存.
次にAI.APIのライブラリ用のDependencyを追加する。プロジェクトナビゲータのモジュール名上で右クリック(app内にあるはず)、そしてOpen Module Settingsを選択. Dependenciesタブをクリック. ボタン左の+マークを選択しLibrary dependencyをクリック.
-
ダイアログ検索内でai.apiを検索, ai.api:sdk:2.0.5末尾に
@aar
を付けたものを入力しOKをクリック。(ここらへんは本家に画像がついてるから見て)
- SDKのライブラリも追加が必要 : com.android.support:appcompat-v7, com.google.code.gson:gson, commons-io:commons-io. (同じ方法で追加してね).
MainActivity.java(app/src/main/java/com.example.yourAppName.app内)を開く, もしくは何でもいいので自分のパッケージを開く。
-
下記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;
ユーザインタフェースの作成
-
activity_main.xml(app/src/main/res/layout配下)を開く. designer内のlayout を開く。
- "Hello World"のTextViewを削除.
- Widget下のボタンを画面上部にドラッグ。 プロパティidを"listenButton"に変更し、そのtextを"Listen"に変更
- Widget下のTextViewをそのボタンの下にドラッグ。開くと、残りスクリーンをそのテキストビューが埋める。プロパティidを"resultTextView"に変更し、プロパティtextを空にする
-
MainActivity.javaのファイルを開き(さっき開いてるかな?). 下記をimportし、作成したステートメントにアクセスするようにする:
import android.view.View; import android.widget.Button; import android.widget.TextView;
-
MainActivity に下記のprivateメンバーを追加する(widget操作用):
private Button listenButton; private TextView resultTextView;
-
OnCreateの最後尾あたりに下記のwidget初期化分を追加:
listenButton = (Button) findViewById(R.id.listenButton); resultTextView = (TextView) findViewById(R.id.resultTextView);
AIサービスとリスナーの作成
-
イベント起動の際に呼び出されるMainActivityクラス(AIListenerクラスをimplementしたやつ)を使う。クラス宣言を下記に置き換える:
public class MainActivity extends ActionBarActivity implements AIListener {
-
MainActivity クラス内でprivateメンバーとして
aiService
(AIServiceクラス)を生成。private AIService aiService;
-
音声認識システム使用のコンフィグを設定するためにOnCreateメソッド内に下記を追加。CLIENT_ACCESS_TOKENを自分のアクセストークンに追加(API.AIのサービスの設定みたいなとこからクライアントのアクセストークンをとってきてね)
final AIConfiguration config = new AIConfiguration("CLIENT_ACCESS_TOKEN", AIConfiguration.SupportedLanguages.English, AIConfiguration.RecognitionEngine.System);
-
下記でAIのサービスを初期化し、リスナーとしてインスタンスをハンドルイベントに追加
aiService = AIService.getService(this, config); aiService.setListener(this);
-
ボタンクリックでリスニング開始のメソッドを追加:
public void listenButtonOnClick(final View view) { aiService.startListening(); }
-
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); }
-
エラーハンドルように追加:
@Override public void onError(final AIError error) { resultTextView.setText(error.toString()); }
-
AIListenerインターフェースを実装するために下記の空メソッドを追加:
@Override public void onListeningStarted() {} @Override public void onListeningCanceled() {} @Override public void onListeningFinished() {} @Override public void onAudioLevel(final float level) {}
App起動
- Android機器をPCに接続または仮想機を起動
- ドロップダウンにモジュールが選択されていることを確認し、デバッグボタンをクリック
- 機器または仮想機で起動しているはず。。。Listenボタンをクリックしintentを起動するフレーズを言う。数秒後、TextViewに結果が表示される
例
ユーザ特定の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のワークをするために下記の手順を行う:
-
アプリケーションクラス付近で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"); } }
-
Application
クラスにActivityを数えるintとBlueTooth管理のためのBluetoothController
をフィールドとして追加private int activitiesCount; private BluetoothControllerImpl bluetoothController;
-
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; }
-
全てのActivityの
onPause
とonResume
からこのメソッドを呼び出す必要がある。そして、すべての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がインストールされているか確認してね