このガイドでは、AppFunctions API を Android アプリに統合し、関数のロジックを実装して、統合が正しく機能していることを確認する方法について説明します。
バージョンの互換性
この実装では、プロジェクトの compileSdk を API レベル 36 以降に設定する必要があります。
アプリで AppFunctions がサポートされているかどうかを確認する必要はありません。これは、AppFunctions Jetpack ライブラリ内で自動的に処理されます。
AppFunctionManager は、機能がサポートされている場合はインスタンスを返します。サポートされていない場合は
null を返します。
依存関係
必要なライブラリの依存関係をモジュールの build.gradle.kts(または build.gradle)ファイルに追加し、トップレベルのアプリ モジュールで KSP プラグインを次のように構成します。
dependencies {
implementation("androidx.appfunctions:appfunctions:1.0.0-alpha10")
// If this project uses any Kotlin source, use Kotlin Symbol Processing (KSP)
// See Add the KSP plugin to your project
ksp("androidx.appfunctions:appfunctions-compiler:1.0.0-alpha10")
}
AppFunctions のロジックを実装する
Android アプリに AppFunction を実装するには、特定の AppFunctions ロジックを実装するクラスを作成します。これには、パラメータとレスポンスのシリアル化可能なデータクラスを作成し、関数メソッド内でコアロジックを提供することが含まれます。
次のコードは、カスタム パラメータとレスポンス タイプを定義し、リポジトリを使用してメイン関数のロジックを定義するなど、 TODO アプリでタスクを作成する実装例を示しています。
@RequiresApi(36) @AndroidEntryPoint @AppFunctionServiceEntryPoint( serviceName = "TaskAppFunctionService", appFunctionXmlFileName = "task_app_function_service", ) abstract class BaseTaskAppFunctionService : AppFunctionService() { @Inject internal lateinit var taskRepository: TaskRepository /** * Creates a task based on [createTaskParams]. * * @param createTaskParams The parameter to describe how to create the task. */ @AppFunction(isDescribedByKDoc = true) suspend fun createTask( createTaskParams: CreateTaskParams, ): Task = withContext(Dispatchers.IO) { // Developers can use predefined exceptions to let the agent know // why it failed. if (createTaskParams.title == null && createTaskParams.content == null) { throw AppFunctionInvalidArgumentException("Title or content should be non-null") } val id = taskRepository.createTask( createTaskParams.title, createTaskParams.content ) return@withContext taskRepository .getTask(id) ?.toTask() ?: throw AppFunctionElementNotFoundException("Task not found for ID = $id") } // Maps internal TaskEntity private fun TaskEntity.toTask() = Task(id = id, title = title, content = description) }
コードに関する主なポイント
- デフォルトでは、AppFunction の実装は Android UI スレッドで実行されます。
そのため、長時間実行オペレーションでは次のことを行う必要があります。
- AppFunction を suspend 関数として宣言します。
- オペレーションによってスレッドがブロックされる可能性がある場合は、適切なコルーチン ディスパッチャに切り替えます。
isDescribedByKDocがtrueに設定されている場合、関数記述またはシリアル化可能な記述はAppFunctionMetadataの一部としてエンコードされ、エージェントがアプリの AppFunction の使用方法を理解するのに役立ちます。
マニフェストで AppFunction サービスを宣言する
KSP によって生成されたサービス宣言と app_metadata プロパティをモジュール マニフェスト(src/main/AndroidManifest.xml など)内に登録します。
KSP コンパイラは、抽象エントリ ポイント クラスを拡張する具体的なサービスクラス(TaskAppFunctionService)と、対応する XML スキーマを assets/ ディレクトリに生成します。
<service android:name="com.example.snippets.ai.TaskAppFunctionService" android:permission="android.permission.BIND_APP_FUNCTION_SERVICE" android:exported="true" tools:targetApi="36"> <property android:name="android.app.appfunctions.schema" android:value="app_functions_schema.xsd" /> <property android:name="android.app.appfunctions.v2" android:value="task_app_function_service.xml" /> <intent-filter> <action android:name="android.app.appfunctions.AppFunctionService" /> </intent-filter> </service> <property android:name="android.app.appfunctions.app_metadata" android:resource="@xml/app_metadata" />
省略可: 実行時に AppFunction の可用性を切り替える
AppFunctionManager API を使用して、AppFunctions をゲーティングするときに関数を明示的に有効または無効にします。ゲーティングは、アプリの特定の機能がすべてのユーザーに利用できない場合に便利です。AppFunctions を動的に有効または無効にすることで、インテリジェンス システムは、特定の時点でユーザーが利用できる機能を正確に把握できます。
特定のアカウント状態を必要とする AppFunctions を安全にゲーティングするには、次の 2 つの手順を行います。
ステップ 1. デフォルトで関数を無効にする
フィーチャー トグルが検証される前に関数にアクセスできないようにするには、@AppFunction アノテーションの isEnabled パラメータを false に設定します。
@AppFunction(isEnabled = false, isDescribedByKDoc = true) suspend fun createTask( createTaskParams: CreateTaskParams, ): Task = TODO()
ステップ 2. 実行時に関数を動的に有効にする
コンパイラは、各 AppFunction クラスに対して、関数 ID 定数を含む対応するクラス(Ids 接尾辞を使用)を生成します。生成された ID 定数と AppFunctionManagerCompat の setAppFunctionEnabled メソッドを使用して、実行時に関数の有効状態を変更できます。
suspend fun onFeatureEnabled(context: Context) { try { AppFunctionManager.getInstance(context) ?.setAppFunctionEnabled( BaseTaskAppFunctionServiceIds.CREATE_TASK_ID, AppFunctionManager.APP_FUNCTION_STATE_ENABLED, ) } catch (e: Exception) { // Handle exception: AppFunctions indexation may not be fully completed // upon initial app startup. } } suspend fun onFeatureDisabled(context: Context) { try { AppFunctionManager.getInstance(context) ?.setAppFunctionEnabled( BaseTaskAppFunctionServiceIds.CREATE_TASK_ID, AppFunctionManager.APP_FUNCTION_STATE_DISABLED, ) } catch (e: Exception) { // Handle exception } }
利用可能にする機能の種類の考慮事項
セキュリティは常に最優先事項です。アプリのどの機能を AppFunctions として利用可能にするかを選択する際は、システム エージェントがサーバーでユーザー クエリを処理して高度な LLM 機能を利用する可能性があることに注意してください。
機密情報を公開せずに優れたユーザー エクスペリエンスを提供するには、次のガイドラインに沿って対応することをおすすめします。
- 自然言語のメリットがある機能: 手動の UI ナビゲーションよりも会話で表現しやすいタスクを利用できるようにします。
- アクセスを絞り込む: ユーザーの特定のリクエストを処理するために必要な データとアクションにのみエージェントがアクセスできる AppFunctions を作成します。
- 機密性の低い情報: 非常に個人的な情報 や機密情報ではないデータ、またはアクションのコンテキストでユーザーが明示的に共有に同意したデータのみを共有します。
- 破壊的なアクションに対する明確な確認: データを削除するなど、破壊的なアクションを実行する関数には十分 注意してください。エージェントが呼び出す場合でも、アプリには独自の確認ステップを含め、意図について明確で曖昧でない言語を使用する必要があります。 また、ユーザーが何を求められているかを確実に把握できるように、確認ステップを複数追加することをおすすめします。
AppFunction の統合を確認する
AppFunctions が正しく統合されているかどうかを確認するには、adb
shell cmd app_function を使用します。
adb shell cmd app_function list-app-functions | grep --after-context 10
$myPackageName を使用して、アプリが提供する AppFunctions の詳細を確認します。
明示的な識別子("$enclosingClassName#$methodName")を使用して、コマンドラインから AppFunction を直接実行することもできます。
adb shell "cmd app_function execute-app-function \
--package com.example.android.appfunctions \
--function 'com.example.android.appfunctions.BaseTaskAppFunctionService#createTask' \
--parameters '{\"createTaskParams\": {\"title\": \"Buy milk\", \"content\": \"From grocery store\"}}'"
Android MCP の動作を確認し、プロンプトなしでエンドツーエンドのワークフローを確認するには、デバイスに AppFunctions testing agent Android アプリをインストールして実行します。
Android Studio の Gemini などのチャットベースのアシスタントを使用して統合を確認する場合は、AppFunctions 開発スキルを使用するか、次のようなプロンプトを指定します。
Execute `adb shell cmd app_function` to learn how the tool works, then act as a
chat agent aiming to invoke AppFunctions to fulfil user prompts for this app.
Rely on the AppFunction description as instructions.
下位の API バージョンから移行する
バージョン 1.0.0-alpha10 では、AppFunctions にコンパイル時の @AppFunctionServiceEntryPoint アーキテクチャが導入され、ライブラリの依存関係が統合され、従来の構成プロバイダ(AppFunctionConfiguration.Provider)が置き換えられました。
アプリで現在以前のバージョンの AppFunctions(
1.0.0-alpha09 など)を使用している場合は、Android Studio の Gemini などの AI IDE で AppFunctions エージェント
スキルを使用して移行を自動化できます。このスキルには、ビルドの依存関係の統合、必要な @AppFunctionServiceEntryPoint サービス ラッパーの作成、コンテキスト パラメータの分離、マニフェスト宣言の更新を行うエージェントをガイドする専用の移行ルールが含まれています。
AI エージェントで自動移行を開始するには、次のようなプロンプトを使用します。
Use the AppFunctions migration skill to upgrade my app's AppFunctions implementation from 1.0.0-alpha09 to the 1.0.0-alpha10 @AppFunctionServiceEntryPoint architecture.