androidprovisioningdevice-policy-managerandroid-12device-owner

Android 12 Device Owner Provisioning


I have an application, that can be successfully setup as Device Owner on devices up to Android 12 via QR code from JSON below:

{
"android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME":
"package.CustomDeviceAdminReceiver",
"android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM":
"actual_checksum",
"android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION":
"https://Site/APK_Link",
"android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED": true
 }

App contains declared receiver:

<receiver
        android:name=".deviceadmin.CustomDeviceAdminReceiver"
        android:description="@string/app_name"
        android:label="@string/app_name"
        android:permission="android.permission.BIND_DEVICE_ADMIN">
        <meta-data
            android:name="android.app.device_admin"
            android:resource="@xml/enterprise_device_admin" />

        <intent-filter>
            <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
            <action android:name="android.app.action.PROFILE_PROVISIONING_COMPLETE" />
        </intent-filter>
</receiver> 

For Android 12 (as described here https://source.android.com/devices/tech/admin/provision) I added 2 activities:

<activity
        android:name=".deviceadmin.AdminPolicyComplianceActivity"
        android:screenOrientation="portrait"
        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>
<activity
        android:name=".deviceadmin.ProvisioningModeActivity"
        android:screenOrientation="portrait"
        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>

1st one:

public class ProvisioningModeActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_provisioning_mode);

    Intent intent = getIntent();
    int provisioningMode = 1;
    List<Integer> allowedProvisioningModes = intent.getIntegerArrayListExtra(DevicePolicyManager.EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES);

    if (allowedProvisioningModes.contains(DevicePolicyManager.PROVISIONING_MODE_FULLY_MANAGED_DEVICE))
        provisioningMode = DevicePolicyManager.PROVISIONING_MODE_FULLY_MANAGED_DEVICE;
    else if (allowedProvisioningModes.contains(DevicePolicyManager.PROVISIONING_MODE_MANAGED_PROFILE))
        provisioningMode = DevicePolicyManager.PROVISIONING_MODE_MANAGED_PROFILE;

    Intent resultIntent = new Intent();
    resultIntent.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_MODE, provisioningMode);

    setResult(RESULT_OK, resultIntent);
    finish();
}
}

and 2nd one (almost empty):

public class AdminPolicyComplianceActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_admin_policy_compliance);

    setResult(RESULT_OK);
    finish();
}
}

but I got error while enrollment: "Can't setup device. Can't use the admin app. It's missing components or corrupted".

Can somebody find that I missed please?


Solution

  • From Android 12 we are supposed to have components exported safely. Since your activities ProvisioningModeActivity and AdminPolicyComplianceActivity uses intent filter, we have to set the exported flag.

    <activity
        android:name=".deviceadmin.AdminPolicyComplianceActivity"
        android:screenOrientation="portrait"
        android:permission="android.permission.BIND_DEVICE_ADMIN"
        android:exported="true">
        <intent-filter>
            <action 
              android:name="android.app.action.ADMIN_POLICY_COMPLIANCE"/>
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>
    <activity
        android:name=".deviceadmin.ProvisioningModeActivity"
        android:screenOrientation="portrait"
        android:permission="android.permission.BIND_DEVICE_ADMIN"
        android:exported="true">
        <intent-filter>
            <action android:name="android.app.action.GET_PROVISIONING_MODE" 
            />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>
    

    This way firmware will be able to recognize the activity and launch it.

    Also, regarding android:testOnly="false", this flag must be false if you are going to do QR code provisioning. If its true then, you will be able to remove admin via android settings.