Some types of applications require that the end users can not be able to remove or at least stop the application. For example, all types of Parental Controls, Data Leak Prevention, and applications with similar concepts should work on devices regardless of the user’s intentions. On the other hand, when trying to search proven solutions for implementing such applications, we cannot find some comprehensive answers in the Internet. This article describes one of the possible solutions.
Written by:
Andrey Petrov,
Software Developer
Contents
1. Intro
2. The task
2.1. Appearance of the application
2.2. Used technologies
2.3. Pending issues
3. The general principles of the mechanism
3.1. Graphical representation
4. Implementation of the mechanism
4.1. Activation of the mechanism for protection against the application stop and uninstall, and the service launch (MainActivity.java)
4.2. The service launch and its running (BackgroundService.java)
4.3. The service “autostarter” code (ServiceStarter.java)
4.4. The DeviceAdmin component code (DeviceAdminComponent.java)
5. Results
6. Sources
1. Intro
Though, there are individual solutions for the "Disable force stop and uninstall button on Android" tasks, but in order to activate these buttons, you simply need to perform the user’s actions in reverse order.
As for the task of creation of an unkillable application, there are opinions that it cannot be supported by the concept of Android (1, 2, 3), because the basic idea of this OS is to give the user permission to work with his device as he wishes.
However, we are going to consider one of the ways to create an application that can be stopped or removed only by the user (Admin), who installed it.
2. The task
2.1 Appearance of the application
Task: Create the TryStopOrUninstallMe application.
After the application start and security policy acceptance, within a 10 seconds timeout, application displays the information that it successfully works (Toast with the “Ooops! Try to kill me :)” text).
If you stop the service, it will be restarted no later than in 2 seconds (by timeout).
The ForceStop and Uninstall buttons are inactive in the application menu. When you try to activate these buttons by disabling DeviceAdministrator for the application, phone is locked. At the same time the previous user password is deleted and further calls can be made only after unlocking the phone by administrator, who knows the password.
2.2 Used technologies
Programming language: Java.
Used libraries and technologies: Android SDK.
Minimum supported version of Android: 2.2
Maximum supported version of Android: 5.0.2 (the newest one for today)
ROOT-permissions requirements on the device: not required
Testing: the application was tested on Nexus 5 with Android 5.0.1.
2.3 Pending issues
In order to keep this article short and because of the triviality of the problem, we do not consider:
- Creation of start Activity, in which the administrator would set a master password. Instead, we have simply hardcoded it (e.g., "12345");
- Application startup at system startup.
3. The general principles of the mechanism
The following approaches will be used to implement this idea:
- Disabling the application forced stop and uninstall will be implemented using Device Administration API. Although it is designed for a little bit different purposes (some of which will be shown later), we’ll use it as a "deactivator" of the ForceStop and Uninstall buttons for our application (a side effect is actually what we need):
- There is no standard mechanism to disable the DeviceAdmin mode unlocking for user. However, we can sign up to receive event alerts on removing our application from the list of administered ones. And in this case we can:
- Reset the current password for device locking (one of the DeviceAdmin API purposes);
- Lock the phone (another great DeviceAdmin API feature).
- Our application will use the service to run in the background. For the cases when user tries to stop our service (Settings -> Application -> RunningServices) we will implement auto-start using the AlarmManager system mechanism.
- If user stop the service and have enough time to go to the application menu until the system restarts the service, then the application (not the service) stop button will be available for him.
After application is stopped, nothing can be restarted by itself. Thus, to deprive user of this chance, we will redirect him to his desktop and lock the device. While user is returning to the target Activity, system has enough time to restart the service (during my testing, it always takes 1-2 seconds).
3. The general principles of the mechanism
3.1 Graphical representation
Pic. 3.1 – Scheme that demonstrates the activation of mechanism for self-protection against application stop or uninstall
Pic. 3.2 – Device behavior while user tries to disable self-protection against application stop or uninstall
Pic. 3.3 – Device behavior while user tries to stop the service manually
4. Implementation of the mechanism
4.1 Activation of the mechanism for self-protection against the application stop and uninstall, and the service launch (MainActivity.java)
Everything that is done in the main (and only one) Activity is DeviceAdmin activation and service launch. It is expected that the device administrator activates the protection by pressing Activate.
Otherwise, the user can stop or remove the application in a standard way.
4.2 The service launch and its running (BackgroundService.java)
Everything here is also relatively simple.
At the start, service activates reset mechanism. If for some reason it is stopped, PendingIntent with information about our service will be created and transferred to the AlarmManager system service indicating restart timeout.
As a task, service creates a thread, which uses an infinite loop to periodically display the "Ooops !!! Try to kill me :)" message on the user’s desktop.
4.3 The service “autostarter” code (ServiceStarter.java)
"Autostarter" is presented by a standard BroadcastReceiver, in which the attempt to start the service is performed.
Receiver triggers according to timeout due to the AlarmManager service, because receiver was registered at the start of the service.
If the service is already running, then the second onCreate for it will not be called. And that is exactly what we need.
4.4 The DeviceAdmin component code (DeviceAdminComponent.java)
We need DeviceAdmin in order to:
- prohibit user to stop or uninstall the application;
- have the possibility to change the password and lock the device if user attempts to disable the DeviceAdmin component.
Also note that the administrator password is hardcoded as the "12345" string.
The onDisableRequested code works out after the confirmation of the DeviceAdmin deactivation, but before the deactivation itself.
5. Results
Thus, without using ROOT-permissions, incidents, or undocumented system features, we have managed to create the application that is practically impossible to be stopped or removed without knowing the administrator password. Although in some cases you can try to do it.
After studying this technique, we once again come to the conclusion that:
- it is almost always possible to find loopholes to circumvent any restrictions;
- it is strongly not recommended to install applications from untrusted sources. Especially if it requires the acceptance of the DeviceAdmin policies…
And what about you? Do you know a way to create a similar system? ;)
BTW, if you do need ROOT-permissions, learn about it from our article on how to obtain root acces on Android.
6. Sources
- http://developer.android.com/index.html;
- http://stackoverflow.com.
- Take a look at other technologies we use for Mobile (Security) Development
Downloads
Continue reading with another Android-related article: How to create an apk from command line