The application roles feature allows an IT admin to grant special privileges to a managed application on an Android-powered device. By assigning a specific role, an app can be exempted from power and background restrictions, suspension, hibernation (on Android 14+) and have user controls (i.e. includes user actions like force-stopping and clearing app data) disabled (on Android 11+), allowing it to perform its critical function without interruption. Additionally, the app can be notified of its assigned roles, which allows it to bootstrap itself without user intervention.
Prerequisites
The device is managed by an AMAPI based EMM (EMMs using a custom DPC are not supported).
Prepare your app for using the feature
Integrating with the AMAPI SDK is only required if the app wants to be notified of its assigned roles which allows it to bootstrap itself (i.e. auto launch without user interaction).
Integrate with the AMAPI SDK in your app
You can find more information about AMAPI SDK and how to add it to your app in the AMAPI SDK integration guide.
Add the required metadata to the app's manifest
Android Device Policy (ADP) needs to know the ComponentName
of your class
which implements NotificationReceiverService
to notify your app of its
assigned roles. You must tag your service in AndroidManifest.xml
suitably so
that it can be automatically discovered by ADP.
- Your app must have exactly one service which is
enabled
and hasmeta-data
withandroid:name
equal tocom.google.android.managementapi.notification.NotificationReceiverService.SERVICE_APP_ROLES
- This service must have
android:exported
set totrue
- The
android:value
of themeta-data
must be set to an empty string
<service
android:name=".MyNotificationReceiverService"
android:exported="true">
<meta-data android:name="com.google.android.managementapi.notification.NotificationReceiverService.SERVICE_APP_ROLES" android:value="" />
</service>
If you are testing the COMPANION_APP
role, you should also add the following
meta-data
to your service so that Android Device Policy can send local
command status updates to your app:
<meta-data android:name="com.google.android.managementapi.notification.NotificationReceiverService.SERVICE_COMMAND_STATUS" android:value="" />
Create a service extending NotificationReceiverService (or update the existing)
Create or update your existing NotificationReceiverService
and implement an
AppRolesListener
to listen for roles assigned to your app. Only
getAppRolesListener()
is required for listening for roles assigned to your
app. If your app is assigned a COMPANION_APP
role you should also implement
getCommandListener()
:
import android.util.Log
import com.google.android.managementapi.approles.AppRolesListener
import com.google.android.managementapi.approles.model.AppRolesSetRequest
import com.google.android.managementapi.approles.model.AppRolesSetResponse
import com.google.android.managementapi.commands.CommandListener
import com.google.android.managementapi.commands.model.Command
import com.google.android.managementapi.notification.NotificationReceiverService
class MyNotificationReceiverService : NotificationReceiverService() {
// If your app wants to listen for roles assigned
override fun getAppRolesListener(): AppRolesListener =
object : AppRolesListener {
override fun onAppRolesSet(request: AppRolesSetRequest): AppRolesSetResponse {
val roleTypes = request.roles.map { role -> role.roleType }
Log.i(TAG, "onAppRolesSet: $roleTypes")
return AppRolesSetResponse.getDefaultInstance()
}
}
// If your app wants to listen for local command status updates
// Only relevant for COMPANION_APP role
override fun getCommandListener(): CommandListener {
return object : CommandListener {
override fun onCommandStatusChanged(command: Command) {
Log.i(TAG, "onCommandStatusChanged")
}
}
}
private companion object {
const val TAG = "MyNotificationReceiverService"
}
}
Your app can be notified multiple times if its roles change multiple times. If
all roles are removed, your app will still be notified with an empty list of
roles. This notification will get your app out of stopped state and along with
the exemptions granted for your app, your app can bootstrap itself without any
user interaction. Thanks to the app roles notification and exemptions, your app
can listen for ACTION_BOOT_COMPLETED
broadcasts. If your app depends on
its managed configurations to bootstrap itself, see
Set up managed configurations on how to read and listen
for changes.
Provision the device with app roles policies
App developers can test assigning app roles to their application using and EMM or following the Android Management API quickstart. The AMAPI Colab notebook lets you enroll an enterprise, create a policy,and provision a device.
Set the policy for your app with app roles
Set up a policy
with the app roles that your app is intended to have using the
ApplicationPolicy.roles
.
The following example shows how to configure the role for MTD apps:
{
"applications": [
{
"packageName": "com.example.mtd",
"installType": "FORCE_INSTALLED",
"roles": [
{ "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
]
}
]
}
Before assigning the roles as specified in the policy the system will check that
the app's signing key certificate fingerprint on the device matches the one from
the Play Store.
If the fingerprint is different, the roles are not going to be assigned to the
app and NonComplianceReason.APP_SIGNING_CERT_MISMATCH
non-compliance will be reported to the EMM.
{
"applications": [
{
"packageName": "com.example.mtd",
"installType": "FORCE_INSTALLED",
"signingKeyCerts": [
{ "signingKeyCertFingerprintSha256": "base64-encoded-sha256" }
],
"roles": [
{ "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
]
}
]
}
If your app has managed configuration, the IT admin can set up an initial
configuration for the relevant restriction
s in the application policy:
{
"applications": [
{
"packageName": "com.example.mtd",
"installType": "FORCE_INSTALLED",
"roles": [
{ "roleType": "MOBILE_THREAT_DEFENSE_ENDPOINT_DETECTION_RESPONSE" }
],
"managedConfiguration": {
"<key>": "<value>"
}
}
]
}