В этом руководстве объясняется, как интегрировать AppFunctions API в приложение Android, реализовать логику функции и проверить правильность интеграции.
Совместимость версий
Для этой реализации требуется, чтобы в вашем проекте compileSdk был установлен уровень API 37 или выше. В проекте должен использоваться плагин Android Gradle версии 9.1.0 или более поздней.
Приложению не нужно проверять, поддерживаются ли AppFunctions. Это автоматически выполняется в библиотеке Jetpack для AppFunctions.
AppFunctionManager возвращает экземпляр, если функция поддерживается, и null, если нет.
Связанные запросы
Добавьте необходимые зависимости библиотек в файл build.gradle.kts (или build.gradle) модуля и настройте плагин KSP в модуле приложения верхнего уровня, как показано ниже.
dependencies {
implementation("androidx.appfunctions:appfunctions:1.0.0-beta01")
// 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-beta01")
}
Реализуйте логику AppFunctions
Чтобы реализовать AppFunction для приложения Android, создайте класс, реализующий логику 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. */ @AppFunctionDeclaration(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 выполняется в потоке UI Android.
Поэтому продолжительная операция должна выполнять следующие действия:
- Объявите AppFunction как функцию приостановки.
- Переключитесь на подходящий диспетчер сопрограмм, если операция может заблокировать поток.
- Если для параметра
isDescribedByKDocзадано значениеtrue, описание функции или сериализуемое описание кодируется как частьAppFunctionMetadata, чтобы помочь агенту понять, как использовать AppFunction приложения. Начиная с версии 1.0.0-beta01 уisDescribedByKDocнет значения по умолчанию, поэтому его нужно задавать явно.
Объявите сервис 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, которым требуется определенное состояние аккаунта, выполните следующие действия:
Шаг 1. Отключить функцию по умолчанию
Чтобы функция не была доступна до проверки флага функции, задайте для параметра isEnabled аннотации @AppFunctionDeclaration значение false.
@AppFunctionDeclaration(isEnabled = false, isDescribedByKDoc = true) suspend fun createTask( createTaskParams: CreateTaskParams, ): Task = TODO()
Шаг 2. Динамически включать функцию во время выполнения
Для каждого класса @AppFunctionServiceEntryPoint компилятор генерирует соответствующий класс, содержащий константы идентификаторов функций (с суффиксом Ids).
Вы можете использовать эти сгенерированные константы идентификаторов вместе с методом setAppFunctionEnabled из AppFunctionManager, чтобы изменить статус включения функции во время выполнения.
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.
Чтобы обеспечить удобство для пользователей и избежать раскрытия конфиденциальной информации, рекомендуем следовать приведенным ниже инструкциям.
- Функции, которые выигрывают от использования естественного языка. Сделайте доступными задачи, которые пользователю проще выразить в разговоре, чем вручную перемещаться по интерфейсу.
- Ограничьте доступ. Создайте функции AppFunctions, которые предоставляют агенту доступ только к данным и действиям, необходимым для выполнения конкретного запроса пользователя.
- Неконфиденциальная информация. Передавайте только те данные, которые не являются личными или конфиденциальными, или те, на передачу которых пользователь дал явное согласие в контексте действия.
- Однозначное подтверждение для любого деструктивного действия. Будьте крайне осторожны с функциями, которые выполняют деструктивные действия, например удаляют данные. Даже если агент может вызвать их, ваше приложение должно включать собственный шаг подтверждения и использовать ясный, недвусмысленный язык в отношении намерений. Также полезно добавить несколько шагов подтверждения, чтобы пользователь точно понимал, что от него требуется.
Проверка интеграции AppFunction
Чтобы проверить, правильно ли вы интегрировали AppFunctions, используйте adb
shell cmd app_function.
Используйте adb shell cmd app_function list-app-functions --package $myPackageName, чтобы посмотреть сведения о функциях AppFunctions, которые предоставляет ваше приложение.
Вы также можете выполнить AppFunction непосредственно из командной строки, используя ее явный идентификатор ("$enclosingClassName#$methodName"):
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, и проверить сквозные рабочие процессы без подсказок, установите и запустите на устройстве Android приложение AppFunctions testing agent.
Если вы проверяете интеграцию с помощью чат-ботов, например 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.
Use the AppFunction descriptions to choose functions and parameters.
Переход с более ранних версий API
В версии 1.0.0-alpha10 в AppFunctions была добавлена архитектура @AppFunctionServiceEntryPoint, которая работает во время компиляции, объединяет зависимости библиотек и заменяет устаревшие поставщики конфигураций (AppFunctionConfiguration.Provider). В версии 1.0.0-alpha12 устаревшие поставщики были удалены. В версии 1.0.0-alpha13 аннотация @AppFunction переименована в @AppFunctionDeclaration, а в версии 1.0.0-beta01 атрибут appfn:description в XML-файле метаданных приложения переименован в appfn:instructions.
Если в вашем приложении используется более ранняя версия AppFunctions (например, 1.0.0-alpha09 или 1.0.0-alpha10), вы можете автоматизировать перенос с помощью навыка агента AppFunctions в ИИ-среде разработки, например Gemini в Android Studio. Навык содержит специальные правила переноса, которые помогают агенту объединить зависимости сборки, создать необходимую оболочку сервиса @AppFunctionServiceEntryPoint, разделить параметры контекста, обновить объявления манифеста и применить переименования 1.0.0-beta01.
Навыки работы с Android
Посмотреть на GitHubКак реализовать AppFunctions
android skills add appfunctionsUse the AppFunctions skill to upgrade my app's AppFunctions implementation to 1.0.0-beta01.