Yum News Yum News

Technology  ·  Artificial Intelligence  ·  Developer Insights

Breaking
Gemini Task Automation Guide: India UK Japan Apps ✦   How to Set Up ChatGPT Wallet for Agent Purchases ✦   How to Set Up and Use Gemini Live on Apple CarPlay ✦   How to Set Up Gemini Live on Apple CarPlay ✦   How to Use the Gemini Decisions API for Fast Choices ✦   How to Use Gemini Task Automation on Pixel Phones   ✦   Gemini 3.8 Live launches with native audio dialogue  ✦  Android September Drop adds Find Hub memory  ✦  ML Kit now supports Gemini Nano on-device inference
Add AppFunctions to Your Android App: Step-by-Step
androidtutorialsai-toolsdeveloper

Add AppFunctions to Your Android App: Step-by-Step

Learn how to integrate the AppFunctions API so Gemini and on-device agents can call features in your Android app.

AppFunctions let Android apps expose structured capabilities that on-device agents such as Gemini can discover and execute. Instead of navigating your UI, an agent calls a typed function and receives a result.

The feature requires Android 16 (API 36) or higher and the Jetpack AppFunctions library. Gemini integration remains in private preview with trusted testers, yet you can implement and test the API today.

This guide walks through dependency setup, function implementation, manifest registration, verification, and security considerations using the current 1.0.0-alpha10 library.

Why AppFunctions Matter

AppFunctions act as the mobile counterpart to tools in the Model Context Protocol. Your app becomes an on-device server of callable tools. Authorized callers with the EXECUTE_APP_FUNCTIONS permission can list available functions, read their metadata, and invoke them.

Common examples include creating a task, searching notes, or sending a message. The OS indexes the functions so agents consider them alongside remote tools when fulfilling user requests.

Person holding an Android phone showing app icons

Add Dependencies and Configure KSP

Set compileSdk to 36 or higher. Add the AppFunctions library and its KSP compiler to your module-level build.gradle.kts:

dependencies {
    implementation("androidx.appfunctions:appfunctions:1.0.0-alpha10")
    ksp("androidx.appfunctions:appfunctions-compiler:1.0.0-alpha10")
}

Apply the KSP plugin in the same module. The library handles backward compatibility and returns null from AppFunctionManager.getInstance() on unsupported devices.

You can also install the official AppFunctions Android skill with android skills add appfunctions so Gemini in Android Studio or other agents can generate the boilerplate.

Implement the Function Logic

Create an abstract class that extends AppFunctionService and annotate it with @AppFunctionServiceEntryPoint. Inject your repositories with Hilt or your preferred DI framework.

@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 the supplied parameters.
     * @param createTaskParams Title and content for the new task.
     */
    @AppFunction(isDescribedByKDoc = true)
    suspend fun createTask(
        createTaskParams: CreateTaskParams
    ): Task = withContext(Dispatchers.IO) {
        if (createTaskParams.title == null && createTaskParams.content == null) {
            throw AppFunctionInvalidArgumentException("Title or content should be non-null")
        }
        val id = taskRepository.createTask(
            createTaskParams.title,
            createTaskParams.content
        )
        taskRepository.getTask(id)?.toTask()
            ?: throw AppFunctionElementNotFoundException("Task not found for ID = $id")
    }
}

Declare parameter and return types as data classes annotated with @AppFunctionSerializable. Functions run on the main thread by default, so long-running work must use suspend and switch dispatchers. Setting isDescribedByKDoc = true embeds the KDoc into the metadata that agents read.

Register the Service in the Manifest

KSP generates the concrete service class and the XML schema. Declare the service and the app metadata property in AndroidManifest.xml:

<service
    android:name=".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" />

Provide a short description of your app’s capabilities and operational patterns in res/xml/app_metadata.xml so agents understand when to choose your tools.

Developer coding on a laptop with dual monitors

Gate Functions at Runtime

Some features should stay disabled until a user signs in or meets a condition. Mark the function with isEnabled = false and toggle it later:

suspend fun onFeatureEnabled(context: Context) {
    AppFunctionManager.getInstance(context)
        ?.setAppFunctionEnabled(
            BaseTaskAppFunctionServiceIds.CREATE_TASK_ID,
            AppFunctionManager.APP_FUNCTION_STATE_ENABLED
        )
}

The compiler generates the *Ids constants. Catch exceptions on first launch because indexing may not finish immediately.

Verify the Integration

List registered functions with:

adb shell cmd app_function list-app-functions | grep --after-context 10 your.package.name

Execute one directly:

adb shell "cmd app_function execute-app-function \
  --package com.example.app \
  --function 'com.example.app.BaseTaskAppFunctionService#createTask' \
  --parameters '{\"createTaskParams\": {\"title\": \"Buy milk\"}}'"

Install the official testing agent from the android/appfunctions GitHub repository for interactive checks. You can also ask Gemini in Android Studio to act as a caller once the AppFunctions skill is installed.

If you already use Android CLI skills with agents, the same android skills workflow accelerates AppFunctions work. See our earlier post on Android CLI skills for any agent.

Security and Design Tips

  • Expose only actions that benefit from natural language (creating items, searching, summarizing).
  • Keep access narrow. Return only the data required for the request.
  • Avoid highly sensitive data such as passwords or full financial details.
  • Require explicit confirmation inside your app for destructive operations even if the agent calls the function.
  • Write clear KDoc so agents understand parameter constraints and side effects.
  • Prefer the Jetpack library over raw platform APIs for type safety and future compatibility.

Conclusion

AppFunctions give your Android app a structured way to participate in on-device agent workflows. Start with one high-value function, register the service, and verify it with ADB. As Gemini’s integration expands beyond private preview, well-described functions become the preferred path for reliable cross-app automation.

Update the library when newer alphas appear and use the official skill for migrations from earlier versions.

Sources

Share this story