1. 概要
App Actions を使えば、Google アシスタントでアプリの個々の機能に直接ジャンプし、音声を使ってタスクを完了できます。Android アプリに App Action を追加するには、ケーパビリティ要素を実装します。ケーパビリティは、音声リクエストに対応できるアプリの機能と、リクエストの適切な処理方法を、Google アシスタントに伝える役割を持ちます。
この Codelab では、App Actions を使った開発に関する初級レベルのコンセプトについて解説します。Android アプリの開発と Android の「インテント」について、事前の経験が必要となります。Android 向け開発の経験があまりない場合は、まず Android デベロッパーの基礎 Codelab 集のいずれかを履修するのもおすすめです。
作成する内容
この Codelab では、サンプルの Android 向けフィットネス アプリに、App Actions の組み込みインテント(BII: Built-in Intent)を 2 つ追加します。これにより、アプリのユーザーがエクササイズ用のタイマーを音声によって開始および停止できるようになります。
学習する内容
Health and Fitness カテゴリの BII を使って Google アシスタントを Android アプリへと拡張する方法を学びます。また、Android Studio 用の Google アシスタント プラグインを使って BII をテストする方法も習得できます。
前提条件
続行する前に、使用する環境内に以下のツールが揃っていることを確認してください。
- シェルコマンドを実行するためのターミナル(git がインストールされていること)。
- Android Studio の最新バージョン。
- [Google Play Console][] にアクセスできる Google アカウント。
- Play ストアにインターネット経由でアクセスできる、Android の実機または仮想デバイス。
続行する前に、同じ Google アカウントで Android Studio とテスト用デバイスの Google アプリにもログインしていることを確認しましょう。
2. 仕組みを理解する
App Actions は、ユーザーを Google アシスタントから Android アプリに接続します。具体的にはどのような仕組みなのでしょうか。
アプリを使ったタスクの実行をユーザーから依頼されると、Google アシスタントはそのクエリを、アプリの XML リソース shortcuts.xml
で定義された App Actions ケーパビリティ(capability
)のいずれかとマッチングします。
図 1. Google アシスタントが App Actions 音声クエリを処理する仕組みを示したフロー図
各ケーパビリティ要素は、以下を定義します。
- インテント(1 つ): ケーパビリティをトリガーする App Actions 音声インテント。
- フルフィルメント(1 つまたは複数): ユーザーの音声リクエストを解決(フルフィル)するために Google アシスタントが生成する Android インテントまたはディープリンク。フルフィルメントの定義では、ユーザーのクエリから受け取ることを想定するパラメータ群と、それらのパラメータを起動指示にエンコードする方法が指定されます。
インテント
自然言語理解(NLU)において「インテント」とは、類似の意味を持つユーザーのフレーズをまとめたグループです。Google は何十種類もの「組み込み」インテント(BII)を用意し、App Actions で利用できるさまざまなリクエスト タイプに対応しています。たとえば、Google アシスタントは「ピザを注文して」や「デザートのメニューを見せて」といったフレーズを、BII「ORDER_MENU_ITEM
」と関連付けるようトレーニングされています。App Actions でこれらの BII を活用すれば、一般的な音声リクエストをアプリの機能へと手軽に拡張することができます。
フルフィルメント
ユーザーのリクエストによって shortcuts.xml
内の App Action がトリガーされると、Android アクティビティは送られてくる Android インテントまたはディープリンクを検出および処理し、求められた機能をユーザーに提供します。これにより、ユーザーのクエリに応じて Google アシスタントがアプリを呼び出す、音声駆動型のユーザー エクスペリエンスが実現します。
3. 開発環境を準備する
この Codelab では、サンプルの Android 向けフィットネス アプリを使用します。エクササイズ用のタイマーの開始と停止、エクササイズ ルーティンについての統計データの閲覧ができるアプリです。
ベースファイルをダウンロードする
この Codelab 用のベースファイルを入手するには、次のコマンドを実行して GitHub リポジトリのクローンを作成します。
git clone --branch codelab-start https://github.com/actions-on-google/appactions-fitness-kotlin.git
リポジトリのクローンを作成したら、Android Studio で開きます。
- [Welcome to Android Studio] ダイアログで、[Import project] をクリックします。
- リポジトリのクローンを作成したフォルダを見つけ、選択します。
Android アプリケーション ID を更新する
アプリのアプリケーション ID を更新すると、テストデバイス上のアプリが一意に識別され、Google Play Console にアプリをアップロードする場合に「パッケージ名の重複」エラーが発生するのを回避できます。アプリケーション ID を更新するには、app/build.gradle
を開きます。
android {
...
defaultConfig {
applicationId "com.MYUNIQUENAME.android.fitactions"
...
}
}
applicationId
フィールドの「MYUNIQUENAME」は、独自の値に置き換えます。
デバイスでアプリを試す
アプリのコード編集をさらに進める前に、サンプルアプリでどんなことができるのか把握しておくといいでしょう。開発環境内でアプリをテストする際の流れは次のとおりです。
- Android テストデバイス(仮想デバイスまたは実機)を開く。
- Google アシスタント アプリが機能することを確認する。
- Android Studio を使ってサンプルアプリをデバイスにデプロイし、実行する。
アプリをテストする手順:
- Android Studio で、[Run] > [Run app] を選択するか、ツールバーの実行アイコン をクリックします。
- 仮想デバイスを使用している場合は、[Select Deployment Target] ダイアログで仮想デバイスを選択し、[OK] をクリックします。推奨される OS バージョンは Android 8(API レベル 26)以上ですが、Actions は Android 5(API レベル 21)以上のデバイスであれば動作します。
- アプリを起動後、ホームボタンを長押しして Google アシスタントをセットアップし、正しく機能することを確認します。Google アシスタントにまだログインしていなかった場合は、ここでログインします。
- アプリを再度開きます。
図 2. サンプルアプリ Fit Actions でエクササイズの統計データが表示されている様子
アプリを少し操作して、何ができるのか確認してみましょう。Run アイコンをタップするとエクササイズ用のタイマーが開始し、×アイコンをタップすれば停止します。これらのタスクを、App Actions による音声操作で実行できるようにしていきます。
Google アシスタント プラグインをインストールする
Google アシスタント プラグインを使用すると、App Actions の動作をテストデバイスで確認できます。Android Studio に追加する手順は次のとおりです。
- [File] > [Settings](macOS では [Android Studio] > [Preferences])に移動します。
- [Plugins] セクションで [Marketplace] に移動して「Google Assistant」を検索します。
- ツールをインストールして Android Studio を再起動します。
4. エクササイズ開始の BII ケーパビリティを追加する
BII「actions.intent.START_EXERCISE
」は、音声によってアプリを起動してワークアウトを開始できる機能を提供します。このステップでは、この BII に対応するケーパビリティを実装して、ユーザーが Google アシスタントに、フィットネス アプリ内でランニングを開始することを依頼できるようにします。
ケーパビリティを定義する
Google アシスタントは、shortcuts.xml
内で定義された capability
要素を使って、音声コマンドを処理します。流れは次のとおりです。
- Google アシスタントがユーザーの音声クエリを、アプリのケーパビリティで定義された BII とマッチングします。
- Google アシスタントがクエリから値を抽出して、BII のパラメータに渡します。各パラメータは、生成された
Intent
に添付されているBundle
に追加されます。 - Google アシスタントがその
Intent
を使ってアプリを起動し、バンドルされたパラメータにアプリがアクセスできるようにします。
BII「START_EXERCISE
」は、BII パラメータ「exercise.name
」をサポートしています。このパラメータを使って、アプリで記録するエクササイズの種類をユーザーが指定できるようにしましょう。
BII「START_EXERCISE
」をアプリに追加するには、対応する capability
を、サンプル プロジェクトの app/src/main/res/xml
ディレクトリにある shortcuts.xml
に追加します。コードは次のようになります。
<!-- shortcuts.xml -->
<capability android:name="actions.intent.START_EXERCISE">
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="PUT_YOUR_APPLICATION_ID_HERE"
android:targetClass="com.devrel.android.fitactions.FitMainActivity">
<parameter
android:name="exercise.name"
android:key="exerciseType"/>
</intent>
</capability>
PUT_YOUR_APPLICATION_ID_HERE
とある箇所は、前のステップで定義した独自の applicationId
に置き換えてください。
上のサンプル XML コードは以下を行います。
- BII「
START_EXERCISE
」のケーパビリティを宣言 - Google アシスタントがアプリを起動するために生成する Android
intent
を指定:targetPackage
およびtargetClass
属性で、受け取り側アクティビティを指定parameter
属性で、BII パラメータ「exercise.name
」を、送信先アクティビティが受け取ったBundle
エクストラ内のexerciseType
にマッピング
BII パラメータをインライン インベントリによって扱う
各 BII パラメータは、Google アシスタントのユーザークエリから抽出された要素を表します。たとえば、ユーザーが「OK Google, ExampleApp でランニングを開始」と言えば、Google アシスタントは「ランニング」を schema.org BII パラメータ「exercise.name
」へと抽出します。BII によっては、BII パラメータをアプリが受け付ける識別子群とマッチングするよう Google アシスタントに指示することも可能です。
この処理は、BII パラメータにインライン インベントリ要素をバインドすることによって行います。インライン インベントリとは、サポートされる BII パラメータ値(ここでは「ランニング」「ハイキング」「ジョギング」など)と、それぞれに対応するショートカット ID(EXERCISE_RUN
など)のセットです。このようにインベントリをバインドしておけば、Google アシスタントは生のクエリ値ではなくショートカット ID をフルフィルメント アクティビティに受け渡すことができます。
一部のパラメータ(exercise.name
など)は、機能するためにインライン インベントリを必要とします。このパラメータを処理するには、次のインベントリ shortcut
要素を shortcuts.xml
に追加します。
<!-- shortcuts.xml -->
<shortcuts>
<shortcut
android:shortcutId="running"
android:shortcutShortLabel="@string/activity_running">
<capability-binding android:key="actions.intent.START_EXERCISE">
<parameter-binding
android:key="exercise.name"
android:value="@array/runningSynonyms"/>
</capability-binding>
</shortcut>
<shortcut
android:shortcutId="walking"
android:shortcutShortLabel="@string/activity_walking">
<capability-binding android:key="actions.intent.START_EXERCISE">
<parameter-binding
android:key="exercise.name"
android:value="@array/walkingSynonyms"/>
</capability-binding>
</shortcut>
<shortcut
android:shortcutId="cycling"
android:shortcutShortLabel="@string/activity_cycling">
<capability-binding android:key="actions.intent.START_EXERCISE">
<parameter-binding
android:key="exercise.name"
android:value="@array/cyclingSynonyms"/>
</capability-binding>
</shortcut>
<capability> ... </capability>
</shortcuts>
上のコードでは、アプリがサポートする 3 種類のエクササイズ(ランニング、ウォーキング、サイクリング)について、それぞれインライン インベントリを表すショートカットを定義しています。各ショートカットは、次のようにケーパビリティとバインドされています。
- 各
capability-binding
要素のandroid:key
属性が、同一の BII(ケーパビリティに対応して定義されたSTART_EXCERCISE
)を参照しています。 - 各ショートカットの
parameter-binding
要素で、BII パラメータ「exercise.name
」がキーに指定されています。
インライン インベントリの類義語を追加する
前述のインベントリ ショートカットで、parameter-binding
要素の android:value
属性は、各インベントリ要素の類義語を集めた配列リソースを参照しています。類義語が定義されていれば、同じ要素タイプのバリエーション(たとえば「ランニング」「ジョギング」「スプリント」など)に、同一の shortcutId
を参照させることができます。次の類義語エントリ群を、プロジェクトの array.xml
リソースに追加しましょう。
<!-- array.xml -->
<array name="runningSynonyms">
<item>Run</item>
<item>Jog</item>
<item>Jogging</item>
<item>Sprint</item>
</array>
<array name="walkingSynonyms">
<item>Walk</item>
<item>Hike</item>
<item>Hiking</item>
</array>
<array name="cyclingSynonyms">
<item>Biking</item>
<item>Riding</item>
<item>Pedaling</item>
</array>
受け取った Android インテントを解決する
Android インテントは、Android が別のアプリにアクションをリクエストする際に使用する、メッセージング オブジェクトです。Google アシスタントは、トリガーされたケーパビリティの構成情報からインテントを生成することによって、ユーザーの音声クエリを解決(フルフィル)します。START_EXERCISE
ケーパビリティのインテントを解決するには、ターゲット クラス FitMainActivity
を更新して、受け取ったインテントと BII パラメータ群を処理できるようにします。
まず、Intent.handleIntent
関数を次のコードに置き換えます。
//FitMainActivity.kt
private fun Intent.handleIntent() {
when (action) {
// When the BII is matched, Intent.Action_VIEW will be used
Intent.ACTION_VIEW -> handleIntent(data)
// Otherwise start the app as you would normally do.
else -> showDefaultView()
}
}
次に、クラスに新しい handleIntent
関数を追加します。コードは次のとおりです。
//FitMainActivity.kt
/**
* Use extras provided by the intent to handle the different BIIs
*/
private fun handleIntent(data: Uri?) {
// path is normally used to indicate which view should be displayed
// i.e https://fit-actions.firebaseapp.com/start?exerciseType="Running" -> path = "start"
var actionHandled = true
val startExercise = intent?.extras?.getString(START_EXERCISE)
// Add stopExercise variable here
if (startExercise != null){
val type = FitActivity.Type.find(startExercise)
val arguments = Bundle().apply {
putSerializable(FitTrackingFragment.PARAM_TYPE, type)
}
updateView(FitTrackingFragment::class.java, arguments)
} // Add conditional for stopExercise
else{
// path is not supported or invalid, start normal flow.
showDefaultView()
// Unknown or invalid action
actionHandled = false
}
notifyActionSuccess(actionHandled)
}
上の Intent.handleIntent
関数では、ACTION_VIEW
がトリガーされると、App Action のインテント データが handleIntent
関数に渡されます。START_EXERCISE
インテントにバンドルされた BII パラメータ群は、intent?.extras?.getString(START_EXERCISE)
によって参照されています。関数の残りの部分では、FitTrackingFragment
を更新して、選択された startExercise
フィットネス タイプを表示しています。
App Action をテストする
App Actions の開発では、Google アシスタント プラグインを使用することで、各 Action をテストデバイスでプレビューできます。このプラグインは、各 Action のインテント パラメータ値を調整して、ユーザーが Google アシスタントへのリクエスト時に使用するフレーズのさまざまなバリエーションにアプリが対応できるかテストする際にも役立ちます。
プラグインで App Action をテストする手順:
- Android Studio でアプリを起動します([Run] > [Run App] を選択、または上部ツールバーの実行アイコンをクリック)。
- [Tools] > [App Actions] > [Google Assistant] > [App Actions Test Tool] を開きます。
- [Create Preview] をクリックします。求められた場合は、App Actions のポリシーと利用規約を確認して同意します。
- 組み込みインテント「
actions.intent.START_EXERCISE
」を選択します。 - [exercise] ボックスの値は、デフォルトの「running」のままにしておきます。
- [Run App Action] をクリックします。Google アシスタントがディープリンクによってアプリのエクササイズ用タイマーを開き、タイマーがランニング型のワークアウトを開始したことを確認します。
これで、BII「START_EXERCISE
」を使って初めての App Action を実装できました。次は、ユーザーがアプリでランニング型ワークアウトを終了できるようにしましょう。
5. エクササイズ終了の BII ケーパビリティを追加する
BII「actions.intent.STOP_EXERCISE
」は、「OK Google, ExampleApp でランニングを終了」などの音声によってワークアウト セッションを終了できる機能を提供します。フィットネス アプリにこの BII を実装するには、shortcuts.xml
に capability
をもうひとつ追加します。
<!-- shortcuts.xml -->
<capability android:name="actions.intent.STOP_EXERCISE">
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="PUT_YOUR_APPLICATION_ID_HERE"
android:targetClass="com.devrel.android.fitactions.FitMainActivity">
<!-- Eg. name = "Running" -->
<parameter
android:name="exercise.name"
android:key="stopExercise"/>
</intent>
</capability>
PUT_YOUR_APPLICATION_ID_HERE
とある箇所は、独自の applicationId
に置き換えてください。
BII パラメータをインライン インベントリによって扱う
この BII は BII「START_EXERCISE
」と同じ exercise.name
パラメータをサポートしており、終了させるアクティブなワークアウトをユーザーが指定できるようになっています。この処理を実装するには、shortcuts.xml
にインベントリ ショートカット要素をもうひとつ追加します。
<!-- shortcuts.xml -->
<shortcut
android:shortcutId="running"
android:shortcutShortLabel="@string/activity_running">
<capability-binding android:key="actions.intent.STOP_EXERCISE">
<parameter-binding
android:key="exercise.name"
android:value="@array/runningSynonyms"/>
</capability-binding>
</shortcut>
<shortcut
android:shortcutId="walking"
android:shortcutShortLabel="@string/activity_walking">
<capability-binding android:key="actions.intent.STOP_EXERCISE">
<parameter-binding
android:key="exercise.name"
android:value="@array/walkingSynonyms"/>
</capability-binding>
</shortcut>
<shortcut
android:shortcutId="cycling"
android:shortcutShortLabel="@string/activity_cycling">
<capability-binding android:key="actions.intent.STOP_EXERCISE">
<parameter-binding
android:key="exercise.name"
android:value="@array/cyclingSynonyms"/>
</capability-binding>
</shortcut>
受け取った Android インテントを解決する
FitMainActivity
クラスを更新して、受け取った Android インテント「STOP_EXERCISE
」をアプリが処理できるようにしましょう。まず、STOP_EXERCISE
のインテント データを保持させるため、handleIntent
関数に変数を追加します。
// FitMainActivity.kt
private fun handleIntent(data: Uri?) {
val stopExercise = intent?.extras?.getString(STOP_EXERCISE)
//...
}
次に、handleIntent
関数の条件ロジックを更新して、STOP_EXERCISE
インテントを処理できるようにします。
// FitMainActivity.kt
private fun handleIntent(data: Uri?) {
//...
if (startExercise != null){
val type = FitActivity.Type.find(startExercise)
val arguments = Bundle().apply {
putSerializable(FitTrackingFragment.PARAM_TYPE, type)
}
updateView(FitTrackingFragment::class.java, arguments)
} // Add conditional for stopExercise
<strong>
} else if(stopExercise != null){
// Stop the tracking service if any and return to home screen.
stopService(Intent(this, FitTrackingService::class.java))
updateView(FitStatsFragment::class.java)
}
</strong>
//...
}
上のコードでは、handleIntent
関数を更新して、受け取った Android インテント内に BII「STOP_EXERCISE
」がないか確認させています。同 BII が見つかれば、関数はアクティブなタイマーを停止させて、ホーム画面に戻ります。
App Action をテストする
Google アシスタント プラグインを使って App Action をテストしましょう。手順は次のとおりです。
- Android Studio でアプリを起動します([Run] > [Run App] を選択、または上部ツールバーの実行アイコンをクリック)。
- アプリで、ランニング型のエクササイズを新たに開始します。
- Android Studio でプラグインを開きます([Tools] > [App Actions] > [Google Assistant] > [App Actions Test Tool])。
- [Create Preview] をクリックします。
- 組み込みインテント「
actions.intent.STOP_EXERCISE
」を選択します。 - [exercise] ボックスの値は、デフォルトの「running」のままにしておきます。
- [Run App Action] をクリックします。Google アシスタントがワークアウトを終了させ、表示がホーム画面に戻ったことを確認します。
6. 次のステップ
おつかれさまでした
これで、Google アシスタントの組み込みインテントを使って、Android アプリを音声での操作に対応させる方法を確認できました。この Codelab では、以下のことを学びました。
- ユーザーが Google アシスタントを使ってアプリの特定の機能へ直行できるようにする方法
- インライン インベントリの使用方法
- Google アシスタント プラグインを使って BII をテストする方法
この後は
サンプルのフィットネス アプリをさらに改良してみるのもおすすめです。完成状態のプロジェクトは、GitHub のメインブランチから参照できます。
App Actions を使ったこのアプリの拡張についてさらに理解を深めるには、以下がおすすめです。
- App Actions の Codelab 集で他の記事も読んでみましょう。
- アプリを Google アシスタントへと拡張できる BII は、他にも豊富に用意されています。App Actions の組み込みインテントのリファレンスで確認してみましょう。
Actions on Google の世界をさらに深く理解したい方には、以下のリソースがおすすめです。
- developers.google.com/assistant: Actions on Google の公式ドキュメント サイト。
- App Actions のサンプル インデックス: App Actions の機能を理解するのに役立つサンプルアプリとサンプルコード。
- Actions on Google の GitHub リポジトリ: サンプルコードとライブラリ。
- r/GoogleAssistantDev: Google アシスタントに取り組むデベロッパーを対象とした Reddit 公式コミュニティ。
Twitter アカウント @ActionsOnGoogle で最新情報を発信していますので、よろしければフォローをお願いします。App Actions を使って作ったものは、ぜひハッシュタグ #appactions を付けてシェアしてみてください。
フィードバック アンケート
最後に、こちらのアンケートより、この Codelab についてのフィードバックをお聞かせいただければ幸いです。