In diesem Leitfaden wird erläutert, wie Sie die AppFunctions API in Ihre Android-App einbinden, die Logik für eine Funktion implementieren und prüfen, ob die Integration ordnungsgemäß funktioniert.
Versionskompatibilität
Für diese Implementierung muss Ihr Projekt compileSdk auf API-Level 36 oder höher festgelegt sein.
Ihre App muss nicht prüfen, ob AppFunctions unterstützt werden. Dies wird automatisch in der Jetpack-Bibliothek für AppFunctions erledigt.
AppFunctionManager gibt eine Instanz zurück, wenn das Feature unterstützt wird, andernfalls null.
Abhängigkeiten
Fügen Sie der build.gradle.kts-Datei (oder build.gradle-Datei) Ihres Moduls die erforderlichen Bibliotheksabhängigkeiten hinzu und konfigurieren Sie das KSP-Plug-in in Ihrem App-Modul auf oberster Ebene wie folgt:
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-Logik implementieren
Wenn Sie eine AppFunction für Ihre Android-App implementieren möchten, erstellen Sie eine Klasse, die die spezifische AppFunctions-Logik implementiert. Dazu müssen serialisierbare Datenklassen für Parameter und Antworten erstellt und dann die Kernlogik in der Funktionsmethode bereitgestellt werden.
Der folgende Code zeigt eine Beispielimplementierung zum Erstellen einer Aufgabe in der TODO-App, einschließlich der Definition benutzerdefinierter Parameter und Antworttypen sowie der Hauptfunktionslogik mithilfe eines Repositorys.
@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) }
Wichtige Punkte zum Code
- Standardmäßig wird eine AppFunction-Implementierung im Android-UI-Thread ausgeführt.
Daher sollte ein Vorgang mit langer Ausführungszeit Folgendes tun:
- Deklarieren Sie die AppFunction als Suspend-Funktion.
- Wechseln Sie zu einem geeigneten Koroutinen-Dispatcher, wenn der Vorgang den Thread blockieren könnte.
- Wenn
isDescribedByKDocauftruegesetzt ist, wird die Funktionsbeschreibung oder die serialisierbare Beschreibung als Teil desAppFunctionMetadatacodiert, damit der KI-Agent versteht, wie die AppFunction der App verwendet wird.
AppFunction-Dienst im Manifest deklarieren
Registrieren Sie die vom KSP generierte Dienstdeklaration und das Attribut app_metadata in Ihrem Modulmanifest, z. B. in src/main/AndroidManifest.xml. Der KSP-Compiler generiert die konkrete Dienstklasse (TaskAppFunctionService), die Ihre abstrakte Einstiegspunktklasse erweitert, zusammen mit dem entsprechenden XML-Schema in Ihrem assets/-Verzeichnis.
<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" />
Optional: AppFunction-Verfügbarkeit zur Laufzeit aktivieren oder deaktivieren
Verwenden Sie die AppFunctionManager API, um Funktionen explizit zu aktivieren oder zu deaktivieren, wenn Sie Ihre AppFunctions einschränken. Gating kann nützlich sein, wenn bestimmte Funktionen Ihrer App nicht für alle Nutzer verfügbar sind. Durch das dynamische Aktivieren oder Deaktivieren von AppFunctions weiß das KI-System genau, welche Funktionen für den Nutzer zu einem bestimmten Zeitpunkt verfügbar sind.
Wenn Sie AppFunctions, die einen bestimmten Kontostatus erfordern, sicher einschränken möchten, gehen Sie so vor:
Schritt 1: Funktion standardmäßig deaktivieren
Damit die Funktion nicht zugänglich ist, bevor Ihr Funktions-Flag verifiziert wurde, setzen Sie den Parameter isEnabled Ihrer @AppFunction-Annotation auf false.
@AppFunction(isEnabled = false, isDescribedByKDoc = true) suspend fun createTask( createTaskParams: CreateTaskParams, ): Task = TODO()
Schritt 2: Funktion zur Laufzeit dynamisch aktivieren
Für jede AppFunction-Klasse generiert der Compiler eine entsprechende Klasse mit Funktions-ID-Konstanten (mit dem Suffix Ids). Sie können diese generierten ID-Konstanten zusammen mit der Methode setAppFunctionEnabled aus AppFunctionManagerCompat verwenden, um den Aktivierungsstatus einer Funktion zur Laufzeit zu ändern.
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 } }
Überlegungen zu den Arten von Funktionen, die zur Verfügung gestellt werden sollen
Sicherheit hat immer oberste Priorität. Wenn Sie entscheiden, welche Funktionen Ihrer App als AppFunctions verfügbar gemacht werden sollen, sollten Sie bedenken, dass System-Agents Nutzeranfragen auf dem Server verarbeiten können, um erweiterte LLM-Funktionen zu nutzen.
Damit Nutzer eine gute Erfahrung machen und keine vertraulichen Informationen preisgegeben werden, empfehlen wir, die folgenden Richtlinien zu beachten:
- Funktionen, die von natürlicher Sprache profitieren: Stelle Aufgaben bereit, die für Nutzer in einer Unterhaltung einfacher zu formulieren sind als über die manuelle Navigation auf der Benutzeroberfläche.
- Zugriff einschränken: Erstellen Sie AppFunctions, die dem Agenten nur Zugriff auf Daten und Aktionen gewähren, die für die Erfüllung der spezifischen Anfrage des Nutzers erforderlich sind.
- Nicht vertrauliche Informationen: Gib nur Daten weiter, die nicht streng personenbezogen oder vertraulich sind, oder Daten, die der Nutzer im Rahmen der Aktion ausdrücklich zur Weitergabe freigegeben hat.
- Eindeutige Bestätigung für jede destruktive Aktion: Seien Sie bei Funktionen, die destruktive Aktionen ausführen (z. B. Löschen von Daten), äußerst vorsichtig. Auch wenn der KI-Agent sie aufrufen kann, sollte Ihre App einen eigenen Bestätigungsschritt enthalten und die Absichten klar und unmissverständlich formulieren. Es ist auch hilfreich, mehr als einen Bestätigungsschritt hinzuzufügen, um sicherzustellen, dass der Nutzer weiß, was er tun soll.
AppFunction-Integration prüfen
Mit adb
shell cmd app_function können Sie prüfen, ob Sie AppFunctions richtig eingebunden haben.
Mit adb shell cmd app_function list-app-functions | grep --after-context 10
$myPackageName können Sie sich Details zu den AppFunctions Ihrer App ansehen.
Sie können eine AppFunction auch direkt über die Befehlszeile mit ihrer expliziten Kennung ("$enclosingClassName#$methodName") ausführen:
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\"}}'"
Wenn Sie Android MCP in Aktion erleben und End-to-End-Workflows ohne Prompts prüfen möchten, installieren Sie die Android-App AppFunctions Testing Agent auf Ihrem Gerät und führen Sie sie aus.
Wenn Sie Ihre Integration mit chatbasierten Assistenten wie Gemini in Android Studio überprüfen, verwenden Sie den AppFunctions-Entwicklungsskill oder geben Sie einen Prompt wie den folgenden ein:
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.
Von niedrigeren API-Versionen migrieren
In Version 1.0.0-alpha10 wurde in AppFunctions eine @AppFunctionServiceEntryPoint-Architektur zur Kompilierzeit eingeführt, die Bibliotheksabhängigkeiten konsolidiert und Legacy-Konfigurationsanbieter (AppFunctionConfiguration.Provider) ersetzt.
Wenn Ihre App derzeit eine frühere Version von AppFunctions verwendet (z. B. 1.0.0-alpha09), können Sie die Migration mit dem AppFunctions-Agenten-Skill in einer KI-IDE wie Gemini in Android Studio automatisieren. Der Skill enthält spezielle Migrationsregeln, die einen Agenten anleiten, Ihre Build-Abhängigkeiten zu konsolidieren, den erforderlichen @AppFunctionServiceEntryPoint-Dienst-Wrapper zu erstellen, Kontextparameter zu entkoppeln und Ihre Manifestdeklarationen zu aktualisieren.
Android-Fähigkeiten
Auf GitHub ansehenAppFunctions implementieren
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.