Skip to content

Instantly share code, notes, and snippets.

@bashenk
Last active June 23, 2025 01:59
Show Gist options
  • Save bashenk/58c6dd883b177ee6e6ed1c533f3e8066 to your computer and use it in GitHub Desktop.
Save bashenk/58c6dd883b177ee6e6ed1c533f3e8066 to your computer and use it in GitHub Desktop.
Creating a QR Code for Android Device Enrollment

Creating a QR Code for Android Device Enrollment

Android Enterprise Documentation: Create a QR code

Always required

Required if a DPC isn't already installed on the device

Recommended if the device isn't already connected to Wi-Fi

Optional


EMM Provisioning

Android Zero-Touch Enrollment EMM Provisioning Guide

👍 EMM Recommended

Use the following intent extras to set up your DPC

👎 EMM Not recommended

Don't include the following extras that you might use in other enrollment methods


Additional references

@robin-thoni
Copy link

How we decide if we have to use PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM or PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM?

PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM identifies a particular package build

PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM identifies the publisher

The later allows to install an updated version of the package without requiring regenerating the QR code. The first one ensures you're installing a trusted and/or well tested version of the package.

@shaikh-kamran
Copy link

Okay so i can use any one, both will work in any android version?

@robin-thoni
Copy link

EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM was added in API 21 (Android 5.0), while EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM was added in API 23 (Android 6.0)

@MichMich
Copy link

Thanks for this super complete piece information. Much appreciated. Can anyone confirm if this method should allow me to generate a QR to install an APK as “Device Owner” without the use of an MDM or Android Enterprise?

@robin-thoni
Copy link

Yes, you'll be able to install a Device Owner app using this method. You can try it out using this Google sample app.

@MichMich
Copy link

Thanks for the rapid response! I really appreciate it.

@MichaelTeeuw
Copy link

The Sample app seems to work. Good starter point to figure out why I run into issues with my app. Again: thanks for your help!

@MichaelTeeuw
Copy link

I apologies for using this Gist for asking this question, but does anybody happen to have a super barebones DPC kotlin application I can take a look at? I've been working on my own but unfortunately I'm unable to correctly use it using the QR method. After scanning the code, the app is being downloaded, android displays “Device belongs to your organization”, but then it fails. Debugging by fetching the logs is a PITA, but it looks like Android is trying to fall back on the (non existent) CloudDPC app in stead of using my app as the DPC.

Unable to start service Intent { cmp=com.android.managedprovisioning/com.google.android.apps.work.clouddpc.base.managedprovisioning.provisioning.ProvisioningService } U=0: not found

I've got the feeling my app is not correctly registering itself as a DPC app. Any help is highly appreciated!

@MichaelTeeuw
Copy link

Finally found it! For anyone running into the same issue; you need the following additional activities (next to your DeviceAdminReceiver):

        <activity
            android:name=".GetProvisioningModeActivity"
            android:exported="true"
            android:permission="android.permission.BIND_DEVICE_ADMIN">
            <intent-filter>
                <action android:name="android.app.action.GET_PROVISIONING_MODE" />
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

        <activity
            android:name=".PolicyComplianceActivity"
            android:exported="true"
            android:permission="android.permission.BIND_DEVICE_ADMIN">
            <intent-filter>
                <action android:name="android.app.action.ADMIN_POLICY_COMPLIANCE" />
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>
class PolicyComplianceActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Do any required setup
        val intent = Intent(this, MainActivity::class.java)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        startActivity(intent)
        finish()
    }
}
class GetProvisioningModeActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val result = Intent().apply {
            putExtra(
                DevicePolicyManager.EXTRA_PROVISIONING_MODE,
                DevicePolicyManager.PROVISIONING_MODE_FULLY_MANAGED_DEVICE
            )
        }

        setResult(Activity.RESULT_OK, result)
        finish()
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment