Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Service running on separate Process gets killed when I swipe out my App (running in other process)

I have an Android Service (implementation of Servcie interface) which is running on a separate process compared to my real app. Unfortunately when I leave my real App (in which I clicked the Button to start my Service) and swipe it out from Task Manager, my Service gets killed as well.

I know there are a lot of questions like this here, but somehow none are targeting the Problem in my concrete constellation or they are vaguely answered.

So in my manifest I have something like:

<application ...>
    <activity .../>
    <service Android:name="MyService"
        Android:label="MyLabel"
        Android:export="false"
        Android:process=":MyRemoteProcessName" />
</application>

I first have played around with an IntentService, but also switched to an own implementation of the Service Interface (eliminating the IntentService to be the point of failure) which looks something like:

public class MyService extends Service {

    private ScheduledExecutorService scheduledWorker = Executors.newSingleThreadScheduledExecutor();

    @Override
    public void onStart() {
        // Init components
        startForeground(this, MyNotification);
    }

    @Override
    public int onStartCommand(Intent i, int startId) {
        // Execute Work on Threadpool here
        scheduledWorker.execute(new ScheduledStopRequest(this, startId), 5, TimeUnit.Minutes);
        return START_REDILIVER_INTENT;
    }

    // Overwritten onDestroy-Method

    @Override
    public void onLowMemory() {
        Log.e(LOG_TAG, "On Low Memory called!");
    }

    @Override
    public IBind onBind() {
        // Dont't want to let anyone bind here
        return null;
    }

    // Simply tries to stop the service after e.g. 5 Minutes after a call
    private static class MyRunnable implements Runnable {

        // Constructor with params used in run method..

        @Override
        public void run() {
            mReferenceToMyService.stopSelfResult(startId);
        }
    }
}

I'm starting my Service in an onClick-Listener on a special button, with an explicit Intent, which kinda looks like the following:

@Override
public void onClick(View v) {
    Intent i = new Intent(this, MyService.class);
    startService(i);
}

My Intention is to keep the Service running when the user leaves the app, so that the Service can finish downloading and storing some important data. When the user comes back to my app again, he can view the data (That's why I'm executing it in a separate process). So is this possible?

My assumption right now is, that Android somehow notices my Service is just being used by my App (due to missing IntentFilters in Manifest or explicit call rather than by filter?!) and thus kills it immediately when my App is closed (even when running as ForegroundService as you can see above).

Does it seem possible to you and might some changes in the call of the service fix this problem or am I getting the concept of a service wrong?

(One last note: onLowMemory-Method doesn't get called -> No log entries.)

like image 513
Sebsen36 Avatar asked Oct 30 '22 11:10

Sebsen36


People also ask

How do you handle running service when an app is killed by swiping in Android?

You can't handle swipe, because system just removes your process from memory without calling any callback. I have checked, that before user calls "recent apps" screen, onPause() will be always called. So you need to save all data in onPause method without checking isFinishing().

How do I stop Android services from killing my apps?

First, swipe down once from the top of the screen and tap the gear icon. Scroll down and find “Apps.” Next, tap the three-dot menu icon and select “Special Access.” If you don't see it, there will be a section on that screen titled “Special App Access.” Now select “Optimize Battery Usage.”

Why does Android run an app inside a separate process?

In most cases, every Android application runs in its own Linux process. This process is created for the application when some of its code needs to be run, and will remain running until it is no longer needed and the system needs to reclaim its memory for use by other applications.


1 Answers

So, according to your hints (and so new keywords for me to look for) and after some additional research by myself, I think I have solved my problem. During my research I have found an very interisting blog post on this topic, maybe also for you, which is why I would like to share it with you: http://workshop.alea.net/post/2016/06/android-service-kill/ .

After verifying and going through the steps in this article everything seems to work fine (so startForeground seems to solve the problem). I want to point out here, that I have only tested it, with my service instance still running in separate process, so manifest entries as is above.

The actual thing which really confused me at the beginning was my android studio debug session being killed everytime, just after swiping out my app from recent apps (menu). This made me think my service being killed by the system as well. But according to the article (I have added some logs to the callback methods provided) when

  1. Opening my app

  2. starting service

  3. swiping out app

  4. starting app again and finally

  5. calling service again,

I only received callbacks to the methods as if my service would still be running. Having an explicit look at DDMS (tool) also prooved my 2nd process, and thus my service, being still alive. Having verified this, I then cleared all my app data and repeated the steps above (excluding step no. 5). Having had a look in the database afterwards, prooved the data having been downloaded by the service.

For the curious of you:

The process of swiping out my app from recent apps (and thus having the onTaskRemoved callback method being called) lead to another problem. It somehow increases the startId parameter of onStartCommand by 1 so that my DelayedStopRequest malfunctiones and doesn't stop my service anymore.

This means: Repeating above steps 1 - 3 makes me receive startId = 1 in onStartCommand. By calling stopSelfResult(1) later on (which was the latest startId) it returnes false and the service keeps running. Continuing to follow step 4 + 5 then, makes onStartCommand being called with startId = 3 (but should actually be 2! which is skipped somehow). Calling stopSelfResult(3) with parameter 3 later on is then going to stop the service again (also visible in screenshots).

I hope my answer is correct so far (, understandable) and also helpful for you. Thank you for all of your answers which provided beneficial input and also pointed me to the solution. The android version I have been working with is:

4.1.2 - Jelly Bean | API Level : 16

I also added screenshots of the log entries from DDMS (imgur is rejecting my uploads so you'll temporarily have a link to my dropbox): screenshots from logs from DDMS

like image 54
Sebsen36 Avatar answered Nov 11 '22 10:11

Sebsen36