Added in API level 36

android.app.appfunctions


Android App Functions provides APIs for applications to expose functionality to the system for cross-app orchestration, and for system-privileged agents to discover and execute this functionality.

Most developers should implement app functions through the AppFunctions Jetpack SDK. The Jetpack SDK offers a more convenient and type-safe way to build app functions.

App Functions is currently a beta/experimental preview feature.

What are App Functions?

An app function is a discrete piece of functionality within an application that is made available for execution by trusted, system-privileged applications (referred to as "agents"). This allows agents to orchestrate complex workflows across multiple applications. For example, an agent could execute a "createNote" function in a note-taking app or a "playSong" function in a music app.

The App Functions framework interacts with two main players:

  • The App: Any application that exposes one or more app functions.
  • The Agent: A trusted application that discovers and executes app functions from other apps.

All interactions with the App Functions system start with AppFunctionManager and AppFunctionService.

The App: Providing Functions

An app can provide functions in two ways: through a dedicated service or by registering them at runtime. In both cases, functions must first be declared in an XML asset file.

Declaring Function Metadata

All app functions, regardless of implementation, must be declared in an XML asset file. This file defines the AppFunctionMetadata for each function.

Example XML declaration (e.g., assets/note_app_functions.xml):

<appfunctions>
     <appfunction>
         <id>createNote</id>
         <enabledByDefault>true</enabledByDefault>
         <parameters>...</parameters>
         <returnType>...</returnType>
         ...
     </appfunction>
 </appfunctions>
 

Functions implemented using AppFunctionService

This approach is suitable for functionality that is always available regardless of a component's lifecycle. The system will wake up your app to execute the function when executed by an agent.

Example AndroidManifest.xml:

<service
     android:name=".NoteAppFunctionService"
     android:permission="android.permission.BIND_APP_FUNCTION_SERVICE"
     android:exported="true">
   <property
       android:name="android.app.appfunctions"
       android:value="note_app_functions.xml" />
   <intent-filter>
     <action android:name="android.app.appfunctions.AppFunctionService" />
   </intent-filter>
 </service>
 

Important: Only one AppFunctionService implementation can be active in an app at a time.

Example implementation:

 class NoteAppFunctionService : AppFunctionService() {
     override fun onExecuteFunction(
         request: ExecuteAppFunctionRequest,
         callingPackage: String,
         callingPackageSigningInfo: SigningInfo,
         cancellationSignal: CancellationSignal,
         callback: OutcomeReceiver<ExecuteAppFunctionResponse, AppFunctionException>
     ) {
         when (request.functionIdentifier) {
             "createNote" -> {
                 // Implement createNote functionality.
                 callback.onResult(ExecuteAppFunctionResponse(...))
             }
             else -> {
                 // Should never happen, the system will automatically return FUNCTION_NOT_FOUND.
                 callback.onError(
                     AppFunctionException(
                         AppFunctionException.FUNCTION_NOT_FOUND,
                         "Unknown function: ${request.functionIdentifier}"
                     )
                 )
             }
         }
     }
 }
 

Important: It is strongly recommended that you do not alter your function\u2019s behavior based on the callingPackage or callingPackageSigningInfo. Your function should behave consistently for all callers to ensure a predictable experience. Starting in CINNAMON_BUN, the value of callingPackage will always be an empty string and callingPackageSigningInfo will always be an unknown signing info.

Functions implemented using AppFunctionManager.registerAppFunction

Starting in Android CINNAMON_BUN, this approach is suitable for functionality that is only available when the app is in a certain runtime state, such as functionality tied to a specific Activity.

Example AndroidManifest.xml:

<application ...>
   <property
       android:name="android.app.appfunctions"
       android:value="note_runtime_app_functions.xml" />
   ...
 </application>
 

Example implementation:

 class NoteActivity : Activity() {
     private lateinit var appFunctionRegistration: AppFunctionRegistration

     override fun onStart() {
         super.onStart()
         val appFunctionManager = getSystemService<AppFunctionManager>()
         appFunctionRegistration =
             appFunctionManager.registerAppFunction(
                 "getActiveNoteContent",
                 mainExecutor,
                 object : AppFunction {
                     override fun onExecuteAppFunction(
                         request: ExecuteAppFunctionRequest,
                         cancellationSignal: CancellationSignal,
                         callback:
                             OutcomeReceiver<ExecuteAppFunctionResponse, AppFunctionException>
                     ) {
                         // Implement getActiveNoteContent functionality.
                         callback.onResult(ExecuteAppFunctionResponse(...))
                     }
                 })
     }

     override fun onStop() {
         appFunctionRegistration.unregister()
         super.onStop()
     }
 }
 

Function Scopes

Functions implemented using AppFunctionManager.registerAppFunction can have different scopes, defined in their XML metadata:

  • AppFunctionMetadata.SCOPE_ACTIVITY: The function is tied to a specific Activity instance. Multiple activities can register their own version of the same function simultaneously. Agents can differentiate between them using the AppFunctionActivityId.
  • AppFunctionMetadata.SCOPE_GLOBAL: Only one implementation of the function can be registered at a time for the entire application. This is useful for functions that are tied to a singleton component, such as a foreground service.

Functions implemented using AppFunctionService are always considered AppFunctionMetadata.SCOPE_GLOBAL.

IMPORTANT: Functions provided with AppFunctionManager.registerAppFunction called from an Activity context should prefer ERROR(/#SCOPE_ACTIVITY). Only use ERROR(/#SCOPE_GLOBAL) for such functions if you are absolutely sure there can be only one instance of that activity.

The Agent: Discovering and Executing Functions

An agent's lifecycle with an app function typically involves three steps: discovery, state retrieval, and execution.

1. Discovering App Functions

Agents can find available functions using AppFunctionManager.searchAppFunctions. This method returns the AppFunctionMetadata for functions that match the given AppFunctionSearchSpec. This metadata contains essential, non-changing information about a function, such as its unique AppFunctionName and its execution scope.

2. Retrieving Runtime State

While AppFunctionMetadata is static, a function's state can change at runtime. For example, a function might be temporarily disabled by the app, or might be registered at runtime from one or more Activitys. Agents can query the current AppFunctionState using AppFunctionManager.getAppFunctionStates. This state indicates whether the function is currently enabled and, for functions of AppFunctionMetadata.SCOPE_ACTIVITY, which AppFunctionActivityId instances have registered it.

Agents can also use AppFunctionManager.getAppFunctionActivityStates to get the list of AppFunctionNames currently associated with a known AppFunctionActivityId. This is useful for example for agents coming from a VoiceInteractionSession, which they can convert to an AppFunctionActivityId using getAppFunctionActivityId(ActivityId).

To keep both AppFunctionMetadata and AppFunctionState up-to-date during an agentic runtime session, agents can use AppFunctionManager.observeAppFunctions to be notified of changes to function metadata and state.

3. Executing App Functions

Once an agent has the necessary metadata and confirms the function is enabled, it can execute the function using AppFunctionManager.executeAppFunction. The agent must construct an ExecuteAppFunctionRequest, which specifies the target function and any required parameters.

The execution can result in a successful ExecuteAppFunctionResponse or an AppFunctionException if an error occurs.

Interfaces

AppFunction An interface for implementing the logic of an app function registered at runtime using AppFunctionManager.registerAppFunction
AppFunctionObservation Result of AppFunctionManager.observeAppFunctions
AppFunctionObserver Interface for observing changes to app functions provided to AppFunctionManager.observeAppFunctions
AppFunctionRegistration Result of AppFunctionManager.registerAppFunction

Classes

AppFunctionActivityId An identifier of an Activity an app function can be associated with. 
AppFunctionActivityState The state of an activity from the perspective of app functions, retrieved using AppFunctionManager.getAppFunctionActivityStates
AppFunctionManager Provides access to App Functions. 
AppFunctionMetadata Contains an app function's metadata, essential for its invocation and discovery, retrieved using AppFunctionManager.searchAppFunctions
AppFunctionName Globally unique identifier for an app function. 
AppFunctionPackageMetadata Contains metadata about a package providing app functions. 
AppFunctionSchemaMetadata Contains identifying metadata for a predefined schema, which can describe well-known function signatures. 
AppFunctionSearchSpec Filter criteria for AppFunctionManager.searchAppFunctions
AppFunctionSearchSpec.Builder Builder for constructing AppFunctionSearchSpec
AppFunctionService Extend this class to implement app functions, that can be executed by AppFunctionManager.executeAppFunction
AppFunctionState Runtime state of an app function, retrieved using AppFunctionManager.getAppFunctionStates
AppFunctionUriGrant Uri for which access permission is to be granted to the caller of AppFunctionManager.executeAppFunction, provided to ExecuteAppFunctionResponse
ExecuteAppFunctionRequest A request to execute an app function, provided to AppFunctionManager.executeAppFunction
ExecuteAppFunctionRequest.Builder Builder for ExecuteAppFunctionRequest
ExecuteAppFunctionResponse The response to an app function execution, returned by AppFunctionManager.executeAppFunction
RegisterAppFunctionRequest A request to register an AppFunction implementation, provided to AppFunctionManager.registerAppFunctions

Exceptions

AppFunctionException App function related error.