8

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?

TeazMalker
  • 83
  • 1
  • 6
  • I found the problem in my code: looks like I need to set `android:testOnly="false"`, but I didn't find any information about it. On pre-12 everything worked fine with default value. Maybe it will help someone – TeazMalker Nov 30 '21 at 05:40
  • And now Android 11 and below does not work @TeazMalker – Faz Jan 29 '22 at 10:53
  • "This kind of APK can be installed only through adb" https://developer.android.com/guide/topics/manifest/application-element#testOnly Test Only APKs can't be installed via normal means. – RRiVEN Mar 01 '22 at 00:29
  • @RRiVEN - right, but what was unexpected is that they needed to EXPLICITLY specify `false`. Previously, they omitted that attribute: *"everything worked fine with default value"*. It would be surprising for OS upgrade to change the default from false to true. – ToolmakerSteve Apr 24 '22 at 15:39
  • @TeazMalker thank you for this question. I've been struggling with getting my DeviceOwner app working on Android12. Your question filled in the missing pieces. Now it installs, but doesn't quit behave the same way. But at least I'm past the "Please contact your IT Admin" dead end. It's just insane to me that there is no facility to collect logs from a QR code provisioning failure.... I was about to try this against a lineage image in an emulator hoping I could see why it failed. You save me from that! – Chris Holt Apr 28 '22 at 14:06

2 Answers2

8

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.

Gokula Krishnan
  • 319
  • 2
  • 5
  • 2
    And now Android 11 and below does not work @Gokul – Faz Jan 29 '22 at 10:53
  • 1
    @Faz can you elaborate on what is not working? To provision Below android 11 device, you still have to listen to "android.app.action.PROFILE_PROVISIONING_COMPLETE". – Gokula Krishnan Jan 31 '22 at 06:35
1

@faz the reason this code doesn't work on Android 11 and below is because the ProvisioningModeActivity intent is not fired with an extra integer array of DevicePolicyManager.EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES. To overcome this add a null check to the allowedProvisioningModes

  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/33562019) – Vojin Purić Jan 06 '23 at 18:04
  • @Vonjin yes this answer doesn't fully solve the original question. But it will help users that come here with issues after they are required to upgrade their app to Android 12. Most will come across this question like faz and myself did and implement the solution in the question and then be stuck because it won't install on Android 10 or lower. And due to Android DPC the developer is really unable to troubleshoot the QR code setup and be unable to come to a solution. – Chris Hallgren Jan 07 '23 at 22:04
  • @ChrisHallgren This actually helped me. Thanks a lot! If anybody is looking for how to implement what you mentioned, it's been explained here by Daniel in the [answer](https://stackoverflow.com/questions/71989742/device-owner-qr-stopped-working-on-android12-devices-getting-cant-set-up-devic) – Antarpuneet Singh Jun 25 '23 at 01:54