android.app.appfunctions
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.
- Declare the function metadata in an XML asset file, as described above.
- Implement a class that extends
AppFunctionService. - Override the
AppFunctionService.onExecuteFunctionmethod to provide the execution logic. - Declare the service in your
AndroidManifest.xml, requiring theBIND_APP_FUNCTION_SERVICEpermission, and include an intent filter for theAppFunctionService.SERVICE_INTERFACEaction. - Reference the metadata XML file from the service declaration using a
<property>tag named"android.app.appfunctions".
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.
- Declare the function metadata in an XML asset file, as described above. Add a
<scope>activity|global</scope>tag to each<appfunction>to define its scope. See Function Scopes below for details. - Implement the
AppFunctioninterface to define the execution logic. - At runtime (e.g., in
onStart()), register yourAppFunctionimplementation usingAppFunctionManager.registerAppFunction. - Keep the returned
AppFunctionRegistrationobject and callAppFunctionRegistration.unregisterwhen the function is no longer relevant (e.g., inonStop()or beforestopForeground(boolean)).
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 specificActivityinstance. Multiple activities can register their own version of the same function simultaneously. Agents can differentiate between them using theAppFunctionActivityId.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. |
Interfaces
Classes
- AppFunctionActivityId
- AppFunctionActivityState
- AppFunctionManager
- AppFunctionMetadata
- AppFunctionName
- AppFunctionPackageMetadata
- AppFunctionSchemaMetadata
- AppFunctionSearchSpec
- AppFunctionSearchSpec.Builder
- AppFunctionService
- AppFunctionState
- AppFunctionUriGrant
- ExecuteAppFunctionRequest
- ExecuteAppFunctionRequest.Builder
- ExecuteAppFunctionResponse
- RegisterAppFunctionRequest
Exceptions