在應用程式中加入 AppFunctions API

本指南說明如何在 Android 應用程式中整合 AppFunctions API、實作函式的邏輯,以及確認整合作業是否正常運作。

版本相容性

如要實作這項功能,專案的 compileSdk 必須設為 API 級別 36 以上。

應用程式不必驗證是否支援 AppFunctions,因為 AppFunctions Jetpack 程式庫會自動處理這項作業。如果系統支援這項功能,AppFunctionManager 會傳回執行個體,否則會傳回空值。

依附元件

在模組的 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 宣告為暫停函式。
    • 如果作業可能會封鎖執行緒,請切換至合適的協同程式調度工具。
  • 如果 isDescribedByKDoc 設為 true,函式說明或可序列化說明會編碼為 AppFunctionMetadata 的一部分,協助代理程式瞭解如何使用應用程式的 AppFunction。

在資訊清單中宣告 AppFunction 服務

在模組資訊清單中 (例如 src/main/AndroidManifest.xml),註冊 KSP 產生的服務宣告和 app_metadata 屬性。KSP 編譯器會產生具體服務類別 (TaskAppFunctionService),擴充抽象進入點類別,以及 assets/ 目錄中的對應 XML 結構定義。

<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 可用性

在控管 AppFunctions 時,請使用 AppFunctionManager API 明確啟用或停用函式。如果應用程式的某些功能不適用於所有使用者,閘道功能就非常實用。動態啟用或停用 AppFunctions 後,智慧系統就能確切掌握使用者在任何時間可用的功能。

如要安全地控管需要特定帳戶狀態的 AppFunction,請按照下列兩步驟程序操作:

步驟 1:預設停用這項功能

如要避免在驗證功能旗標前存取函式,請將 @AppFunction 註解的 isEnabled 參數設為 false

@AppFunction(isEnabled = false, isDescribedByKDoc = true)
suspend fun createTask(
    createTaskParams: CreateTaskParams,
): Task = TODO()

步驟 2:在執行階段動態啟用函式

針對每個 AppFunction 類別,編譯器會產生對應的類別,其中包含函式 ID 常數 (使用 Ids 後置字元)。您可以使用這些產生的 ID 常數和 AppFunctionManagerCompatsetAppFunctionEnabled 方法,在執行階段變更函式的啟用狀態。

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 導覽較難執行的工作。
  • 縮小存取範圍:建立 AppFunction,只允許虛擬服務專員存取滿足使用者特定要求所需的資料和動作。
  • 非私密資訊:請只分享非高度個人或機密的資料,或是使用者在動作情境中明確同意分享的資料。
  • 明確確認任何破壞性動作:請務必謹慎使用會執行破壞性動作 (例如刪除資料) 的函式。雖然代理程式可能會叫用這些意圖,但應用程式應加入自己的確認步驟,並使用清楚明確的語言說明意圖。此外,新增多個確認步驟也有助於確保使用者瞭解系統要求他們執行的動作。

驗證 AppFunction 整合

如要驗證是否已正確整合 AppFunctions,可以使用 adb shell cmd app_function

使用 adb shell cmd app_function list-app-functions | grep --after-context 10 $myPackageName 查看應用程式提供的 AppFunctions 詳細資料。

您也可以使用明確的 ID ("$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 測試代理程式 Android 應用程式,不需要任何提示。

如果您使用 Gemini 版 Android Studio 等聊天式助理驗證整合,請使用 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),您可以在 AI IDE (例如 Android Studio 內建 Gemini) 中使用 AppFunctions 代理程式技能,自動執行遷移作業。這項技能包含專屬的遷移規則,可引導代理程式整合建構依附元件、建立必要的 @AppFunctionServiceEntryPoint 服務包裝函式、解除內容參數的耦合,以及更新資訊清單宣告。