I though it was not possible but I noticed that NQ Mobile Security is able to show a message after I click on Uninstall and before the PackageUninstaller is called. I would like to replicate this behavior in my App.

I tried with an Activity listening to "android.intent.action.DELETE" Intent, as suggested here: How to know my app is uninstalled from the device...?

But as I'm about to uninstall my app, the chooser pops up asking to pick my application or the package uninstaller. How can I avoid this?

Is there a different way to intercept your application UNINSTALL event? (before answering that it is not possible, please try to uninstall NQ Mobile Security and see what happens. On my Android 2.3.4 it shows a nice screen saying that is not safe to go without a security app).

Solution 1

I noticed that NQ Mobile Security is able to show a message after I click on Uninstall and before the PackageUninstaller is called

They must be exploiting some security flaw in Android. I will research it and see if I can get it fixed. Apps are not supposed to get control at uninstall time.

Thanks for pointing this out!

Is there a different way to intercept your application UNINSTALL event?

I sure hope not.

Solution 2

Opera Max is an app that does something similar - after being uninstalled opens a webpage.

How do they do this?

By using libevent, from native code, they watch /data/data/com.opera.max directory to be removed and then post good old action.VIEW broadcast when it happens.

Install their app, run it, and on rooted device from adb shell remove /data/data/com.opera.max directory

UPDATE: I created a sample app that shows how it works. BTW it doesn't work with recent (KitKat+ I think) Android versions: https://github.com/pelotasplus/ActionAfterUninstall

Solution 3

I'm pretty sure that they are monitoring the LogCat to intercept when the Activity Manager calls the PackageUninstaller. I think they kill the task and start their own Activity. It's pretty clever but it's definitely exploiting a security hole in Android.

Solution 4

They are likely asking for a very critical permission that the user is granting them unknowingly. Look at the "Permissions" tab for this app (as of 6/15/2012): https://play.google.com/store/apps/details?id=com.nqmobile.antivirus20&hl=en.

The list of permissions this app gets is downright chilling. Among other things:

SYSTEM TOOLS RETRIEVE RUNNING APPS Allows the app to retrieve information about currently and recently running tasks. Malicious apps may discover private information about other apps.

CHANGE/INTERCEPT NETWORK SETTINGS AND TRAFFIC Allows the app to change network settings and to intercept and inspect all network traffic, for example to change the proxy and port of any APN. Malicious apps may monitor, redirect, or modify network packets without your knowledge.

PREVENT TABLET FROM SLEEPING PREVENT PHONE FROM SLEEPING Allows the app to prevent the tablet from going to sleep. Allows the app to prevent the phone from going to sleep.

CHANGE YOUR UI SETTINGS Allows the app to change the current configuration, such as the locale or overall font size. MODIFY GLOBAL SYSTEM SETTINGS Allows the app to modify the system's settings data. Malicious apps may corrupt your system's configuration.

DISPLAY SYSTEM-LEVEL ALERTS Allows the app to show system alert windows. Malicious apps may take over the entire screen.

MOUNT AND UNMOUNT FILESYSTEMS Allows the app to mount and unmount filesystems for removable storage.

CHANGE NETWORK CONNECTIVITY Allows the app to change the state of network connectivity.

CHANGE WI-FI STATE Allows the app to connect to and disconnect from Wi-Fi access points, and to make changes to configured Wi-Fi networks.

-- Update --

I also found that the Android Package Manager pretty much just deletes a package if it is asked to do so. The only check it performs prior to doing so is whether the package being deleted is currently registered as having an active device admin:

    try {
        if (dpm != null && dpm.packageHasActiveAdmins(packageName)) {
            Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
            return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
        }
    } catch (RemoteException e) {
    }
    

See line 6900 in PackageManagerService in the AOSP source here.

For this, the application must be explicitly registered as a device admin by the user. See notes on device administration here: http://developer.android.com/training/enterprise/device-management-policy.html.

Solution 5

As per https://stackoverflow.com/a/26829978/1317564, here is some example code that does it: https://github.com/zzljob/android-uninstall-feedback/blob/master/library/jni/feedback-uninstall.c. This won't actually stop the uninstall from taking place, but does provide a way to catch it and take some action. I'm honestly surprised that this works in Android and the team may have plugged the gap in recent releases.