이 가이드에서는 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 로직을 구현하는 클래스를 만드세요. 여기에는 파라미터와 응답을 위한 직렬화 가능한 데이터 클래스를 만든 다음 함수 메서드 내에서 핵심 로직을 제공하는 작업이 포함됩니다.
다음 코드는 저장소를 사용하여 맞춤 매개변수와 응답 유형, 기본 함수 로직을 정의하는 등 할 일 앱에서 작업을 만드는 구현 예를 보여줍니다.
@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를 동적으로 사용 설정하거나 사용 중지하면 인텔리전스 시스템에서 언제든지 사용자에게 제공되는 기능을 정확하게 알 수 있습니다.
특정 계정 상태가 필요한 AppFunctions를 안전하게 관리하려면 다음 두 단계를 따르세요.
1단계: 기본적으로 함수를 사용 중지
기능 플래그가 확인되기 전에 함수에 액세스할 수 없도록 하려면 @AppFunction 주석의 isEnabled 매개변수를 false로 설정하세요.
@AppFunction(isEnabled = false, isDescribedByKDoc = true) suspend fun createTask( createTaskParams: CreateTaskParams, ): Task = TODO()
2단계: 런타임에 함수를 동적으로 사용 설정
각 AppFunction 클래스에 대해 컴파일러는 함수 ID 상수가 포함된 해당 클래스를 생성합니다 (Ids 접미사 사용). AppFunctionManagerCompat의 setAppFunctionEnabled 메서드와 함께 생성된 ID 상수를 사용하여 런타임에 함수의 사용 설정 상태를 변경할 수 있습니다.
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 } }
사용 가능하게 할 기능 유형 고려사항
보안은 항상 최우선입니다. 앱의 어떤 기능을 AppFunction으로 사용할 수 있도록 할지 선택할 때 시스템 에이전트가 고급 LLM 기능을 활용하기 위해 서버에서 사용자 쿼리를 처리할 수 있다는 점을 기억해야 합니다.
민감한 정보가 노출되지 않으면서도 우수한 사용자 환경을 제공하려면 다음 가이드라인을 따르는 것이 좋습니다.
- 자연어의 이점을 활용하는 기능: 사용자가 수동 UI 탐색을 통해 표현하는 것보다 대화에서 더 쉽게 표현할 수 있는 작업을 제공합니다.
- 액세스 제한: 에이전트가 사용자의 특정 요청을 처리하는 데 필요한 데이터와 작업에만 액세스할 수 있는 AppFunction을 만듭니다.
- 민감하지 않은 정보: 매우 개인적이거나 기밀이 아닌 데이터 또는 사용자가 작업의 맥락에서 공유하는 데 명시적으로 동의한 데이터만 공유합니다.
- 파괴적인 작업에 대한 명확한 확인: 파괴적인 작업 (예: 데이터 삭제)을 실행하는 함수를 사용할 때는 매우 신중해야 합니다. 에이전트가 이를 호출할 수 있지만 앱에는 자체 확인 단계가 포함되어야 하며 의도에 관해 명확하고 모호하지 않은 언어를 사용해야 합니다. 사용자가 요청받는 작업을 인식하도록 확인 단계를 두 개 이상 추가하는 것도 도움이 됩니다.
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 테스트 에이전트 Android 앱을 설치하고 실행하세요.
Android 스튜디오의 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는 라이브러리 종속 항목을 통합하고 기존 구성 제공자(AppFunctionConfiguration.Provider)를 대체하는 컴파일 시간 @AppFunctionServiceEntryPoint 아키텍처를 도입했습니다.
현재 앱에서 이전 버전의 AppFunctions (예: 1.0.0-alpha09)를 사용하는 경우 Android 스튜디오의 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.