There are two primary user identity types for Android enterprise enrollments: Managed Google Play accounts and Managed Google Accounts. Managed Google Play accounts are device-centric, meaning they aren't tied to a specific user's Google identity. In contrast, Managed Google Accounts are linked to a user's corporate Google identity, which improves the user experience by keeping them logged in on their devices.
Managed Google Play accounts used to be the standard. However, Google now encourages all new development to use the improved enrollment flow, which defaults to creating Managed Google Accounts.
While guidance for the older implementation is provided at the end of this document for context, all new development should follow the new enrollment flow detailed here.
Overview
The improved device enrollment flow streamlines device setup by leveraging several new components and changing how custom Device Policy Controllers (DPCs) are implemented. This new approach requires custom DPC solutions to integrate with the Android Management API (AMAPI) SDK and Android Device Policy to perform device preparation and user enrollment functions.
The AMAPI SDK provides the necessary APIs for interacting with the Android Device Policy on the device itself. On the server side, Enterprise Mobility Management (EMM) solutions will use the Play EMM API to generate the enrollment tokens required to initiate the device enrollment process.
The Android Device Policy application now assumes a central role in handling device-side operations. The AMAPI SDK is used to manage its installation and necessary updates on the device. Android Device Policy also takes over the user authentication flow, handling user authentication directly and providing the user's identity to the EMM. If Google cannot authenticate the user for any reason, a new managed Google Play account is created and added to the device as a fallback.
API Integration
Before getting started, verify that you are using the latest version of the Play EMM API client and the AMAPI SDK.
Enrollment implementation guide
This guide provides the necessary steps for implementing enrollment. It covers preparing the environment, handling different enrollment methods, and managing the device lifecycle.
Prepare environment
Before initiating the account setup, it is necessary to prepare the device
environment. This preparation entails updating the Play Store to its latest
iteration and silently installing the Android Device Policy
(com.google.android.apps.work.clouddpc
) onto the device. Android Device Policy
installation is essential as it houses critical components of the Account Setup
process. EMMs need not perform manual environment preparation. Instead, they
should use the
EnvironmentClient
,
as documented at and adhere to the provided code examples.
Sample code
Before being able to use the AccountSetup API to add the work account on the device, the DPC must first verify that the device environment is ready.
Use
EnvironmentClientFactory
to instantiate anEnvironmentClient
and callprepareEnvironment
orprepareEnvironmentAsync
val notificationReceiverServiceName = ComponentName(context, NotificationReceiver::class.java) // An EMM should implement android.app.admin.DeviceAdminReceiver and use that // class to instantiate a ComponentName val admin = ComponentName(this, com.example.dpc.DeviceAdminReceiver::class.java) EnvironmentClientFactory.create(context) .prepareEnvironment( PrepareEnvironmentRequest.builder() .setRoles( listOf( Role.builder().setRoleType( Role.RoleType.DEVICE_POLICY_CONTROLLER ).build() ) ) .setAdmin(admin) .build(), notificationReceiverServiceName, ) [Proceed with AccountSetup]
This operation could take several seconds or minutes, since applications may be installed or updated to verify a proper working environment. Google recommends starting this process as early as possible in the background and showing appropriate UI while the user waits. When the operation completes, the device is ready for the DPC to use the AccountSetup API.
Enrollment flow
EMMs must discontinue using users.generateAuthenticationToken()
and
users.insert()
for all devices. Instead, EMMs must call the on-device
API
to perform end-user authentication. The new API will return the userId
and
email
to the DPC. If Google is not able to authenticate the user, a
Managed Google Play Account will be created and added to the device. In this
case, Google will return the userId
of that account.
Google now introduces the use of enrollment tokens, which must be passed to the authentication API. EMMs determine when and how to create the token, and it can be part of an existing enrollment payload (e.g., a QR code or Zero-touch configuration).
However, Google recommends creating the token on demand and replacing the existing API for Managed Google Play Accounts with the new API to minimize the change.



The improved custom DPC enrollment flow involves the following steps:
- Create Enrollment Token: The EMM creates an enrollment token using the Play EMM API.
- Prepare Environment: The custom DPC uses the Prepare Environment flow to verify the device is ready for enrollment.
- Initiate Enrollment: The custom DPC invokes the
startAccountSetup
API in the AMAPI SDK, passing the enrollment token. Note: The DPC must be either device owner or profile owner before calling this API. - Launch Google authentication activity: If required, the custom DPC
invokes the
launchAuthenticationActivity
API in the AMAPI SDK, passing theAccountSetupAttempt
. This starts a Google authentication activity, returning the user to the custom DPC upon successful authentication. The user can also skip this process. In this case, a Managed Google Play account will be added to the device. This option can be configured usinggoogleAuthenticationOptions
. - Finalize Enrollment: The AMAPI SDK notifies the custom DPC of the enrollment result.
- Enable Google services: Once a user's device with the
Managed Google Account is compliant with enterprise policies, the EMM must
call
Devices.setState()
. This action enables access to Google services for the account on the device. Without this call, the Play Store and other Google services won't function.
Account Setup - sample code
To initiate an account setup attempt, the calling app can use
AccountSetupClient
and call either thestartAccountSetup()
orstartAccountSetupFuture()
method. For an example implementation, see the following code sample:// Create AccountSetupClient val client = AccountSetupClientFactory.create( this, activityResultRegistry ) lifecycle.addObserver(client.lifecycleObserver) // Create adminComponent val notificationReceiver = ComponentName(this, AccountSetupNotificationReceiver::class.java) // Helper method to get enrollment token created with Play EMM API val enrollmentToken = getEnrollmentToken() val request = StartAccountSetupRequest.builder() .setEnrollmentToken(enteredText) .setNotificationReceiverServiceComponentName(notificationReceiver) .setAdminComponentName( ComponentName(this, com.example.dpc.DeviceAdminReceiver::class.java)) .build() try { val accountSetupAttempt = client.startAccountSetup(request) // handle attempt } catch (e: Exception) { // handle exception } ```
Implement
AccountSetupListener
interface and provide an implementation for how to handle the received status updates.Extend
NotificationReceiverService
and provide theAccountSetupListener
instance created in step 2 by overridinggetAccountSetupListener()
.// Handles account setup changes class AccountSetupNotificationReceiver : NotificationReceiverService(), AccountSetupListener { override fun getAccountSetupListener(): AccountSetupListener = this override fun onAccountSetupChanged(accountSetupAttempt: AccountSetupAttempt) { when (accountSetupAttempt.state.kind) { StateCase.ADDED_ACCOUNT -> { val enterpriseAccount = state.addedAccount() val userId = enterpriseAccount.userId val deviceId = enterpriseAccount.deviceId // Handle account added state. } StateCase.AUTHENTICATION_ACTIVITY_LAUNCH_REQUIRED -> { val request = LaunchAuthenticationActivityRequest.builder() .setAccountSetupAttempt(accountSetupAttempt) .build(); // Send the attempt to the foreground activity to call: accountSetupClient.launchAuthenticationActivity(request) } StateCase.ACCOUNT_SETUP_ERROR -> { // Handle error state. val failureReason = state.accountSetupError().failureReason } else -> { // Handle unknown account setup attempt state. } } } } ```
Add the extended
NotificationReceiverService
class to yourAndroidManifest.xml
and verify it is exported.<application> <service android:name = ".accountsetup.AccountSetupNotificationReceiver" android:exported = "true" /> </application>
If your app targets SDK 30 or later, then a queries element is needed in the
AndroidManifest.xml
to specify that it will interact with ADP.<queries> <package android:name="com.google.android.apps.work.clouddpc" /> </queries>
Testing guidance
This section provides a set of guidelines and best practices for testing your implementation.
Test PrepareEnvironment
Get Device's Current State: The EMM runs
adb shell dumpsys package com.google.android.apps.work.clouddpc | grep versionName
to get the version of the Android Device Policy present on the device. If the Android Device Policy is not installed, an empty output is expected.
Integrate PrepareEnvironment: The custom DPC invokes
prepareEnvironment
API in the AMAPI SDK, passing the correct request.Await PrepareEnvironment result: The custom DPC waits for the
prepareEnvironment
to complete.Confirm PrepareEnvironment success: On completion, EMM runs again
adb shell dumpsys package com.google.android.apps.work.clouddpc | grep versionName
This time the Android Device Policy version should be higher than in step 1.
Test Google Account authentication
- Create test enterprise: The EMM creates a test domain Google enterprise
linked to a test EMM, with
enterprises.generateSignupUrl
. - Enable Google authentication: The EMM enables Google authentication for the test enterprise following these instructions in the Google Admin console.
- Create Enrollment Token: The EMM creates an enrollment token using the Play EMM API with type userDevice.
- Initiate Enrollment: The custom DPC invokes the
startAccountSetup
API in the AMAPI SDK, passing the enrollment token. - Launch activity required: The AMAPI SDK notifies the custom DPC that an activity must be launched to authenticate the user.
- Authenticate the user: The custom DPC invokes
launchAuthenticationActivity
to start the activity. The user authenticates with a Managed Google Account (part of the enterprise created in step 1). - Finalize Enrollment: The AMAPI SDK notifies the custom DPC of the enrollment result.
Test skipping Google authentication
We will use the previously described setup.
This time, in step 7, the user presses Skip instead of authenticating with
their Google Account. The enrollment completes successfully, with a service
account on the device (i.e. the
AuthenticationType
is Anonymous).
Test userless devices
The improved custom DPC enrollment flow utilizes the followeing steps, when Google authentication is disabled:
- Create a test enterprise: This can be the same enterprise as created previously.
- Create Enrollment Token: The EMM creates an enrollmenttoken using the Play EMM API with type userlessDevice.
- Initiate Enrollment: The custom DPC invokes the
startAccountSetup
API in the AMAPI SDK, passing the enrollment token. - Finalize Enrollment: The AMAPI SDK notifies the custom DPC of the enrollment result.