In dieser Anleitung 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 Einbindung korrekt funktioniert.
Versionskompatibilität
Für diese Implementierung muss compileSdk Ihres Projekts auf API-Level 36 oder höher festgelegt sein.
Ihre App muss nicht prüfen, ob AppFunctions unterstützt werden. Das wird automatisch in der AppFunctions Jetpack-Bibliothek erledigt.
AppFunctionManager gibt eine Instanz zurück, wenn die Funktion unterstützt wird, andernfalls wird „null“ zurückgegeben.
Abhängigkeiten
Fügen Sie die erforderlichen Bibliotheksabhängigkeiten der Datei build.gradle.kts (oder „build.gradle“) Ihres Moduls hinzu und konfigurieren Sie das KSP-Plug-in im App-Modul der obersten Ebene wie unten gezeigt:
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 Antwort typen 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 UI-Thread von Android ausgeführt.
Bei einem Vorgang mit langer Ausführungszeit sollte daher Folgendes berücksichtigt werden:
- Deklarieren Sie die AppFunction als Suspend-Funktion.
- Wechseln Sie zu einem geeigneten Coroutine-Dispatcher, wenn der Vorgang den Thread blockieren könnte.
- Wenn
isDescribedByKDocauftruegesetzt ist, wird die Funktionsbeschreibung oder die serialisierbare Beschreibung als Teil vonAppFunctionMetadatacodiert, damit der Agent weiß, wie die AppFunction der App verwendet werden kann.
AppFunction-Dienst im Manifest deklarieren
Registrieren Sie die vom KSP generierte Dienstdeklaration und die app_metadata-Property im Manifest Ihres Moduls, z. B. in src/main/AndroidManifest.xml. Der KSP-Compiler generiert die konkrete Dienstklasse (TaskAppFunctionService), die Ihre abstrakte Einstiegspunktklasse erweitert, sowie das entsprechende XML-Schema im Verzeichnis 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" />
Optional: AppFunction-Verfügbarkeit zur Laufzeit umschalten
Verwenden Sie die AppFunctionManager API, um Funktionen explizit zu aktivieren oder zu deaktivieren, wenn Sie Ihre AppFunctions einschränken. Das 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 Ihren Nutzer zu einem bestimmten Zeitpunkt verfügbar sind.
Wenn Sie AppFunctions, für die ein bestimmter Kontostatus erforderlich ist, sicher einschränken möchten, führen Sie die folgenden beiden Schritte aus:
Schritt 1: Funktion standardmäßig deaktivieren
Damit die Funktion nicht zugänglich ist, bevor das Funktions-Flag überprüft wurde, setzen Sie den Parameter isEnabled Ihrer Annotation @AppFunction 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 Konstanten für die Funktions-ID (mit dem Suffix „Ids“). Sie können diese generierten ID-Konstanten zusammen mit der Methode setAppFunctionEnabled aus AppFunctionManagerCompat verwenden, um den aktivierten Status 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 verfügbar gemacht werden sollen
Sicherheit hat immer höchste Priorität. Wenn Sie auswählen, welche Funktionen Ihrer App als AppFunctions verfügbar gemacht werden sollen, müssen Sie bedenken, dass System-Agents Nutzeranfragen auf dem Server verarbeiten können, um erweiterte LLM-Funktionen zu nutzen.
Um eine optimale Nutzererfahrung zu bieten und gleichzeitig die Offenlegung sensibler Informationen zu vermeiden, empfehlen wir Ihnen, die folgenden Richtlinien zu beachten:
- Funktionen, die von natürlicher Sprache profitieren: Stellen Sie Aufgaben zur Verfügung die ein Nutzer in einem Gespräch einfacher ausdrücken kann als durch manuelle UI Navigation.
- Eingeschränkter Zugriff: Erstellen Sie AppFunctions, die dem Agent nur Zugriff auf die Daten und Aktionen gewähren, die erforderlich sind, um die spezifische Anfrage des Nutzers zu erfüllen.
- Nicht sensible Informationen: Geben Sie nur Daten weiter, die nicht hochgradig personenbezogen oder vertraulich sind, oder Daten, deren Weitergabe der Nutzer im Rahmen der Aktion ausdrücklich zustimmt.
- Eindeutige Bestätigung für jede destruktive Aktion: Seien Sie äußerst vorsichtig bei Funktionen, die destruktive Aktionen ausführen (z. B. Daten löschen). Der Agent kann sie zwar aufrufen, aber Ihre App sollte einen eigenen Bestätigungsschritt enthalten und eine klare, eindeutige Sprache verwenden, um die Absichten zu beschreiben. Es ist auch hilfreich, mehr als einen Bestätigungsschritt hinzuzufügen, um wirklich sicherzustellen, dass der Nutzer weiß, was er tun soll.
AppFunction-Einbindung prüfen
Mit adb
shell cmd app_function können Sie prüfen, ob Sie AppFunctions korrekt eingebunden haben.
Verwenden Sie adb shell cmd app_function list-app-functions | grep --after-context 10
$myPackageName, um Details zu den AppFunctions zu sehen, die Ihre App bereitstellt.
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 Eingabeaufforderungen prüfen möchten, installieren Sie die AppFunctions testing agent Android-App auf Ihrem Gerät und führen Sie sie aus.
Wenn Sie Ihre Einbindung mit chatbasierten Assistenten wie Gemini in Android Studio prüfen, verwenden Sie die AppFunctions-Entwicklungsfunktion oder geben Sie eine Eingabeaufforderung wie die folgende an:
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 mit AppFunctions eine @AppFunctionServiceEntryPoint-Architektur zur Kompilierzeit eingeführt, die Bibliotheksabhängigkeiten konsolidiert und ältere 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 der AppFunctions-Agent
Funktion in einer KI-IDE wie Gemini in Android Studio automatisieren. Die Funktion enthält spezielle Migrationsregeln, die einen Agent anleiten, Ihre Build-Abhängigkeiten zu konsolidieren, den erforderlichen @AppFunctionServiceEntryPoint-Dienst-Wrapper zu erstellen, Kontextparameter zu entkoppeln und Ihre Manifestdeklarationen zu aktualisieren.
Android-Funktionen
Auf GitHub ansehenAppFunctions implementieren
android skills add --skill 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.