In my application, which is a device admin, I need to wipe the entire device when the user tries to deactivate the admin function of the application. When the user goes to Settings / Security / Device admins and deactivates the admin app, first a dialog is presented "Do you want to deactivate". If the user says "yes", then another small dialog is presented, with the text provided by the application's AdminReceiver in onDisableRequested(). If the user then says "yes", I want to wipe the entire device. How to accomplish this?
I tried everything, searched long for answers, found no real solutions.
What I tried:
- AdminReceiver has a function onDisable(). I tried to wipe the device in that function. However, it appears that onDisable() is called after the admin has been disabled. Thus the app cannot use the wipeData() function at all (a security exception is thrown). I have also verified that isAdminActive() returns false at that time.
Official documentation does not say this clearly, but it seems that the admin is already disabled when onDisable() is called. Thus we have to wipe the device before that time.
AdminReceiver has a function onDisableRequested(), which returns CharSequence. I tried to put another alert box in that function. This crashes because an alert box cannot be called from a non-activity context, which seems to be what we have when we are in onDisableRequested().
AdminReceiver has a function onReceive(), which gets called on any events. In this function, again, we are not in an activity context and cannot present our own dialogs.
I tried creating another activity from onReceive(). This works; during onReceive() when we get ACTION_DISABLE_ADMIN_REQUESTED, the admin is still active and we can wipe the device. However, the system still presents its own dialog asking the user whether to deactivate the admin. If the user says no to our dialog but yes to the system dialog, the admin will be deactivated and we will have failed to wipe the device.
I tried the following, in my subclass of DeviceAdminReceiver:
@Override
public void onReceive(Context context, Intent intent) {
// detect whether disabling is requested?
if (intent.getAction().equals(ACTION_DEVICE_ADMIN_DISABLE_REQUESTED)) {
confirmWipeDevice(context);
} else {
super.onReceive(context, intent);
}
}
In other words, I do not call super.onReceive() if the action is to disable the admin. The function confirmWipeDevice() shows a different activity with a dialog. This does not show the system dialog for confirming the disabling of my admin app. However, this does not prevent the app from being actually disabled!
It seems that the Android system does the following:
Send ACTION_DEVICE_ADMIN_DISABLE_REQUESTED to the AdminReceiver
Proceed with disabling the admin regardless of what the admin app wants to do
If the user cancels the disabling, fine; if not, the app is disabled. There is no way for the app to refuse being disabled, or to perform the device wipe upon disabling.
The only solution so far is to wipe immediately without confirmation when the user wants to disable the admin app. In other words, I can call getManager().wipeData() immediately in onDisableRequested(). At that time, the admin is still active and this works.
Is this correct? How to wipe the device when the user chooses to disable the admin app?