Questa guida spiega come integrare l'API AppFunctions nella tua app per Android, implementare la logica per una funzione e verificare che l'integrazione funzioni correttamente.
Compatibilità delle versioni
Questa implementazione richiede che il progetto compileSdk sia impostato sul livello API 37 o superiore. Il progetto deve utilizzare il plug-in Android per Gradle 9.1.0 o versioni successive.
La tua app non è tenuta a verificare se le AppFunctions sono supportate; questa operazione viene gestita automaticamente all'interno della libreria Jetpack AppFunctions.
AppFunctionManager restituisce un'istanza se la funzionalità è supportata, altrimenti restituisce null.
Dipendenze
Aggiungi le dipendenze della libreria richieste al file build.gradle.kts (o build.gradle) del modulo e configura il plug-in KSP nel modulo dell'app di primo livello come mostrato:
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")
}
Implementa la logica di AppFunctions
Per implementare un'AppFunction per la tua app per Android, crea una classe che implementi la logica specifica delle AppFunction. Ciò comporta la creazione di classi di dati serializzabili per parametri e risposte, quindi la fornitura della logica di base all'interno del metodo della funzione.
Il codice seguente mostra un'implementazione di esempio per la creazione di un'attività nell'app TODO, inclusa la definizione di parametri personalizzati e tipi di risposta e la logica della funzione principale utilizzando un repository.
@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) }
Punti chiave sul codice
- Per impostazione predefinita, un'implementazione di AppFunction viene eseguita nel thread dell'interfaccia utente di Android.
Pertanto, un'operazione a lunga esecuzione deve eseguire le seguenti operazioni:
- Dichiara AppFunction come funzione di sospensione.
- Passa a un coroutine dispatcher adatto quando l'operazione potrebbe bloccare il thread.
- Quando
isDescribedByKDocè impostato sutrue, la descrizione della funzione o la descrizione serializzabile viene codificata come parte diAppFunctionMetadataper aiutare l'agente a capire come utilizzare l'AppFunction dell'app. A partire dalla versione 1.0.0-beta01,isDescribedByKDocnon ha un valore predefinito, quindi impostalo esplicitamente.
Dichiara il servizio AppFunction nel manifest
Registra la dichiarazione del servizio generata da KSP e la proprietà app_metadata all'interno del manifest del modulo, ad esempio in src/main/AndroidManifest.xml. Il compilatore KSP genera la classe di servizio concreta (TaskAppFunctionService) che estende la classe del punto di accesso astratto, insieme allo schema XML corrispondente nella directory 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" />
(Facoltativo) Attiva/disattiva la disponibilità di AppFunction in fase di runtime
Utilizza l'API AppFunctionManager per attivare o disattivare esplicitamente le funzioni quando
limiti le tue AppFunction. La limitazione può essere utile quando alcune funzionalità della tua app non sono disponibili per tutti gli utenti. Attivando o disattivando dinamicamente AppFunctions, il sistema di intelligence sa esattamente quali funzionalità sono disponibili per l'utente in un determinato momento.
Per proteggere in modo sicuro le AppFunction che richiedono uno stato dell'account specifico, segui una procedura in due passaggi:
Passaggio 1: Disattiva la funzione per impostazione predefinita
Per impedire l'accesso alla funzione prima che il flag di funzionalità venga verificato, imposta il parametro isEnabled dell'annotazione @AppFunctionDeclaration su false.
@AppFunctionDeclaration(isEnabled = false, isDescribedByKDoc = true) suspend fun createTask( createTaskParams: CreateTaskParams, ): Task = TODO()
Passaggio 2: Attiva dinamicamente la funzione in fase di runtime
Per ogni classe @AppFunctionServiceEntryPoint, il compilatore genera una classe corrispondente contenente costanti ID funzione (utilizzando un suffisso Ids).
Puoi utilizzare queste costanti ID generate insieme al metodo setAppFunctionEnabled di AppFunctionManager per modificare lo stato di attivazione di una funzione in fase di 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 } }
Considerazioni sui tipi di funzionalità da rendere disponibili
La sicurezza è sempre fondamentale. Quando scegli quali funzionalità della tua app rendere disponibili come AppFunction, è importante ricordare che gli agenti di sistema potrebbero elaborare le query degli utenti sul server per sfruttare le funzionalità avanzate degli LLM.
Per offrire un'esperienza utente ottimale ed evitare di esporre informazioni sensibili, ti consigliamo di seguire queste linee guida:
- Funzionalità che traggono vantaggio dal linguaggio naturale: rendi disponibili attività che un utente può esprimere più facilmente in una conversazione rispetto alla navigazione manuale nell'interfaccia utente.
- Accesso limitato: crea AppFunction che consentono all'agente di accedere solo ai dati e alle azioni necessari per soddisfare la richiesta specifica dell'utente.
- Informazioni non sensibili: condividi solo dati che non sono altamente personali o riservati o dati per i quali l'utente acconsente esplicitamente alla condivisione nel contesto dell'azione.
- Conferma inequivocabile per qualsiasi azione distruttiva: presta la massima attenzione alle funzioni che eseguono azioni distruttive (come l'eliminazione di dati). Anche se l'agente potrebbe richiamarle, l'app deve includere un proprio passaggio di conferma e utilizzare un linguaggio chiaro e non ambiguo in merito alle intenzioni. È anche utile aggiungere più di un passaggio di conferma per assicurarsi che l'utente sia consapevole di ciò che gli viene chiesto di fare.
Verifica l'integrazione di AppFunction
Per verificare se hai integrato correttamente AppFunctions, puoi utilizzare adb
shell cmd app_function.
Utilizza adb shell cmd app_function list-app-functions --package $myPackageName per visualizzare i dettagli delle AppFunctions fornite dalla tua app.
Puoi anche eseguire un'AppFunction direttamente dalla riga di comando utilizzando il suo identificatore esplicito ("$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\"}}'"
Per provare Android MCP in azione e verificare i workflow end-to-end senza bisogno di prompt, installa ed esegui l'app per Android AppFunctions testing agent sul tuo dispositivo.
Se stai verificando l'integrazione utilizzando assistenti basati su chat come Gemini in Android Studio, utilizza la skill di sviluppo AppFunctions o fornisci un prompt come il seguente:
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.
Esegui la migrazione da versioni API precedenti
Nella versione 1.0.0-alpha10, AppFunctions ha introdotto un'architettura @AppFunctionServiceEntryPoint in fase di compilazione che consolida le dipendenze della libreria e sostituisce i provider di configurazione legacy (AppFunctionConfiguration.Provider). La versione 1.0.0-alpha12 ha rimosso i provider legacy. La versione 1.0.0-alpha13 ha rinominato l'annotazione @AppFunction in
@AppFunctionDeclaration, mentre la versione 1.0.0-beta01 ha rinominato l'attributo
appfn:description nel file XML dei metadati dell'app in
appfn:instructions.
Se la tua app utilizza una versione precedente di AppFunctions (ad esempio 1.0.0-alpha09 o
1.0.0-alpha10), puoi automatizzare la migrazione utilizzando la skill dell'agente
AppFunctions in un IDE AI come Gemini in Android Studio. La skill contiene regole di migrazione dedicate che guidano un agente nel consolidamento delle dipendenze di build, nella creazione del wrapper del servizio @AppFunctionServiceEntryPoint richiesto, nel disaccoppiamento dei parametri di contesto, nell'aggiornamento delle dichiarazioni del manifest e nell'applicazione delle ridenominazioni della versione 1.0.0-beta01.
Competenze Android
Visualizza su GitHubImplementa AppFunctions
android skills add appfunctionsUse the AppFunctions skill to upgrade my app's AppFunctions implementation to 1.0.0-beta01.