В этом руководстве рассказывается, как интегрировать AppFunctions API в приложение для Android, реализовать логику функции и проверить, правильно ли работает интеграция.
Совместимость с версиями
Для этого необходимо, чтобы в проекте 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
Чтобы реализовать AppFunction для приложения Android, создайте класс, который реализует определенную логику AppFunctions. Для этого нужно создать сериализуемые классы данных для параметров и ответов, а затем реализовать основную логику в методе функции.
В приведенном ниже примере кода показано, как создать задачу в приложении для создания списков дел, в том числе как определить специальные параметры и типы ответов, а также основную логику функции с помощью репозитория.
@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 выполняется в потоке UI Android.
Поэтому длительная операция должна:
- Объявите AppFunction как функцию приостановки.
- Переключаться на подходящий диспетчер сопрограмм, когда операция может заблокировать поток.
- Если для параметра
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, система искусственного интеллекта точно определяет, какие функции доступны пользователю в данный момент.
Чтобы безопасно ограничивать доступ к функциям приложений, требующим определенного состояния аккаунта, выполните следующие два шага:
Шаг 1. Как отключить функцию по умолчанию
Чтобы функция не была доступна до проверки флага функции, задайте для параметра isEnabled аннотации @AppFunction значение false.
@AppFunction(isEnabled = false, isDescribedByKDoc = true) suspend fun createTask( createTaskParams: CreateTaskParams, ): Task = TODO()
Шаг 2. Как динамически включить функцию во время выполнения
Для каждого класса AppFunction компилятор создает соответствующий класс, содержащий константы идентификаторов функций (с суффиксом Ids). Эти константы сгенерированных идентификаторов можно использовать вместе с методом setAppFunctionEnabled из AppFunctionManagerCompat, чтобы изменить состояние функции во время выполнения.
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, помните, что системные агенты могут обрабатывать запросы пользователей на сервере, чтобы использовать расширенные возможности больших языковых моделей.
Чтобы обеспечить удобство пользователей и не раскрывать конфиденциальную информацию, следуйте приведенным ниже рекомендациям.
- Функции, для которых подходит естественный язык. Сделайте доступными задачи, которые пользователю проще описать в разговоре, чем выполнить вручную с помощью интерфейса.
- Ограничьте доступ. Создайте AppFunctions, которые предоставляют агенту доступ только к данным и действиям, необходимым для выполнения конкретного запроса пользователя.
- Неконфиденциальная информация. Передавайте только данные, которые не являются строго личными или конфиденциальными, а также данные, которые пользователь явно разрешил передавать в контексте действия.
- Недвусмысленное подтверждение для любого деструктивного действия. Будьте крайне осторожны с функциями, которые выполняют деструктивные действия (например, удаляют данные). Хотя агент может вызывать эти функции, в приложении должен быть собственный шаг подтверждения с четким и однозначным описанием намерений. Также рекомендуется добавить несколько этапов подтверждения, чтобы пользователь точно понимал, что от него требуется.
Как проверить интеграцию AppFunction
Чтобы проверить, правильно ли вы интегрировали AppFunctions, можно использовать adb
shell cmd app_function.
Используйте adb shell cmd app_function list-app-functions | grep --after-context 10
$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.
Если вы проверяете интеграцию с помощью чат-ботов, например 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), вы можете автоматизировать переход с помощью навыка агента AppFunctions в ИИ-среде разработки, такой как Gemini в Android Studio. В навыке есть специальные правила переноса, которые помогают агенту объединить зависимости сборки, создать необходимый оберточный сервис @AppFunctionServiceEntryPoint, отделить параметры контекста и обновить декларации манифеста.
Навыки работы с Android
Посмотреть на GitHubКак реализовать AppFunctions
android skills add appfunctionsUse the AppFunctions migration skill to upgrade my app's AppFunctions implementation from 1.0.0-alpha09 to the 1.0.0-alpha10 @AppFunctionServiceEntryPoint architecture.