Search code examples
androidforeground-service

Is Android thread started from foreground service persistent?


I need a service which should run 24/7 which does the following functions.

(1) checking GPS of the user with fusedLocationApi every second to check if the user enters a particular geofence.

(2) checking if another application package is installed (Thread)

(3) send an alive packet to the server by a particular interval of 60 seconds. (Thread)

The threads are singleton instances since I have to assure that only one thread per function run, for battery life.

All the above threads run on the foreground service's onStartCommand. I've read that the foreground service itself will not die on most circumstances, but how are the threads? Are threads started from the foreground service persistent as well? And furthermore, how can I test to prove that it's persistent?

Please help!


Solution

  • I'll answer my own question.

    For about a month of observation and trying, I finally got what I want.

    The answer for the question is YES, but NO. The threads are alive on doze mode, but what they do inside are suspended.

    My foreground service has a FusedLocationProviderClient which runs on a minute interval, and a threads that does some other works, such as pinging my server on a six minute interval. They both won't die, but there was a huge amount of delay on the pinging stuff. It is supposed to ping the server every six minute but while on doze, it pings by the delay of 30minute or more, even past an hour.

    I used two aproaches to fix this thing. I don't know which one makes this work, but it works anyway.

    (1) Added Battery white listing on the start up.

            Intent intent = PowerSaverHelper.prepareIntentForWhiteListingOfBatteryOptimization(getContext(), getPackageName(), false);
    
            if (intent != null) {
    
                startActivityForResult(intent, 19810);
    
            } else {
    
                getInterval();
            }
    

    (2) Created and hold a partial wakeLock on the onStartCommand of the Foreground service.

            try {
    
                PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
                wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                        "MyService::GpsWakeLock");
                if (!wakeLock.isHeld()) {
                    wakeLock.acquire();
                }
    
            } catch (Exception e) {
                ErrorController.showError(e);
            }
    

    And release it on onDestroy of the foreground service.

                if (wakeLock != null && wakeLock.isHeld()) {
    
                    wakeLock.release();
                }
    

    This solution worked fine for me. The Gps fetches gps location by a minute(if it can), and pings the server on an exact interval, overnight without the device not connected to any power source.

    But, the downfall of this method is expectable. The battery drain. While looking through this via Battery Historian, I saw that the cpu is always awake while the foreground service is running. Even by removing the gps stuff (which drains a lot of battery), it spent about 0.7% of battery during an hour of testing.

    However, if your goal is simular to mine, a special purpose application which should be persistant, this approach might help.