10

Recently i've seen a funny app - Photo Wonder. When this app is uninstalled, it shows a web survey page asking for the reason of app uninstall. Now, here is the problem. As far as I know, after an app has been removed, the system broadcasts ACTION_PAKAGE_REMOVED intent. But this funny app was able to show my the web page although the official doc says "The package that is being installed does not receive this Intent." Anyhow, I could find a process checking some kind of status of the app.

Now here is the question. Can the native app catch the broadcasted intent from android system? If it is possible, please let me know how! :-(

sergej shafarenka
  • 20,071
  • 7
  • 67
  • 86
MoTSF
  • 119
  • 1
  • 5
  • By the way there is two apps with such name in Google Play. Which one do you mean? – sergej shafarenka Jan 22 '14 at 10:01
  • 1
    See http://stackoverflow.com/questions/18692571/how-it-works-warning-that-app-is-going-to-be-uninstalled – David Wasser Jan 22 '14 at 10:24
  • 1
    @DavidWasser that is a very good link you have there. to the OP, the answer in that question might help you. Here is the link to the answer: http://stackoverflow.com/a/18816716/2431281 – Keale Jan 23 '14 at 01:02
  • 1
    @Keale Thanks. Unfortunately, this doesn't work reliably since 4.0 because `ACTION_QUERY_PACKAGE_RESTART` doesn't always get broadcast. See http://stackoverflow.com/questions/20699640/cant-get-receiver-when-the-app-uninstall/20701763#20701763 – David Wasser Jan 23 '14 at 08:55
  • @beworker Oh. made by Baidu. – MoTSF Jan 24 '14 at 08:37
  • @DavidWasser Thank you for your help. but the solution you linked shows dialog asking which package to proceed. it is little bit different from my intention. anyway thank you! – MoTSF Jan 24 '14 at 09:25
  • 1
    @beworker I found other app. you can see same operation with Dolphin browser ( you need to run the browser at least once. ) – MoTSF Jan 24 '14 at 09:30

2 Answers2

25

I believe I've got the main idea of how they did it. Here is the pieces of the puzzle.

  1. Any Android application can start a process by calling Runtime.exec() function.

    Runtime.getRuntime().exec("chmod 755 '/data/data/my.app/files'/native_code");
    

    After this line of code gets executed there is another process spawned. This process runs under the same linux user as the application itself.

  2. When a user opens Settings -> Apps -> My App and presses "Force stop" button, main application process gets killed, but the process hosting native program (see above) still runs. I personally believe this is a security issue and I am going to report it back to AOSP.

  3. Such native program can run infinitely and do nothing - just sleeping. But before going to sleep, it registers a termination signal handler which will be called when process is about to be terminated by the system.

    int main(void) {
        signal(SIGTERM, termination_handler);
        while(1) {
            sleep(10);
        }
    }
    
    void termination_handler(int sig) {
       // handle termination signal here
    }
    
  4. Now you should already know what the last piece is, right? My native termination_handler should be able to launch a browser. I didn't try this in code, but I assume this is possible, because I can do it using adb shell as following

    adb shell am start -a android.intent.action.VIEW -d http://www.google.com
    

Now back to the question about how Dolphin Browser does it. Install the app and launch it at least once. Once started, it registers a native uninstall watcher using the principles described above. To see it, connect to the device and open adb shell. Then call ps to see list of processes. You will see two processes similar to following

    u0_a109   315   ... mobi.mgeek.TunnyBrowser
    u0_a109   371   ... /data/data/mobi.mgeek.TunnyBrowser/files/watch_server

As you can see it starts a watch_server native program, which is a part of its apk-file. Now open App info page of Dolphin Browser and press "Force Stop". Switch back to terminal and call ps again. You will see there is no mobi.mgeek.TunnyBrowser process anymore, but watch_server still runs.

By the way this approach will only work, if watcher server runs all the time. To make sure it is always up, both apps require "run at startup" permission, where they start their watchers.

Now, when you uninstall the app, Android stops all processes belonging to this application. Watcher receives termination signal and opens browser with predefined URL and then shuts down.

I might look a bit different in some details, but the main concept behind this hack must be as described.

sergej shafarenka
  • 20,071
  • 7
  • 67
  • 86
2

There could be a tricky thing like that application is also having watcher service.

You can check the permission used by that app may contain INSTALL and UNINSTALL permissions.

HOW IT WORKS:

  1. instead of single app that may have 2 app bundle.

  2. as and when you install it, this app is also installing some service that is watching your app status

  3. When you try to uninstall that app the system broadcast is called which is handled by that service and will check that if your package is exist in installed application or not.

  4. as soon as this service finds that your package is not in the list it calls an intent with action view with the web url to open the brawser.

dinesh sharma
  • 3,312
  • 1
  • 22
  • 32
  • 3
    No, this isn't possible. First of all, an APK can only contain a single application. When an application is uninstalled, all of its components are uninstalled (this includes any services, content providers, etc.). The system broadcast `ACTION_PACKAGE_REMOVED` is made after the application has been removed, so there is no way that this application can get it. Secondly, non-system apps will never be granted the permission to `INSTALL_PACKAGES`, so it isn't possible that a 3rd-party application can install another application without the user having to actually confirm this installation. – David Wasser Jan 22 '14 at 10:13
  • 3
    its possible by making only service with different package that will be installed by the your app now you have two different apps(1 monitor service and 1 app) with different package and when you uninstall the app then the service will remain because it has different package name. :) – dinesh sharma Jan 22 '14 at 10:55
  • @dineshsharma Have you actually tried what you explain? – FD_ Jan 22 '14 at 11:30
  • Well, then I'll upvote your answer ;) – FD_ Jan 22 '14 at 11:33