Panduan ini menjelaskan cara mengintegrasikan AppFunctions API ke dalam aplikasi Android, mengimplementasikan logika untuk fungsi, dan memverifikasi bahwa integrasi berfungsi dengan benar.
Kompatibilitas versi
Implementasi ini mengharuskan project compileSdk Anda ditetapkan ke level API
37 atau yang lebih tinggi. Project Anda harus menggunakan Plugin Android Gradle 9.1.0 atau yang lebih tinggi.
Aplikasi Anda tidak perlu memverifikasi apakah AppFunctions didukung; hal ini
ditangani secara otomatis dalam library Jetpack AppFunctions.
AppFunctionManager menampilkan instance jika fitur didukung, dan
menampilkan null jika tidak.
Dependensi
Tambahkan dependensi library yang diperlukan ke file build.gradle.kts (atau
build.gradle) modul Anda, dan konfigurasikan plugin KSP di modul aplikasi tingkat teratas seperti
yang ditunjukkan:
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")
}
Mengimplementasikan logika AppFunctions
Untuk mengimplementasikan AppFunction untuk aplikasi Android Anda, buat class yang mengimplementasikan logika AppFunctions tertentu. Hal ini melibatkan pembuatan class data yang dapat diserialisasi untuk parameter dan respons, lalu menyediakan logika inti dalam metode fungsi.
Kode berikut menunjukkan contoh implementasi untuk membuat tugas di aplikasi TODO, termasuk menentukan parameter kustom dan jenis respons serta logika fungsi utama menggunakan repositori.
@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) }
Poin penting tentang kode
- Secara default, implementasi AppFunction berjalan di UI thread Android.
Oleh karena itu, operasi yang berjalan lama harus melakukan hal berikut:
- Deklarasikan AppFunction sebagai fungsi penangguhan.
- Beralihlah ke dispatcher coroutine yang sesuai saat operasi dapat memblokir thread.
- Jika
isDescribedByKDocditetapkan ketrue, deskripsi fungsi atau deskripsi yang dapat diserialisasi akan dienkode sebagai bagian dariAppFunctionMetadatauntuk membantu agen memahami cara menggunakan AppFunction aplikasi. Mulai versi 1.0.0-beta01,isDescribedByKDoctidak memiliki nilai default, jadi tetapkan secara eksplisit.
Mendeklarasikan layanan AppFunction dalam manifes Anda
Daftarkan deklarasi layanan yang dihasilkan KSP dan properti app_metadata
di dalam manifes modul Anda, misalnya, di src/main/AndroidManifest.xml. Compiler
KSP menghasilkan class layanan konkret (TaskAppFunctionService)
yang memperluas class titik entri abstrak, beserta skema XML
yang sesuai di direktori 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" />
Opsional: Mengaktifkan/menonaktifkan ketersediaan AppFunction saat runtime
Gunakan AppFunctionManager API untuk mengaktifkan atau menonaktifkan fungsi secara eksplisit saat
membatasi AppFunction Anda. Pembatasan dapat berguna jika fitur tertentu di aplikasi Anda
tidak tersedia untuk semua pengguna. Dengan mengaktifkan atau menonaktifkan
AppFunctions secara dinamis, sistem kecerdasan akan mengetahui dengan pasti fitur mana yang tersedia
untuk pengguna Anda pada waktu tertentu.
Untuk membatasi AppFunction yang memerlukan status akun tertentu dengan aman, ikuti proses dua langkah:
Langkah 1. Menonaktifkan fungsi secara default
Agar fungsi tidak dapat diakses sebelum tombol fitur Anda
diverifikasi, tetapkan parameter isEnabled dari anotasi @AppFunctionDeclaration
Anda ke false.
@AppFunctionDeclaration(isEnabled = false, isDescribedByKDoc = true) suspend fun createTask( createTaskParams: CreateTaskParams, ): Task = TODO()
Langkah 2. Mengaktifkan fungsi secara dinamis saat runtime
Untuk setiap class @AppFunctionServiceEntryPoint, compiler akan membuat class yang sesuai yang berisi konstanta ID fungsi (menggunakan akhiran Ids).
Anda dapat menggunakan konstanta ID yang dihasilkan ini bersama dengan metode setAppFunctionEnabled
dari AppFunctionManager untuk mengubah status fungsi yang diaktifkan saat
runtime.
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 } }
Pertimbangan jenis fungsi yang akan disediakan
Keamanan selalu menjadi hal yang terpenting. Saat memilih kemampuan aplikasi yang akan disediakan sebagai AppFunction, penting untuk diingat bahwa agen sistem dapat memproses kueri pengguna di server untuk memanfaatkan kemampuan LLM tingkat lanjut.
Untuk memberikan pengalaman pengguna yang baik dan juga menghindari pengungkapan informasi sensitif, sebaiknya ikuti panduan berikut:
- Fungsi yang memanfaatkan bahasa alami: Sediakan tugas yang lebih mudah diungkapkan pengguna dalam percakapan daripada melalui navigasi UI manual.
- Akses terbatas: Buat AppFunction yang hanya memberi agen akses ke data dan tindakan yang diperlukan untuk memenuhi permintaan spesifik pengguna.
- Informasi tidak sensitif: Hanya bagikan data yang tidak terlalu pribadi atau rahasia, atau data yang secara eksplisit diizinkan oleh pengguna untuk dibagikan dalam konteks tindakan.
- Konfirmasi yang jelas untuk tindakan destruktif apa pun: Berhati-hatilah dengan fungsi yang melakukan tindakan destruktif (seperti menghapus data). Meskipun agen dapat memanggilnya, aplikasi Anda harus menyertakan langkah konfirmasi sendiri dan menggunakan bahasa yang jelas dan tidak ambigu tentang niatnya. Sebaiknya tambahkan juga lebih dari satu langkah konfirmasi untuk benar-benar memastikan bahwa pengguna mengetahui apa yang diminta untuk mereka lakukan.
Memverifikasi integrasi AppFunction
Untuk memverifikasi apakah Anda telah mengintegrasikan AppFunctions dengan benar, Anda dapat menggunakan adb
shell cmd app_function.
Gunakan adb shell cmd app_function list-app-functions --package $myPackageName untuk
melihat detail AppFunctions yang disediakan aplikasi Anda.
Anda juga dapat menjalankan AppFunction langsung dari command line menggunakan ID eksplisitnya ("$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\"}}'"
Untuk mencoba MCP Android dan memverifikasi alur kerja menyeluruh tanpa memerlukan perintah apa pun, instal dan jalankan aplikasi Android agen pengujian AppFunctions di perangkat Anda.
Jika Anda memverifikasi integrasi menggunakan asisten berbasis chat seperti Gemini di Android Studio, gunakan kemampuan pengembangan AppFunctions, atau berikan perintah seperti berikut:
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.
Bermigrasi dari versi API yang lebih rendah
Pada versi 1.0.0-alpha10, AppFunctions memperkenalkan arsitektur @AppFunctionServiceEntryPoint
waktu kompilasi yang menggabungkan dependensi library
dan menggantikan penyedia konfigurasi lama
(AppFunctionConfiguration.Provider). Versi 1.0.0-alpha12 menghapus penyedia
lama. Versi 1.0.0-alpha13 mengganti nama anotasi @AppFunction menjadi
@AppFunctionDeclaration, dan versi 1.0.0-beta01 mengganti nama
atribut appfn:description dalam file XML metadata aplikasi Anda menjadi
appfn:instructions.
Jika aplikasi Anda menggunakan AppFunctions versi lama (seperti 1.0.0-alpha09 atau
1.0.0-alpha10), Anda dapat mengotomatiskan migrasi menggunakan kemampuan agen
AppFunctions di IDE AI seperti Gemini di Android Studio. Skill ini berisi
aturan migrasi khusus yang memandu agen untuk menggabungkan dependensi
build, membuat wrapper layanan @AppFunctionServiceEntryPoint yang diperlukan, memisahkan parameter konteks, memperbarui deklarasi manifes, dan
menerapkan penggantian nama 1.0.0-beta01.
Keterampilan Android
Lihat di GitHubMengimplementasikan AppFunctions
android skills add appfunctionsUse the AppFunctions skill to upgrade my app's AppFunctions implementation to 1.0.0-beta01.