Minimal android foreground service killed on high-end phoneForeground service being killed by Androidscheduling alarm for every second in android 5.1Service stop's whenever app is killedBest way to use TriggerEventListener in the background?How do apps keep a cached process in memory after being swiped closedThread-Sleep strange behaviorHow to check if a service is running on Android?Background Service getting killed in androidWhy does my Android service get restarted when the process is killed, even though I used START_NOT_STICKY?Android - What happens to a bound service if the binding activity was killed?Long life to Android Service: “immortal service”Android Foreground Service check if createdStopped Foreground Service Restarting ItselfForeground Service killed and not restartedHuawei P20 Lite killing a foreground service in OreoReceive location updates in foreground service started from RECEIVE_SMS BroadcastManager when in doze mode

How Can I Process Untrusted Data Sources Securely?

Should I be able to keep my company purchased standing desk when I leave my job?

Where do the electrons come from to make the carbon stable during bombardment of alpha particles on beryllium

how slow a car engine can run

Strategy to pay off revolving debt while building reserve savings fund?

Is there an English equivalent for "Les carottes sont cuites", while keeping the vegetable reference?

Is it okay for a chapter's POV to shift as it progresses?

Did Voldemort kill his father before finding out about Horcruxes?

Can I use #10 wire for a 30A, 240V pump circuit?

How could an animal "smell" carbon monoxide?

Generating a PIN from cryptographic bytes

How many bits in the resultant hash will change, if the x bits are changed in its the original input?

Finding all possible pairs of square numbers in an array

How fast does a character need to move to be effectively invisible?

How can I obtain a complete list of the kinds of atomic expressions in the Wolfram Language using only the language itself?

How can the electric potential be zero at a point where the electric field isn't, if that field can give a test charge kinetic energy?

Do dragons smell of lilacs?

Is there a typesafe way to get a Database.QueryLocator?

Why doesn't philosophy have higher standards for its arguments?

When designing an adventure, how can I ensure a continuous player experience in a setting that's likely to favor TPKs?

Create Array from list of indices/values

Did 007 exist before James Bond?

Kepler space telescope undetected planets

Was Apollo 13 radio blackout on reentry longer than expected?



Minimal android foreground service killed on high-end phone


Foreground service being killed by Androidscheduling alarm for every second in android 5.1Service stop's whenever app is killedBest way to use TriggerEventListener in the background?How do apps keep a cached process in memory after being swiped closedThread-Sleep strange behaviorHow to check if a service is running on Android?Background Service getting killed in androidWhy does my Android service get restarted when the process is killed, even though I used START_NOT_STICKY?Android - What happens to a bound service if the binding activity was killed?Long life to Android Service: “immortal service”Android Foreground Service check if createdStopped Foreground Service Restarting ItselfForeground Service killed and not restartedHuawei P20 Lite killing a foreground service in OreoReceive location updates in foreground service started from RECEIVE_SMS BroadcastManager when in doze mode






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








22















I'm trying to create an app that lets users log routes (locations/GPS). To ensure locations are logged even when the screen is off, I have created a foreground service for the location logging. I store the locations in a Room Database which is injected into my service using Dagger2.



However, this service is killed by Android which is, of course, not good. I could subscribe to low memory warnings but that doesn't solve the underlying problem of my service getting killed after ~30 minutes on a modern high-end phone running Android 8.0



I have created a minimal project with only a "Hello world" activity and the service: https://github.com/RandomStuffAndCode/AndroidForegroundService



The service is started in my Application class, and route logging is started through a Binder:



// Application
@Override
public void onCreate()
super.onCreate();
mComponent = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();

Intent startBackgroundIntent = new Intent();
startBackgroundIntent.setClass(this, LocationService.class);
startService(startBackgroundIntent);


// Binding activity
bindService(new Intent(this, LocationService.class), mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT);
// mConnection starts the route logging through `Binder` once connected. The binder calls startForeground()


I probably don't need the BIND_AUTO_CREATE flag, I've been testing different flags in an attempt to not get my service killed - no luck so far.



Using the profiler it does not seem like I have any memory leaks, memory usage is stable at ~35mb:



profiler



Using adb shell dumpsys activity processes > tmp.txt i can confirm that foregroundServices=true and my service is listed 8th in the LRU list:



Proc # 3: prcp F/S/FGS trm: 0 31592:com.example.foregroundserviceexample/u0a93 (fg-service)



It seems like it is not possible to create a foreground service that you can trust to not get killed. So what can we do? Well...



  1. Put the service in a separate process, in an attempt to let Android kill the UI/Activities while leaving the service alone. Would probably help, but doesn't seem like a guarantee

  2. Persist everything in the service in e.g. a Room database. Every variable, every custom class, every time any of the changes and then start the service with START_STICKY. This seems kind of wasteful and doesn't lead to very beautiful code, but it would probably work... somewhat. Depending on how long it takes for Android to re-create the service after killing it, a large portion of locations may be lost.

Is this really the current state of doing stuff in the background on Android? Isn't there a better way?



EDIT: Whitelisting the app for battery optimization (disabling it) does not stop my service from being killed



EDIT: Using Context.startForegroundService() to start the service does not improve the situation



EDIT: So this indeed only occurs on some devices, but it occurs consistently on them. I guess you have to make a choice of either not supporting a huge number of users or write really ugly code. Awesome.










share|improve this question
























  • "my service getting killed after ~30 minutes" -- how are you determining this?

    – CommonsWare
    Apr 3 '18 at 19:45







  • 1





    The notification for the foreground service is removed after that time and locations stop being inserted to the database. According to @ianhanniballake it seems like you can get location data frequently and reliably if you're using a foreground service since its supposed to be unaffected by doze

    – user1202032
    Apr 3 '18 at 19:48






  • 1





    Have you tried starting the service using the new Context.startForegroundService()? The service itself still must call startForeground(), but maybe the way the service is initially started makes a difference.

    – TKK
    Apr 3 '18 at 19:56











  • Sorry -- I realized that moments after posting the comment, and I wasn't fast enough to delete that portion. Next question: is this device one that shipped with 8.0? Or did it ship with something older and got upgraded by the manufacturer? I ask because it's possible that this is a manufacturer thing more so than an Android thing. Also, does this behavior persist if you (as a user) add your app to the battery optimization whitelist?

    – CommonsWare
    Apr 3 '18 at 19:57











  • @TKK I have not tried that, but I will now, thanks for the suggestion. I would prefer to only have the service in the foreground when a route is actively being recorded, not all the time, but its worth a shot!

    – user1202032
    Apr 3 '18 at 19:59


















22















I'm trying to create an app that lets users log routes (locations/GPS). To ensure locations are logged even when the screen is off, I have created a foreground service for the location logging. I store the locations in a Room Database which is injected into my service using Dagger2.



However, this service is killed by Android which is, of course, not good. I could subscribe to low memory warnings but that doesn't solve the underlying problem of my service getting killed after ~30 minutes on a modern high-end phone running Android 8.0



I have created a minimal project with only a "Hello world" activity and the service: https://github.com/RandomStuffAndCode/AndroidForegroundService



The service is started in my Application class, and route logging is started through a Binder:



// Application
@Override
public void onCreate()
super.onCreate();
mComponent = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();

Intent startBackgroundIntent = new Intent();
startBackgroundIntent.setClass(this, LocationService.class);
startService(startBackgroundIntent);


// Binding activity
bindService(new Intent(this, LocationService.class), mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT);
// mConnection starts the route logging through `Binder` once connected. The binder calls startForeground()


I probably don't need the BIND_AUTO_CREATE flag, I've been testing different flags in an attempt to not get my service killed - no luck so far.



Using the profiler it does not seem like I have any memory leaks, memory usage is stable at ~35mb:



profiler



Using adb shell dumpsys activity processes > tmp.txt i can confirm that foregroundServices=true and my service is listed 8th in the LRU list:



Proc # 3: prcp F/S/FGS trm: 0 31592:com.example.foregroundserviceexample/u0a93 (fg-service)



It seems like it is not possible to create a foreground service that you can trust to not get killed. So what can we do? Well...



  1. Put the service in a separate process, in an attempt to let Android kill the UI/Activities while leaving the service alone. Would probably help, but doesn't seem like a guarantee

  2. Persist everything in the service in e.g. a Room database. Every variable, every custom class, every time any of the changes and then start the service with START_STICKY. This seems kind of wasteful and doesn't lead to very beautiful code, but it would probably work... somewhat. Depending on how long it takes for Android to re-create the service after killing it, a large portion of locations may be lost.

Is this really the current state of doing stuff in the background on Android? Isn't there a better way?



EDIT: Whitelisting the app for battery optimization (disabling it) does not stop my service from being killed



EDIT: Using Context.startForegroundService() to start the service does not improve the situation



EDIT: So this indeed only occurs on some devices, but it occurs consistently on them. I guess you have to make a choice of either not supporting a huge number of users or write really ugly code. Awesome.










share|improve this question
























  • "my service getting killed after ~30 minutes" -- how are you determining this?

    – CommonsWare
    Apr 3 '18 at 19:45







  • 1





    The notification for the foreground service is removed after that time and locations stop being inserted to the database. According to @ianhanniballake it seems like you can get location data frequently and reliably if you're using a foreground service since its supposed to be unaffected by doze

    – user1202032
    Apr 3 '18 at 19:48






  • 1





    Have you tried starting the service using the new Context.startForegroundService()? The service itself still must call startForeground(), but maybe the way the service is initially started makes a difference.

    – TKK
    Apr 3 '18 at 19:56











  • Sorry -- I realized that moments after posting the comment, and I wasn't fast enough to delete that portion. Next question: is this device one that shipped with 8.0? Or did it ship with something older and got upgraded by the manufacturer? I ask because it's possible that this is a manufacturer thing more so than an Android thing. Also, does this behavior persist if you (as a user) add your app to the battery optimization whitelist?

    – CommonsWare
    Apr 3 '18 at 19:57











  • @TKK I have not tried that, but I will now, thanks for the suggestion. I would prefer to only have the service in the foreground when a route is actively being recorded, not all the time, but its worth a shot!

    – user1202032
    Apr 3 '18 at 19:59














22












22








22


14






I'm trying to create an app that lets users log routes (locations/GPS). To ensure locations are logged even when the screen is off, I have created a foreground service for the location logging. I store the locations in a Room Database which is injected into my service using Dagger2.



However, this service is killed by Android which is, of course, not good. I could subscribe to low memory warnings but that doesn't solve the underlying problem of my service getting killed after ~30 minutes on a modern high-end phone running Android 8.0



I have created a minimal project with only a "Hello world" activity and the service: https://github.com/RandomStuffAndCode/AndroidForegroundService



The service is started in my Application class, and route logging is started through a Binder:



// Application
@Override
public void onCreate()
super.onCreate();
mComponent = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();

Intent startBackgroundIntent = new Intent();
startBackgroundIntent.setClass(this, LocationService.class);
startService(startBackgroundIntent);


// Binding activity
bindService(new Intent(this, LocationService.class), mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT);
// mConnection starts the route logging through `Binder` once connected. The binder calls startForeground()


I probably don't need the BIND_AUTO_CREATE flag, I've been testing different flags in an attempt to not get my service killed - no luck so far.



Using the profiler it does not seem like I have any memory leaks, memory usage is stable at ~35mb:



profiler



Using adb shell dumpsys activity processes > tmp.txt i can confirm that foregroundServices=true and my service is listed 8th in the LRU list:



Proc # 3: prcp F/S/FGS trm: 0 31592:com.example.foregroundserviceexample/u0a93 (fg-service)



It seems like it is not possible to create a foreground service that you can trust to not get killed. So what can we do? Well...



  1. Put the service in a separate process, in an attempt to let Android kill the UI/Activities while leaving the service alone. Would probably help, but doesn't seem like a guarantee

  2. Persist everything in the service in e.g. a Room database. Every variable, every custom class, every time any of the changes and then start the service with START_STICKY. This seems kind of wasteful and doesn't lead to very beautiful code, but it would probably work... somewhat. Depending on how long it takes for Android to re-create the service after killing it, a large portion of locations may be lost.

Is this really the current state of doing stuff in the background on Android? Isn't there a better way?



EDIT: Whitelisting the app for battery optimization (disabling it) does not stop my service from being killed



EDIT: Using Context.startForegroundService() to start the service does not improve the situation



EDIT: So this indeed only occurs on some devices, but it occurs consistently on them. I guess you have to make a choice of either not supporting a huge number of users or write really ugly code. Awesome.










share|improve this question
















I'm trying to create an app that lets users log routes (locations/GPS). To ensure locations are logged even when the screen is off, I have created a foreground service for the location logging. I store the locations in a Room Database which is injected into my service using Dagger2.



However, this service is killed by Android which is, of course, not good. I could subscribe to low memory warnings but that doesn't solve the underlying problem of my service getting killed after ~30 minutes on a modern high-end phone running Android 8.0



I have created a minimal project with only a "Hello world" activity and the service: https://github.com/RandomStuffAndCode/AndroidForegroundService



The service is started in my Application class, and route logging is started through a Binder:



// Application
@Override
public void onCreate()
super.onCreate();
mComponent = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();

Intent startBackgroundIntent = new Intent();
startBackgroundIntent.setClass(this, LocationService.class);
startService(startBackgroundIntent);


// Binding activity
bindService(new Intent(this, LocationService.class), mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT);
// mConnection starts the route logging through `Binder` once connected. The binder calls startForeground()


I probably don't need the BIND_AUTO_CREATE flag, I've been testing different flags in an attempt to not get my service killed - no luck so far.



Using the profiler it does not seem like I have any memory leaks, memory usage is stable at ~35mb:



profiler



Using adb shell dumpsys activity processes > tmp.txt i can confirm that foregroundServices=true and my service is listed 8th in the LRU list:



Proc # 3: prcp F/S/FGS trm: 0 31592:com.example.foregroundserviceexample/u0a93 (fg-service)



It seems like it is not possible to create a foreground service that you can trust to not get killed. So what can we do? Well...



  1. Put the service in a separate process, in an attempt to let Android kill the UI/Activities while leaving the service alone. Would probably help, but doesn't seem like a guarantee

  2. Persist everything in the service in e.g. a Room database. Every variable, every custom class, every time any of the changes and then start the service with START_STICKY. This seems kind of wasteful and doesn't lead to very beautiful code, but it would probably work... somewhat. Depending on how long it takes for Android to re-create the service after killing it, a large portion of locations may be lost.

Is this really the current state of doing stuff in the background on Android? Isn't there a better way?



EDIT: Whitelisting the app for battery optimization (disabling it) does not stop my service from being killed



EDIT: Using Context.startForegroundService() to start the service does not improve the situation



EDIT: So this indeed only occurs on some devices, but it occurs consistently on them. I guess you have to make a choice of either not supporting a huge number of users or write really ugly code. Awesome.







android android-service android-lifecycle android-location android-doze






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Apr 18 '18 at 9:59







user1202032

















asked Apr 3 '18 at 19:41









user1202032user1202032

6091 gold badge7 silver badges26 bronze badges




6091 gold badge7 silver badges26 bronze badges












  • "my service getting killed after ~30 minutes" -- how are you determining this?

    – CommonsWare
    Apr 3 '18 at 19:45







  • 1





    The notification for the foreground service is removed after that time and locations stop being inserted to the database. According to @ianhanniballake it seems like you can get location data frequently and reliably if you're using a foreground service since its supposed to be unaffected by doze

    – user1202032
    Apr 3 '18 at 19:48






  • 1





    Have you tried starting the service using the new Context.startForegroundService()? The service itself still must call startForeground(), but maybe the way the service is initially started makes a difference.

    – TKK
    Apr 3 '18 at 19:56











  • Sorry -- I realized that moments after posting the comment, and I wasn't fast enough to delete that portion. Next question: is this device one that shipped with 8.0? Or did it ship with something older and got upgraded by the manufacturer? I ask because it's possible that this is a manufacturer thing more so than an Android thing. Also, does this behavior persist if you (as a user) add your app to the battery optimization whitelist?

    – CommonsWare
    Apr 3 '18 at 19:57











  • @TKK I have not tried that, but I will now, thanks for the suggestion. I would prefer to only have the service in the foreground when a route is actively being recorded, not all the time, but its worth a shot!

    – user1202032
    Apr 3 '18 at 19:59


















  • "my service getting killed after ~30 minutes" -- how are you determining this?

    – CommonsWare
    Apr 3 '18 at 19:45







  • 1





    The notification for the foreground service is removed after that time and locations stop being inserted to the database. According to @ianhanniballake it seems like you can get location data frequently and reliably if you're using a foreground service since its supposed to be unaffected by doze

    – user1202032
    Apr 3 '18 at 19:48






  • 1





    Have you tried starting the service using the new Context.startForegroundService()? The service itself still must call startForeground(), but maybe the way the service is initially started makes a difference.

    – TKK
    Apr 3 '18 at 19:56











  • Sorry -- I realized that moments after posting the comment, and I wasn't fast enough to delete that portion. Next question: is this device one that shipped with 8.0? Or did it ship with something older and got upgraded by the manufacturer? I ask because it's possible that this is a manufacturer thing more so than an Android thing. Also, does this behavior persist if you (as a user) add your app to the battery optimization whitelist?

    – CommonsWare
    Apr 3 '18 at 19:57











  • @TKK I have not tried that, but I will now, thanks for the suggestion. I would prefer to only have the service in the foreground when a route is actively being recorded, not all the time, but its worth a shot!

    – user1202032
    Apr 3 '18 at 19:59

















"my service getting killed after ~30 minutes" -- how are you determining this?

– CommonsWare
Apr 3 '18 at 19:45






"my service getting killed after ~30 minutes" -- how are you determining this?

– CommonsWare
Apr 3 '18 at 19:45





1




1





The notification for the foreground service is removed after that time and locations stop being inserted to the database. According to @ianhanniballake it seems like you can get location data frequently and reliably if you're using a foreground service since its supposed to be unaffected by doze

– user1202032
Apr 3 '18 at 19:48





The notification for the foreground service is removed after that time and locations stop being inserted to the database. According to @ianhanniballake it seems like you can get location data frequently and reliably if you're using a foreground service since its supposed to be unaffected by doze

– user1202032
Apr 3 '18 at 19:48




1




1





Have you tried starting the service using the new Context.startForegroundService()? The service itself still must call startForeground(), but maybe the way the service is initially started makes a difference.

– TKK
Apr 3 '18 at 19:56





Have you tried starting the service using the new Context.startForegroundService()? The service itself still must call startForeground(), but maybe the way the service is initially started makes a difference.

– TKK
Apr 3 '18 at 19:56













Sorry -- I realized that moments after posting the comment, and I wasn't fast enough to delete that portion. Next question: is this device one that shipped with 8.0? Or did it ship with something older and got upgraded by the manufacturer? I ask because it's possible that this is a manufacturer thing more so than an Android thing. Also, does this behavior persist if you (as a user) add your app to the battery optimization whitelist?

– CommonsWare
Apr 3 '18 at 19:57





Sorry -- I realized that moments after posting the comment, and I wasn't fast enough to delete that portion. Next question: is this device one that shipped with 8.0? Or did it ship with something older and got upgraded by the manufacturer? I ask because it's possible that this is a manufacturer thing more so than an Android thing. Also, does this behavior persist if you (as a user) add your app to the battery optimization whitelist?

– CommonsWare
Apr 3 '18 at 19:57













@TKK I have not tried that, but I will now, thanks for the suggestion. I would prefer to only have the service in the foreground when a route is actively being recorded, not all the time, but its worth a shot!

– user1202032
Apr 3 '18 at 19:59






@TKK I have not tried that, but I will now, thanks for the suggestion. I would prefer to only have the service in the foreground when a route is actively being recorded, not all the time, but its worth a shot!

– user1202032
Apr 3 '18 at 19:59













3 Answers
3






active

oldest

votes


















16





+50









A service started by startForeground besongs to the second most important group visible process:





  1. A visible process is doing work that the user is currently aware of,
    so killing it would have a noticeable negative impact on the user
    experience. A process is considered visible in the following
    conditions:



    1. It is running an Activity that is visible to the user on-screen but not in the foreground (its onPause() method has been called). This
      may occur, for example, if the foreground Activity is displayed as a
      dialog that allows the previous Activity to be seen behind it.


    2. It has a Service that is running as a foreground service, through Service.startForeground() (which is asking the system to treat the
      service as something the user is aware of, or essentially visible to
      them).


    3. It is hosting a service that the system is using for a particular feature that the user is aware, such as a live wallpaper, input method
      service, etc.

    The number of these processes running in the system is less bounded
    than foreground processes, but still relatively controlled. These
    processes are considered extremely important and will not be killed
    unless doing so is required to keep all foreground processes running
    .





That being said, you can never be sure that your service is not killed at any time. E.g. memory pressure, low battery etc. See who-lives-and-who-dies.




For how to handle it, basically you answered the question yourself. The way to go is START_STICKY:




For started services, there are two additional major modes of
operation they can decide to run in, depending on the value they
return from onStartCommand(): START_STICKY is used for services that
are explicitly started and stopped as needed, while START_NOT_STICKY
or START_REDELIVER_INTENT are used for services that should only
remain running while processing any commands sent to them
. See the
linked documentation for more detail on the semantics.




As a general guideline you should do as little as possible in the background (ore foreground) service, i.e. only do the location tracking and keep everything else in your foreground activity. Only the tracking should require very little configuration an can be loaded quickly. Also the smaller your service is the less likely it is to be killed. Your activity will be restored by the system in the state that is was before it went into background, as long as it is not killed as well. A "cold-start" of the foreground activity on the other hand should not be a problem.

I don't consider that as ugly, because this guarantees that the phone always provides the best experience to the user. This is the most important thing it has to do. That some devices close services after 30 minutes (possibly without user interaction) is unfortunate.



So, as you stated, you have to




Persist everything in the service in e.g. a Room database. Every
variable, every custom class, every time any of them changes and then
start the service with START_STICKY.




See creating a never ending service



Implicit question:




Depending on how long it takes for Android to re-create the
service after killing it, a large portion of locations may be lost.




This usually takes only a really short time. Especially because you can use the Fused Location Provider Api for the location updates, which is an independent system service and very unlikely to be killed. So it mainly depends on the time you need to recreate the service in onStartCommand.




Also take note that from Android 8.0 onwards you need to use a
forground service because of the background location
limits.





Edit:
As recently covered in the news:
Some manufacturers may give you a hard time to keep your service running. The site https://dontkillmyapp.com/ keeps track of the manufacturers and possible mitigations for your device. Oneplus is currently (29.01.19) one of the worst offenders.




When releasing their 1+5 and 1+6 phones, OnePlus introduced one of the
most severe background limits on the market to date, dwarfing even
those performed by Xiaomi or Huawei. Not only did users need to enable
extra settings to make their apps work properly, but those settings
even get reset with firmware update so that apps break again and users
are required to re-enable those settings on a regular basis.



Solution for users



Turn off System Settings > Apps > Gear Icon > Special Access > Battery
Optimization.




sadly there is




No known solution on the developer end







share|improve this answer

























  • Good post thank you. Regarding Fused Provider API being killed.... I dont expect that system to be killed, but my reference to the Fused Provider Listener is in my service so when my service is killed i cannot receive updates until the service is restarted, and my FusedProviderListener is re-created and re-subscribed

    – user1202032
    Apr 12 '18 at 12:22











  • That's true. You can use the last known location to try to fill in the blank (a bit). Unfortunately google does not allow programmatic access to the users location history.

    – leonardkraemer
    Apr 12 '18 at 12:39







  • 2





    Update: START_STICKY is completely unreliable. Sometimes the service is restarted but often its not... its killed and never ever restarted. The "Neverending service" link you posed is not going to work consistently as onDestroy() is not called consistently (by design)

    – user1202032
    Apr 16 '18 at 18:04











  • Good to know, do you know the exact circumstance when it is not restarted? Probably it's vendor specific though. As M D P suggested you can use AlarmManager to make sure the service is triggered/restarted at a constant interval. It seems to be the critical part, not sure about the other stuff.

    – leonardkraemer
    Apr 16 '18 at 20:35






  • 1





    @TKK I waited more than 1 hour

    – user1202032
    Apr 17 '18 at 6:52


















2














I know it's late but this may help some one. I too faced the same problem of keeping the foreground service alive without being killed by OS from different manufacturers. Most of the Chinese manufacturer's OS kills the foreground service even if it is added to the exception lists (Battery, Cleaner, etc) and allowed to auto start.



I found this link which solved me this long time problem of keeping the service alive.



All you have to do is run your foreground service in a seperate process. That's it.



You can do that by adding android:process to your service in your AndroidManifest.xml.



For Example:



<service android:name=".YourService"
android:process=":yourProcessName" />


You can refer the docs to know more about android:process



EDIT: SharedPreferences won't work across multiple processes. In this case, you must go for IPC (Inter Process Communication) methods or you can use ContentProviders for storing and accessing your data to be used across processes. Referred from docs.






share|improve this answer

























  • Thank you, my foreground service is no longer terminated on my Redmi Note 6 Pro

    – k8C
    Mar 24 at 4:48











  • @KhoaChuAnh It will work like a charm, until you don't use the same SharedPreferences across two processes.

    – Joshua
    Mar 26 at 9:00












  • I use SharedPreferences in my service with the android:process attribute without problems. As I have read somewhere on the Internet, you can still use BroadcastReceiver, ResultReceiver or Messenger to communicate between activity and service running in another process

    – k8C
    Mar 27 at 10:02











  • Yes, Messenger and ResultReceiver are some of the IPC methods. But those doesn't seem to work in the background. BroadcastReceiver works in background but from oreo and up, it has some limitations like only few events per hour will be received in the background (when it's in the background for a long time) even if it's an explicit broadcast (That's what I read somewhere).

    – Joshua
    Mar 27 at 11:37


















0














I suggest you use these:
AlarmManager, PowerManager, WakeLock, Thread, WakefulBroadcastReceiver, Handler, Looper



I assume you already are using those "separate process" and other tweaks too.



So in your Application class:



MyApp.java:



import android.app.AlarmManager;
import android.app.Application;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.util.Log;

public final class MyApp extends Application

public static PendingIntent pendingIntent = null;
public static Thread infiniteRunningThread;
public static PowerManager pm;
public static PowerManager.WakeLock wl;


@Override
public void onCreate()
try
Thread.setDefaultUncaughtExceptionHandler(
(thread, e)->restartApp(this, "MyApp uncaughtException:", e));
catch(SecurityException e)
restartApp(this, "MyApp uncaughtException SecurityException", e);
e.printStackTrace();

pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if(pm != null)
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TAG");
wl.acquire(10 * 60 * 1000L /*10 minutes*/);


infiniteRunningThread = new Thread();

super.onCreate();


public static void restartApp(Context ctx, String callerName, Throwable e)
Log.w("TAG", "restartApp called from " + callerName);
wl.release();
if(pendingIntent == null)
pendingIntent =
PendingIntent.getActivity(ctx, 0,
new Intent(ctx, ActivityMain.class), 0);

AlarmManager mgr = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
if(mgr != null)
mgr.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + 10, pendingIntent);

if(e != null)
e.printStackTrace();

System.exit(2);




And then in your service:



ServiceTrackerTest.java:



import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.PowerManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.WakefulBroadcastReceiver;

public class ServiceTrackerTest extends Service

private static final int SERVICE_ID = 2018;
private static PowerManager.WakeLock wl;

@Override
public IBinder onBind(Intent intent)
return null;


@Override
public void onCreate()
super.onCreate();
try
Thread.setDefaultUncaughtExceptionHandler(
(thread, e)->MyApp.restartApp(this,
"called from ServiceTracker onCreate "
+ "uncaughtException:", e));
catch(SecurityException e)
MyApp.restartApp(this,
"called from ServiceTracker onCreate uncaughtException "
+ "SecurityException", e);
e.printStackTrace();

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if(pm != null)
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TAG");
wl.acquire(10 * 60 * 1000L /*10 minutes*/);



Handler h = new Handler();
h.postDelayed(()->

MyApp.infiniteRunningThread = new Thread(()->
try
Thread.setDefaultUncaughtExceptionHandler(
(thread, e)->MyApp.restartApp(this,
"called from ServiceTracker onCreate "
+ "uncaughtException "
+ "infiniteRunningThread:", e));
catch(SecurityException e)
MyApp.restartApp(this,
"called from ServiceTracker onCreate uncaughtException "
+ "SecurityException "
+ "infiniteRunningThread", e);
e.printStackTrace();


Looper.prepare();
infiniteRunning();
Looper.loop();
);
MyApp.infiniteRunningThread.start();
, 5000);


@Override
public void onDestroy()
wl.release();
MyApp.restartApp(this, "ServiceTracker onDestroy", null);


@SuppressWarnings("deprecation")
@Override
public int onStartCommand(Intent intent, int flags, int startId)
if(intent != null)
try
WakefulBroadcastReceiver.completeWakefulIntent(intent);
catch(Exception e)
e.printStackTrace();


startForeground(SERVICE_ID, getNotificationBuilder().build());
return START_STICKY;



private void infiniteRunning()
//do your stuff here
Handler h = new Handler();
h.postDelayed(this::infiniteRunning, 300000);//5 minutes interval


@SuppressWarnings("deprecation")
private NotificationCompat.Builder getNotificationBuilder()
return new NotificationCompat.Builder(this)
.setContentIntent(MyApp.pendingIntent)
.setContentText(getString(R.string.notification_text))
.setContentTitle(getString(R.string.app_name))
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher))
.setSmallIcon(R.drawable.ic_stat_tracking_service);





Ignore "Deprecation" and stuff, use them when you have no choice.
I think the code is clear and doesn't need to be explained.
It's just about workaround suggestions and solutions.






share|improve this answer























  • As far as I can see this restarts the service after 5 to 10 minutes. Is this faster or more reliable than the system wise restart for START_STICKY?

    – leonardkraemer
    Apr 12 '18 at 12:45











  • Also since lolipop the alarm manager can not be abused in this way see stackoverflow.com/questions/29914724/…

    – leonardkraemer
    Apr 12 '18 at 12:59











  • @leoderprofi yes, START_STICKY is just a joke, and no it doesn't restart after interval, I copied from my own app that is being used for over 2 years now, it saves last best location on every interval inside infiniteRunning() method, it only restarts when an error happens. and don't worry about lollipop, I've set minSdkVersion to 14 and targetSdkVersion and compileSdkVersion to 27. and it's working just fine even on android N.

    – M D P
    Apr 12 '18 at 16:44












  • It certainly should be reliable since people are getting paid based on the location history my app reports to server. so yes it's more reliable.

    – M D P
    Apr 12 '18 at 16:52











  • @M D P that is not how minSdkVersion works, it doesn't change how a certain version of android behaves, just on what devices the app runs. Can you elaborate what mechanism restarts the app, when it was closed due to memory pressure and what mechanisms are used to prevent closing?

    – leonardkraemer
    Apr 12 '18 at 16:59













Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f49637967%2fminimal-android-foreground-service-killed-on-high-end-phone%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes









16





+50









A service started by startForeground besongs to the second most important group visible process:





  1. A visible process is doing work that the user is currently aware of,
    so killing it would have a noticeable negative impact on the user
    experience. A process is considered visible in the following
    conditions:



    1. It is running an Activity that is visible to the user on-screen but not in the foreground (its onPause() method has been called). This
      may occur, for example, if the foreground Activity is displayed as a
      dialog that allows the previous Activity to be seen behind it.


    2. It has a Service that is running as a foreground service, through Service.startForeground() (which is asking the system to treat the
      service as something the user is aware of, or essentially visible to
      them).


    3. It is hosting a service that the system is using for a particular feature that the user is aware, such as a live wallpaper, input method
      service, etc.

    The number of these processes running in the system is less bounded
    than foreground processes, but still relatively controlled. These
    processes are considered extremely important and will not be killed
    unless doing so is required to keep all foreground processes running
    .





That being said, you can never be sure that your service is not killed at any time. E.g. memory pressure, low battery etc. See who-lives-and-who-dies.




For how to handle it, basically you answered the question yourself. The way to go is START_STICKY:




For started services, there are two additional major modes of
operation they can decide to run in, depending on the value they
return from onStartCommand(): START_STICKY is used for services that
are explicitly started and stopped as needed, while START_NOT_STICKY
or START_REDELIVER_INTENT are used for services that should only
remain running while processing any commands sent to them
. See the
linked documentation for more detail on the semantics.




As a general guideline you should do as little as possible in the background (ore foreground) service, i.e. only do the location tracking and keep everything else in your foreground activity. Only the tracking should require very little configuration an can be loaded quickly. Also the smaller your service is the less likely it is to be killed. Your activity will be restored by the system in the state that is was before it went into background, as long as it is not killed as well. A "cold-start" of the foreground activity on the other hand should not be a problem.

I don't consider that as ugly, because this guarantees that the phone always provides the best experience to the user. This is the most important thing it has to do. That some devices close services after 30 minutes (possibly without user interaction) is unfortunate.



So, as you stated, you have to




Persist everything in the service in e.g. a Room database. Every
variable, every custom class, every time any of them changes and then
start the service with START_STICKY.




See creating a never ending service



Implicit question:




Depending on how long it takes for Android to re-create the
service after killing it, a large portion of locations may be lost.




This usually takes only a really short time. Especially because you can use the Fused Location Provider Api for the location updates, which is an independent system service and very unlikely to be killed. So it mainly depends on the time you need to recreate the service in onStartCommand.




Also take note that from Android 8.0 onwards you need to use a
forground service because of the background location
limits.





Edit:
As recently covered in the news:
Some manufacturers may give you a hard time to keep your service running. The site https://dontkillmyapp.com/ keeps track of the manufacturers and possible mitigations for your device. Oneplus is currently (29.01.19) one of the worst offenders.




When releasing their 1+5 and 1+6 phones, OnePlus introduced one of the
most severe background limits on the market to date, dwarfing even
those performed by Xiaomi or Huawei. Not only did users need to enable
extra settings to make their apps work properly, but those settings
even get reset with firmware update so that apps break again and users
are required to re-enable those settings on a regular basis.



Solution for users



Turn off System Settings > Apps > Gear Icon > Special Access > Battery
Optimization.




sadly there is




No known solution on the developer end







share|improve this answer

























  • Good post thank you. Regarding Fused Provider API being killed.... I dont expect that system to be killed, but my reference to the Fused Provider Listener is in my service so when my service is killed i cannot receive updates until the service is restarted, and my FusedProviderListener is re-created and re-subscribed

    – user1202032
    Apr 12 '18 at 12:22











  • That's true. You can use the last known location to try to fill in the blank (a bit). Unfortunately google does not allow programmatic access to the users location history.

    – leonardkraemer
    Apr 12 '18 at 12:39







  • 2





    Update: START_STICKY is completely unreliable. Sometimes the service is restarted but often its not... its killed and never ever restarted. The "Neverending service" link you posed is not going to work consistently as onDestroy() is not called consistently (by design)

    – user1202032
    Apr 16 '18 at 18:04











  • Good to know, do you know the exact circumstance when it is not restarted? Probably it's vendor specific though. As M D P suggested you can use AlarmManager to make sure the service is triggered/restarted at a constant interval. It seems to be the critical part, not sure about the other stuff.

    – leonardkraemer
    Apr 16 '18 at 20:35






  • 1





    @TKK I waited more than 1 hour

    – user1202032
    Apr 17 '18 at 6:52















16





+50









A service started by startForeground besongs to the second most important group visible process:





  1. A visible process is doing work that the user is currently aware of,
    so killing it would have a noticeable negative impact on the user
    experience. A process is considered visible in the following
    conditions:



    1. It is running an Activity that is visible to the user on-screen but not in the foreground (its onPause() method has been called). This
      may occur, for example, if the foreground Activity is displayed as a
      dialog that allows the previous Activity to be seen behind it.


    2. It has a Service that is running as a foreground service, through Service.startForeground() (which is asking the system to treat the
      service as something the user is aware of, or essentially visible to
      them).


    3. It is hosting a service that the system is using for a particular feature that the user is aware, such as a live wallpaper, input method
      service, etc.

    The number of these processes running in the system is less bounded
    than foreground processes, but still relatively controlled. These
    processes are considered extremely important and will not be killed
    unless doing so is required to keep all foreground processes running
    .





That being said, you can never be sure that your service is not killed at any time. E.g. memory pressure, low battery etc. See who-lives-and-who-dies.




For how to handle it, basically you answered the question yourself. The way to go is START_STICKY:




For started services, there are two additional major modes of
operation they can decide to run in, depending on the value they
return from onStartCommand(): START_STICKY is used for services that
are explicitly started and stopped as needed, while START_NOT_STICKY
or START_REDELIVER_INTENT are used for services that should only
remain running while processing any commands sent to them
. See the
linked documentation for more detail on the semantics.




As a general guideline you should do as little as possible in the background (ore foreground) service, i.e. only do the location tracking and keep everything else in your foreground activity. Only the tracking should require very little configuration an can be loaded quickly. Also the smaller your service is the less likely it is to be killed. Your activity will be restored by the system in the state that is was before it went into background, as long as it is not killed as well. A "cold-start" of the foreground activity on the other hand should not be a problem.

I don't consider that as ugly, because this guarantees that the phone always provides the best experience to the user. This is the most important thing it has to do. That some devices close services after 30 minutes (possibly without user interaction) is unfortunate.



So, as you stated, you have to




Persist everything in the service in e.g. a Room database. Every
variable, every custom class, every time any of them changes and then
start the service with START_STICKY.




See creating a never ending service



Implicit question:




Depending on how long it takes for Android to re-create the
service after killing it, a large portion of locations may be lost.




This usually takes only a really short time. Especially because you can use the Fused Location Provider Api for the location updates, which is an independent system service and very unlikely to be killed. So it mainly depends on the time you need to recreate the service in onStartCommand.




Also take note that from Android 8.0 onwards you need to use a
forground service because of the background location
limits.





Edit:
As recently covered in the news:
Some manufacturers may give you a hard time to keep your service running. The site https://dontkillmyapp.com/ keeps track of the manufacturers and possible mitigations for your device. Oneplus is currently (29.01.19) one of the worst offenders.




When releasing their 1+5 and 1+6 phones, OnePlus introduced one of the
most severe background limits on the market to date, dwarfing even
those performed by Xiaomi or Huawei. Not only did users need to enable
extra settings to make their apps work properly, but those settings
even get reset with firmware update so that apps break again and users
are required to re-enable those settings on a regular basis.



Solution for users



Turn off System Settings > Apps > Gear Icon > Special Access > Battery
Optimization.




sadly there is




No known solution on the developer end







share|improve this answer

























  • Good post thank you. Regarding Fused Provider API being killed.... I dont expect that system to be killed, but my reference to the Fused Provider Listener is in my service so when my service is killed i cannot receive updates until the service is restarted, and my FusedProviderListener is re-created and re-subscribed

    – user1202032
    Apr 12 '18 at 12:22











  • That's true. You can use the last known location to try to fill in the blank (a bit). Unfortunately google does not allow programmatic access to the users location history.

    – leonardkraemer
    Apr 12 '18 at 12:39







  • 2





    Update: START_STICKY is completely unreliable. Sometimes the service is restarted but often its not... its killed and never ever restarted. The "Neverending service" link you posed is not going to work consistently as onDestroy() is not called consistently (by design)

    – user1202032
    Apr 16 '18 at 18:04











  • Good to know, do you know the exact circumstance when it is not restarted? Probably it's vendor specific though. As M D P suggested you can use AlarmManager to make sure the service is triggered/restarted at a constant interval. It seems to be the critical part, not sure about the other stuff.

    – leonardkraemer
    Apr 16 '18 at 20:35






  • 1





    @TKK I waited more than 1 hour

    – user1202032
    Apr 17 '18 at 6:52













16





+50







16





+50



16




+50





A service started by startForeground besongs to the second most important group visible process:





  1. A visible process is doing work that the user is currently aware of,
    so killing it would have a noticeable negative impact on the user
    experience. A process is considered visible in the following
    conditions:



    1. It is running an Activity that is visible to the user on-screen but not in the foreground (its onPause() method has been called). This
      may occur, for example, if the foreground Activity is displayed as a
      dialog that allows the previous Activity to be seen behind it.


    2. It has a Service that is running as a foreground service, through Service.startForeground() (which is asking the system to treat the
      service as something the user is aware of, or essentially visible to
      them).


    3. It is hosting a service that the system is using for a particular feature that the user is aware, such as a live wallpaper, input method
      service, etc.

    The number of these processes running in the system is less bounded
    than foreground processes, but still relatively controlled. These
    processes are considered extremely important and will not be killed
    unless doing so is required to keep all foreground processes running
    .





That being said, you can never be sure that your service is not killed at any time. E.g. memory pressure, low battery etc. See who-lives-and-who-dies.




For how to handle it, basically you answered the question yourself. The way to go is START_STICKY:




For started services, there are two additional major modes of
operation they can decide to run in, depending on the value they
return from onStartCommand(): START_STICKY is used for services that
are explicitly started and stopped as needed, while START_NOT_STICKY
or START_REDELIVER_INTENT are used for services that should only
remain running while processing any commands sent to them
. See the
linked documentation for more detail on the semantics.




As a general guideline you should do as little as possible in the background (ore foreground) service, i.e. only do the location tracking and keep everything else in your foreground activity. Only the tracking should require very little configuration an can be loaded quickly. Also the smaller your service is the less likely it is to be killed. Your activity will be restored by the system in the state that is was before it went into background, as long as it is not killed as well. A "cold-start" of the foreground activity on the other hand should not be a problem.

I don't consider that as ugly, because this guarantees that the phone always provides the best experience to the user. This is the most important thing it has to do. That some devices close services after 30 minutes (possibly without user interaction) is unfortunate.



So, as you stated, you have to




Persist everything in the service in e.g. a Room database. Every
variable, every custom class, every time any of them changes and then
start the service with START_STICKY.




See creating a never ending service



Implicit question:




Depending on how long it takes for Android to re-create the
service after killing it, a large portion of locations may be lost.




This usually takes only a really short time. Especially because you can use the Fused Location Provider Api for the location updates, which is an independent system service and very unlikely to be killed. So it mainly depends on the time you need to recreate the service in onStartCommand.




Also take note that from Android 8.0 onwards you need to use a
forground service because of the background location
limits.





Edit:
As recently covered in the news:
Some manufacturers may give you a hard time to keep your service running. The site https://dontkillmyapp.com/ keeps track of the manufacturers and possible mitigations for your device. Oneplus is currently (29.01.19) one of the worst offenders.




When releasing their 1+5 and 1+6 phones, OnePlus introduced one of the
most severe background limits on the market to date, dwarfing even
those performed by Xiaomi or Huawei. Not only did users need to enable
extra settings to make their apps work properly, but those settings
even get reset with firmware update so that apps break again and users
are required to re-enable those settings on a regular basis.



Solution for users



Turn off System Settings > Apps > Gear Icon > Special Access > Battery
Optimization.




sadly there is




No known solution on the developer end







share|improve this answer















A service started by startForeground besongs to the second most important group visible process:





  1. A visible process is doing work that the user is currently aware of,
    so killing it would have a noticeable negative impact on the user
    experience. A process is considered visible in the following
    conditions:



    1. It is running an Activity that is visible to the user on-screen but not in the foreground (its onPause() method has been called). This
      may occur, for example, if the foreground Activity is displayed as a
      dialog that allows the previous Activity to be seen behind it.


    2. It has a Service that is running as a foreground service, through Service.startForeground() (which is asking the system to treat the
      service as something the user is aware of, or essentially visible to
      them).


    3. It is hosting a service that the system is using for a particular feature that the user is aware, such as a live wallpaper, input method
      service, etc.

    The number of these processes running in the system is less bounded
    than foreground processes, but still relatively controlled. These
    processes are considered extremely important and will not be killed
    unless doing so is required to keep all foreground processes running
    .





That being said, you can never be sure that your service is not killed at any time. E.g. memory pressure, low battery etc. See who-lives-and-who-dies.




For how to handle it, basically you answered the question yourself. The way to go is START_STICKY:




For started services, there are two additional major modes of
operation they can decide to run in, depending on the value they
return from onStartCommand(): START_STICKY is used for services that
are explicitly started and stopped as needed, while START_NOT_STICKY
or START_REDELIVER_INTENT are used for services that should only
remain running while processing any commands sent to them
. See the
linked documentation for more detail on the semantics.




As a general guideline you should do as little as possible in the background (ore foreground) service, i.e. only do the location tracking and keep everything else in your foreground activity. Only the tracking should require very little configuration an can be loaded quickly. Also the smaller your service is the less likely it is to be killed. Your activity will be restored by the system in the state that is was before it went into background, as long as it is not killed as well. A "cold-start" of the foreground activity on the other hand should not be a problem.

I don't consider that as ugly, because this guarantees that the phone always provides the best experience to the user. This is the most important thing it has to do. That some devices close services after 30 minutes (possibly without user interaction) is unfortunate.



So, as you stated, you have to




Persist everything in the service in e.g. a Room database. Every
variable, every custom class, every time any of them changes and then
start the service with START_STICKY.




See creating a never ending service



Implicit question:




Depending on how long it takes for Android to re-create the
service after killing it, a large portion of locations may be lost.




This usually takes only a really short time. Especially because you can use the Fused Location Provider Api for the location updates, which is an independent system service and very unlikely to be killed. So it mainly depends on the time you need to recreate the service in onStartCommand.




Also take note that from Android 8.0 onwards you need to use a
forground service because of the background location
limits.





Edit:
As recently covered in the news:
Some manufacturers may give you a hard time to keep your service running. The site https://dontkillmyapp.com/ keeps track of the manufacturers and possible mitigations for your device. Oneplus is currently (29.01.19) one of the worst offenders.




When releasing their 1+5 and 1+6 phones, OnePlus introduced one of the
most severe background limits on the market to date, dwarfing even
those performed by Xiaomi or Huawei. Not only did users need to enable
extra settings to make their apps work properly, but those settings
even get reset with firmware update so that apps break again and users
are required to re-enable those settings on a regular basis.



Solution for users



Turn off System Settings > Apps > Gear Icon > Special Access > Battery
Optimization.




sadly there is




No known solution on the developer end








share|improve this answer














share|improve this answer



share|improve this answer








edited Feb 15 at 15:55

























answered Apr 11 '18 at 18:39









leonardkraemerleonardkraemer

3,8691 gold badge17 silver badges36 bronze badges




3,8691 gold badge17 silver badges36 bronze badges












  • Good post thank you. Regarding Fused Provider API being killed.... I dont expect that system to be killed, but my reference to the Fused Provider Listener is in my service so when my service is killed i cannot receive updates until the service is restarted, and my FusedProviderListener is re-created and re-subscribed

    – user1202032
    Apr 12 '18 at 12:22











  • That's true. You can use the last known location to try to fill in the blank (a bit). Unfortunately google does not allow programmatic access to the users location history.

    – leonardkraemer
    Apr 12 '18 at 12:39







  • 2





    Update: START_STICKY is completely unreliable. Sometimes the service is restarted but often its not... its killed and never ever restarted. The "Neverending service" link you posed is not going to work consistently as onDestroy() is not called consistently (by design)

    – user1202032
    Apr 16 '18 at 18:04











  • Good to know, do you know the exact circumstance when it is not restarted? Probably it's vendor specific though. As M D P suggested you can use AlarmManager to make sure the service is triggered/restarted at a constant interval. It seems to be the critical part, not sure about the other stuff.

    – leonardkraemer
    Apr 16 '18 at 20:35






  • 1





    @TKK I waited more than 1 hour

    – user1202032
    Apr 17 '18 at 6:52

















  • Good post thank you. Regarding Fused Provider API being killed.... I dont expect that system to be killed, but my reference to the Fused Provider Listener is in my service so when my service is killed i cannot receive updates until the service is restarted, and my FusedProviderListener is re-created and re-subscribed

    – user1202032
    Apr 12 '18 at 12:22











  • That's true. You can use the last known location to try to fill in the blank (a bit). Unfortunately google does not allow programmatic access to the users location history.

    – leonardkraemer
    Apr 12 '18 at 12:39







  • 2





    Update: START_STICKY is completely unreliable. Sometimes the service is restarted but often its not... its killed and never ever restarted. The "Neverending service" link you posed is not going to work consistently as onDestroy() is not called consistently (by design)

    – user1202032
    Apr 16 '18 at 18:04











  • Good to know, do you know the exact circumstance when it is not restarted? Probably it's vendor specific though. As M D P suggested you can use AlarmManager to make sure the service is triggered/restarted at a constant interval. It seems to be the critical part, not sure about the other stuff.

    – leonardkraemer
    Apr 16 '18 at 20:35






  • 1





    @TKK I waited more than 1 hour

    – user1202032
    Apr 17 '18 at 6:52
















Good post thank you. Regarding Fused Provider API being killed.... I dont expect that system to be killed, but my reference to the Fused Provider Listener is in my service so when my service is killed i cannot receive updates until the service is restarted, and my FusedProviderListener is re-created and re-subscribed

– user1202032
Apr 12 '18 at 12:22





Good post thank you. Regarding Fused Provider API being killed.... I dont expect that system to be killed, but my reference to the Fused Provider Listener is in my service so when my service is killed i cannot receive updates until the service is restarted, and my FusedProviderListener is re-created and re-subscribed

– user1202032
Apr 12 '18 at 12:22













That's true. You can use the last known location to try to fill in the blank (a bit). Unfortunately google does not allow programmatic access to the users location history.

– leonardkraemer
Apr 12 '18 at 12:39






That's true. You can use the last known location to try to fill in the blank (a bit). Unfortunately google does not allow programmatic access to the users location history.

– leonardkraemer
Apr 12 '18 at 12:39





2




2





Update: START_STICKY is completely unreliable. Sometimes the service is restarted but often its not... its killed and never ever restarted. The "Neverending service" link you posed is not going to work consistently as onDestroy() is not called consistently (by design)

– user1202032
Apr 16 '18 at 18:04





Update: START_STICKY is completely unreliable. Sometimes the service is restarted but often its not... its killed and never ever restarted. The "Neverending service" link you posed is not going to work consistently as onDestroy() is not called consistently (by design)

– user1202032
Apr 16 '18 at 18:04













Good to know, do you know the exact circumstance when it is not restarted? Probably it's vendor specific though. As M D P suggested you can use AlarmManager to make sure the service is triggered/restarted at a constant interval. It seems to be the critical part, not sure about the other stuff.

– leonardkraemer
Apr 16 '18 at 20:35





Good to know, do you know the exact circumstance when it is not restarted? Probably it's vendor specific though. As M D P suggested you can use AlarmManager to make sure the service is triggered/restarted at a constant interval. It seems to be the critical part, not sure about the other stuff.

– leonardkraemer
Apr 16 '18 at 20:35




1




1





@TKK I waited more than 1 hour

– user1202032
Apr 17 '18 at 6:52





@TKK I waited more than 1 hour

– user1202032
Apr 17 '18 at 6:52













2














I know it's late but this may help some one. I too faced the same problem of keeping the foreground service alive without being killed by OS from different manufacturers. Most of the Chinese manufacturer's OS kills the foreground service even if it is added to the exception lists (Battery, Cleaner, etc) and allowed to auto start.



I found this link which solved me this long time problem of keeping the service alive.



All you have to do is run your foreground service in a seperate process. That's it.



You can do that by adding android:process to your service in your AndroidManifest.xml.



For Example:



<service android:name=".YourService"
android:process=":yourProcessName" />


You can refer the docs to know more about android:process



EDIT: SharedPreferences won't work across multiple processes. In this case, you must go for IPC (Inter Process Communication) methods or you can use ContentProviders for storing and accessing your data to be used across processes. Referred from docs.






share|improve this answer

























  • Thank you, my foreground service is no longer terminated on my Redmi Note 6 Pro

    – k8C
    Mar 24 at 4:48











  • @KhoaChuAnh It will work like a charm, until you don't use the same SharedPreferences across two processes.

    – Joshua
    Mar 26 at 9:00












  • I use SharedPreferences in my service with the android:process attribute without problems. As I have read somewhere on the Internet, you can still use BroadcastReceiver, ResultReceiver or Messenger to communicate between activity and service running in another process

    – k8C
    Mar 27 at 10:02











  • Yes, Messenger and ResultReceiver are some of the IPC methods. But those doesn't seem to work in the background. BroadcastReceiver works in background but from oreo and up, it has some limitations like only few events per hour will be received in the background (when it's in the background for a long time) even if it's an explicit broadcast (That's what I read somewhere).

    – Joshua
    Mar 27 at 11:37















2














I know it's late but this may help some one. I too faced the same problem of keeping the foreground service alive without being killed by OS from different manufacturers. Most of the Chinese manufacturer's OS kills the foreground service even if it is added to the exception lists (Battery, Cleaner, etc) and allowed to auto start.



I found this link which solved me this long time problem of keeping the service alive.



All you have to do is run your foreground service in a seperate process. That's it.



You can do that by adding android:process to your service in your AndroidManifest.xml.



For Example:



<service android:name=".YourService"
android:process=":yourProcessName" />


You can refer the docs to know more about android:process



EDIT: SharedPreferences won't work across multiple processes. In this case, you must go for IPC (Inter Process Communication) methods or you can use ContentProviders for storing and accessing your data to be used across processes. Referred from docs.






share|improve this answer

























  • Thank you, my foreground service is no longer terminated on my Redmi Note 6 Pro

    – k8C
    Mar 24 at 4:48











  • @KhoaChuAnh It will work like a charm, until you don't use the same SharedPreferences across two processes.

    – Joshua
    Mar 26 at 9:00












  • I use SharedPreferences in my service with the android:process attribute without problems. As I have read somewhere on the Internet, you can still use BroadcastReceiver, ResultReceiver or Messenger to communicate between activity and service running in another process

    – k8C
    Mar 27 at 10:02











  • Yes, Messenger and ResultReceiver are some of the IPC methods. But those doesn't seem to work in the background. BroadcastReceiver works in background but from oreo and up, it has some limitations like only few events per hour will be received in the background (when it's in the background for a long time) even if it's an explicit broadcast (That's what I read somewhere).

    – Joshua
    Mar 27 at 11:37













2












2








2







I know it's late but this may help some one. I too faced the same problem of keeping the foreground service alive without being killed by OS from different manufacturers. Most of the Chinese manufacturer's OS kills the foreground service even if it is added to the exception lists (Battery, Cleaner, etc) and allowed to auto start.



I found this link which solved me this long time problem of keeping the service alive.



All you have to do is run your foreground service in a seperate process. That's it.



You can do that by adding android:process to your service in your AndroidManifest.xml.



For Example:



<service android:name=".YourService"
android:process=":yourProcessName" />


You can refer the docs to know more about android:process



EDIT: SharedPreferences won't work across multiple processes. In this case, you must go for IPC (Inter Process Communication) methods or you can use ContentProviders for storing and accessing your data to be used across processes. Referred from docs.






share|improve this answer















I know it's late but this may help some one. I too faced the same problem of keeping the foreground service alive without being killed by OS from different manufacturers. Most of the Chinese manufacturer's OS kills the foreground service even if it is added to the exception lists (Battery, Cleaner, etc) and allowed to auto start.



I found this link which solved me this long time problem of keeping the service alive.



All you have to do is run your foreground service in a seperate process. That's it.



You can do that by adding android:process to your service in your AndroidManifest.xml.



For Example:



<service android:name=".YourService"
android:process=":yourProcessName" />


You can refer the docs to know more about android:process



EDIT: SharedPreferences won't work across multiple processes. In this case, you must go for IPC (Inter Process Communication) methods or you can use ContentProviders for storing and accessing your data to be used across processes. Referred from docs.







share|improve this answer














share|improve this answer



share|improve this answer








edited Mar 26 at 9:08

























answered Mar 6 at 11:55









JoshuaJoshua

1622 silver badges17 bronze badges




1622 silver badges17 bronze badges












  • Thank you, my foreground service is no longer terminated on my Redmi Note 6 Pro

    – k8C
    Mar 24 at 4:48











  • @KhoaChuAnh It will work like a charm, until you don't use the same SharedPreferences across two processes.

    – Joshua
    Mar 26 at 9:00












  • I use SharedPreferences in my service with the android:process attribute without problems. As I have read somewhere on the Internet, you can still use BroadcastReceiver, ResultReceiver or Messenger to communicate between activity and service running in another process

    – k8C
    Mar 27 at 10:02











  • Yes, Messenger and ResultReceiver are some of the IPC methods. But those doesn't seem to work in the background. BroadcastReceiver works in background but from oreo and up, it has some limitations like only few events per hour will be received in the background (when it's in the background for a long time) even if it's an explicit broadcast (That's what I read somewhere).

    – Joshua
    Mar 27 at 11:37

















  • Thank you, my foreground service is no longer terminated on my Redmi Note 6 Pro

    – k8C
    Mar 24 at 4:48











  • @KhoaChuAnh It will work like a charm, until you don't use the same SharedPreferences across two processes.

    – Joshua
    Mar 26 at 9:00












  • I use SharedPreferences in my service with the android:process attribute without problems. As I have read somewhere on the Internet, you can still use BroadcastReceiver, ResultReceiver or Messenger to communicate between activity and service running in another process

    – k8C
    Mar 27 at 10:02











  • Yes, Messenger and ResultReceiver are some of the IPC methods. But those doesn't seem to work in the background. BroadcastReceiver works in background but from oreo and up, it has some limitations like only few events per hour will be received in the background (when it's in the background for a long time) even if it's an explicit broadcast (That's what I read somewhere).

    – Joshua
    Mar 27 at 11:37
















Thank you, my foreground service is no longer terminated on my Redmi Note 6 Pro

– k8C
Mar 24 at 4:48





Thank you, my foreground service is no longer terminated on my Redmi Note 6 Pro

– k8C
Mar 24 at 4:48













@KhoaChuAnh It will work like a charm, until you don't use the same SharedPreferences across two processes.

– Joshua
Mar 26 at 9:00






@KhoaChuAnh It will work like a charm, until you don't use the same SharedPreferences across two processes.

– Joshua
Mar 26 at 9:00














I use SharedPreferences in my service with the android:process attribute without problems. As I have read somewhere on the Internet, you can still use BroadcastReceiver, ResultReceiver or Messenger to communicate between activity and service running in another process

– k8C
Mar 27 at 10:02





I use SharedPreferences in my service with the android:process attribute without problems. As I have read somewhere on the Internet, you can still use BroadcastReceiver, ResultReceiver or Messenger to communicate between activity and service running in another process

– k8C
Mar 27 at 10:02













Yes, Messenger and ResultReceiver are some of the IPC methods. But those doesn't seem to work in the background. BroadcastReceiver works in background but from oreo and up, it has some limitations like only few events per hour will be received in the background (when it's in the background for a long time) even if it's an explicit broadcast (That's what I read somewhere).

– Joshua
Mar 27 at 11:37





Yes, Messenger and ResultReceiver are some of the IPC methods. But those doesn't seem to work in the background. BroadcastReceiver works in background but from oreo and up, it has some limitations like only few events per hour will be received in the background (when it's in the background for a long time) even if it's an explicit broadcast (That's what I read somewhere).

– Joshua
Mar 27 at 11:37











0














I suggest you use these:
AlarmManager, PowerManager, WakeLock, Thread, WakefulBroadcastReceiver, Handler, Looper



I assume you already are using those "separate process" and other tweaks too.



So in your Application class:



MyApp.java:



import android.app.AlarmManager;
import android.app.Application;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.util.Log;

public final class MyApp extends Application

public static PendingIntent pendingIntent = null;
public static Thread infiniteRunningThread;
public static PowerManager pm;
public static PowerManager.WakeLock wl;


@Override
public void onCreate()
try
Thread.setDefaultUncaughtExceptionHandler(
(thread, e)->restartApp(this, "MyApp uncaughtException:", e));
catch(SecurityException e)
restartApp(this, "MyApp uncaughtException SecurityException", e);
e.printStackTrace();

pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if(pm != null)
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TAG");
wl.acquire(10 * 60 * 1000L /*10 minutes*/);


infiniteRunningThread = new Thread();

super.onCreate();


public static void restartApp(Context ctx, String callerName, Throwable e)
Log.w("TAG", "restartApp called from " + callerName);
wl.release();
if(pendingIntent == null)
pendingIntent =
PendingIntent.getActivity(ctx, 0,
new Intent(ctx, ActivityMain.class), 0);

AlarmManager mgr = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
if(mgr != null)
mgr.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + 10, pendingIntent);

if(e != null)
e.printStackTrace();

System.exit(2);




And then in your service:



ServiceTrackerTest.java:



import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.PowerManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.WakefulBroadcastReceiver;

public class ServiceTrackerTest extends Service

private static final int SERVICE_ID = 2018;
private static PowerManager.WakeLock wl;

@Override
public IBinder onBind(Intent intent)
return null;


@Override
public void onCreate()
super.onCreate();
try
Thread.setDefaultUncaughtExceptionHandler(
(thread, e)->MyApp.restartApp(this,
"called from ServiceTracker onCreate "
+ "uncaughtException:", e));
catch(SecurityException e)
MyApp.restartApp(this,
"called from ServiceTracker onCreate uncaughtException "
+ "SecurityException", e);
e.printStackTrace();

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if(pm != null)
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TAG");
wl.acquire(10 * 60 * 1000L /*10 minutes*/);



Handler h = new Handler();
h.postDelayed(()->

MyApp.infiniteRunningThread = new Thread(()->
try
Thread.setDefaultUncaughtExceptionHandler(
(thread, e)->MyApp.restartApp(this,
"called from ServiceTracker onCreate "
+ "uncaughtException "
+ "infiniteRunningThread:", e));
catch(SecurityException e)
MyApp.restartApp(this,
"called from ServiceTracker onCreate uncaughtException "
+ "SecurityException "
+ "infiniteRunningThread", e);
e.printStackTrace();


Looper.prepare();
infiniteRunning();
Looper.loop();
);
MyApp.infiniteRunningThread.start();
, 5000);


@Override
public void onDestroy()
wl.release();
MyApp.restartApp(this, "ServiceTracker onDestroy", null);


@SuppressWarnings("deprecation")
@Override
public int onStartCommand(Intent intent, int flags, int startId)
if(intent != null)
try
WakefulBroadcastReceiver.completeWakefulIntent(intent);
catch(Exception e)
e.printStackTrace();


startForeground(SERVICE_ID, getNotificationBuilder().build());
return START_STICKY;



private void infiniteRunning()
//do your stuff here
Handler h = new Handler();
h.postDelayed(this::infiniteRunning, 300000);//5 minutes interval


@SuppressWarnings("deprecation")
private NotificationCompat.Builder getNotificationBuilder()
return new NotificationCompat.Builder(this)
.setContentIntent(MyApp.pendingIntent)
.setContentText(getString(R.string.notification_text))
.setContentTitle(getString(R.string.app_name))
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher))
.setSmallIcon(R.drawable.ic_stat_tracking_service);





Ignore "Deprecation" and stuff, use them when you have no choice.
I think the code is clear and doesn't need to be explained.
It's just about workaround suggestions and solutions.






share|improve this answer























  • As far as I can see this restarts the service after 5 to 10 minutes. Is this faster or more reliable than the system wise restart for START_STICKY?

    – leonardkraemer
    Apr 12 '18 at 12:45











  • Also since lolipop the alarm manager can not be abused in this way see stackoverflow.com/questions/29914724/…

    – leonardkraemer
    Apr 12 '18 at 12:59











  • @leoderprofi yes, START_STICKY is just a joke, and no it doesn't restart after interval, I copied from my own app that is being used for over 2 years now, it saves last best location on every interval inside infiniteRunning() method, it only restarts when an error happens. and don't worry about lollipop, I've set minSdkVersion to 14 and targetSdkVersion and compileSdkVersion to 27. and it's working just fine even on android N.

    – M D P
    Apr 12 '18 at 16:44












  • It certainly should be reliable since people are getting paid based on the location history my app reports to server. so yes it's more reliable.

    – M D P
    Apr 12 '18 at 16:52











  • @M D P that is not how minSdkVersion works, it doesn't change how a certain version of android behaves, just on what devices the app runs. Can you elaborate what mechanism restarts the app, when it was closed due to memory pressure and what mechanisms are used to prevent closing?

    – leonardkraemer
    Apr 12 '18 at 16:59















0














I suggest you use these:
AlarmManager, PowerManager, WakeLock, Thread, WakefulBroadcastReceiver, Handler, Looper



I assume you already are using those "separate process" and other tweaks too.



So in your Application class:



MyApp.java:



import android.app.AlarmManager;
import android.app.Application;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.util.Log;

public final class MyApp extends Application

public static PendingIntent pendingIntent = null;
public static Thread infiniteRunningThread;
public static PowerManager pm;
public static PowerManager.WakeLock wl;


@Override
public void onCreate()
try
Thread.setDefaultUncaughtExceptionHandler(
(thread, e)->restartApp(this, "MyApp uncaughtException:", e));
catch(SecurityException e)
restartApp(this, "MyApp uncaughtException SecurityException", e);
e.printStackTrace();

pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if(pm != null)
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TAG");
wl.acquire(10 * 60 * 1000L /*10 minutes*/);


infiniteRunningThread = new Thread();

super.onCreate();


public static void restartApp(Context ctx, String callerName, Throwable e)
Log.w("TAG", "restartApp called from " + callerName);
wl.release();
if(pendingIntent == null)
pendingIntent =
PendingIntent.getActivity(ctx, 0,
new Intent(ctx, ActivityMain.class), 0);

AlarmManager mgr = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
if(mgr != null)
mgr.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + 10, pendingIntent);

if(e != null)
e.printStackTrace();

System.exit(2);




And then in your service:



ServiceTrackerTest.java:



import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.PowerManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.WakefulBroadcastReceiver;

public class ServiceTrackerTest extends Service

private static final int SERVICE_ID = 2018;
private static PowerManager.WakeLock wl;

@Override
public IBinder onBind(Intent intent)
return null;


@Override
public void onCreate()
super.onCreate();
try
Thread.setDefaultUncaughtExceptionHandler(
(thread, e)->MyApp.restartApp(this,
"called from ServiceTracker onCreate "
+ "uncaughtException:", e));
catch(SecurityException e)
MyApp.restartApp(this,
"called from ServiceTracker onCreate uncaughtException "
+ "SecurityException", e);
e.printStackTrace();

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if(pm != null)
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TAG");
wl.acquire(10 * 60 * 1000L /*10 minutes*/);



Handler h = new Handler();
h.postDelayed(()->

MyApp.infiniteRunningThread = new Thread(()->
try
Thread.setDefaultUncaughtExceptionHandler(
(thread, e)->MyApp.restartApp(this,
"called from ServiceTracker onCreate "
+ "uncaughtException "
+ "infiniteRunningThread:", e));
catch(SecurityException e)
MyApp.restartApp(this,
"called from ServiceTracker onCreate uncaughtException "
+ "SecurityException "
+ "infiniteRunningThread", e);
e.printStackTrace();


Looper.prepare();
infiniteRunning();
Looper.loop();
);
MyApp.infiniteRunningThread.start();
, 5000);


@Override
public void onDestroy()
wl.release();
MyApp.restartApp(this, "ServiceTracker onDestroy", null);


@SuppressWarnings("deprecation")
@Override
public int onStartCommand(Intent intent, int flags, int startId)
if(intent != null)
try
WakefulBroadcastReceiver.completeWakefulIntent(intent);
catch(Exception e)
e.printStackTrace();


startForeground(SERVICE_ID, getNotificationBuilder().build());
return START_STICKY;



private void infiniteRunning()
//do your stuff here
Handler h = new Handler();
h.postDelayed(this::infiniteRunning, 300000);//5 minutes interval


@SuppressWarnings("deprecation")
private NotificationCompat.Builder getNotificationBuilder()
return new NotificationCompat.Builder(this)
.setContentIntent(MyApp.pendingIntent)
.setContentText(getString(R.string.notification_text))
.setContentTitle(getString(R.string.app_name))
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher))
.setSmallIcon(R.drawable.ic_stat_tracking_service);





Ignore "Deprecation" and stuff, use them when you have no choice.
I think the code is clear and doesn't need to be explained.
It's just about workaround suggestions and solutions.






share|improve this answer























  • As far as I can see this restarts the service after 5 to 10 minutes. Is this faster or more reliable than the system wise restart for START_STICKY?

    – leonardkraemer
    Apr 12 '18 at 12:45











  • Also since lolipop the alarm manager can not be abused in this way see stackoverflow.com/questions/29914724/…

    – leonardkraemer
    Apr 12 '18 at 12:59











  • @leoderprofi yes, START_STICKY is just a joke, and no it doesn't restart after interval, I copied from my own app that is being used for over 2 years now, it saves last best location on every interval inside infiniteRunning() method, it only restarts when an error happens. and don't worry about lollipop, I've set minSdkVersion to 14 and targetSdkVersion and compileSdkVersion to 27. and it's working just fine even on android N.

    – M D P
    Apr 12 '18 at 16:44












  • It certainly should be reliable since people are getting paid based on the location history my app reports to server. so yes it's more reliable.

    – M D P
    Apr 12 '18 at 16:52











  • @M D P that is not how minSdkVersion works, it doesn't change how a certain version of android behaves, just on what devices the app runs. Can you elaborate what mechanism restarts the app, when it was closed due to memory pressure and what mechanisms are used to prevent closing?

    – leonardkraemer
    Apr 12 '18 at 16:59













0












0








0







I suggest you use these:
AlarmManager, PowerManager, WakeLock, Thread, WakefulBroadcastReceiver, Handler, Looper



I assume you already are using those "separate process" and other tweaks too.



So in your Application class:



MyApp.java:



import android.app.AlarmManager;
import android.app.Application;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.util.Log;

public final class MyApp extends Application

public static PendingIntent pendingIntent = null;
public static Thread infiniteRunningThread;
public static PowerManager pm;
public static PowerManager.WakeLock wl;


@Override
public void onCreate()
try
Thread.setDefaultUncaughtExceptionHandler(
(thread, e)->restartApp(this, "MyApp uncaughtException:", e));
catch(SecurityException e)
restartApp(this, "MyApp uncaughtException SecurityException", e);
e.printStackTrace();

pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if(pm != null)
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TAG");
wl.acquire(10 * 60 * 1000L /*10 minutes*/);


infiniteRunningThread = new Thread();

super.onCreate();


public static void restartApp(Context ctx, String callerName, Throwable e)
Log.w("TAG", "restartApp called from " + callerName);
wl.release();
if(pendingIntent == null)
pendingIntent =
PendingIntent.getActivity(ctx, 0,
new Intent(ctx, ActivityMain.class), 0);

AlarmManager mgr = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
if(mgr != null)
mgr.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + 10, pendingIntent);

if(e != null)
e.printStackTrace();

System.exit(2);




And then in your service:



ServiceTrackerTest.java:



import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.PowerManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.WakefulBroadcastReceiver;

public class ServiceTrackerTest extends Service

private static final int SERVICE_ID = 2018;
private static PowerManager.WakeLock wl;

@Override
public IBinder onBind(Intent intent)
return null;


@Override
public void onCreate()
super.onCreate();
try
Thread.setDefaultUncaughtExceptionHandler(
(thread, e)->MyApp.restartApp(this,
"called from ServiceTracker onCreate "
+ "uncaughtException:", e));
catch(SecurityException e)
MyApp.restartApp(this,
"called from ServiceTracker onCreate uncaughtException "
+ "SecurityException", e);
e.printStackTrace();

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if(pm != null)
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TAG");
wl.acquire(10 * 60 * 1000L /*10 minutes*/);



Handler h = new Handler();
h.postDelayed(()->

MyApp.infiniteRunningThread = new Thread(()->
try
Thread.setDefaultUncaughtExceptionHandler(
(thread, e)->MyApp.restartApp(this,
"called from ServiceTracker onCreate "
+ "uncaughtException "
+ "infiniteRunningThread:", e));
catch(SecurityException e)
MyApp.restartApp(this,
"called from ServiceTracker onCreate uncaughtException "
+ "SecurityException "
+ "infiniteRunningThread", e);
e.printStackTrace();


Looper.prepare();
infiniteRunning();
Looper.loop();
);
MyApp.infiniteRunningThread.start();
, 5000);


@Override
public void onDestroy()
wl.release();
MyApp.restartApp(this, "ServiceTracker onDestroy", null);


@SuppressWarnings("deprecation")
@Override
public int onStartCommand(Intent intent, int flags, int startId)
if(intent != null)
try
WakefulBroadcastReceiver.completeWakefulIntent(intent);
catch(Exception e)
e.printStackTrace();


startForeground(SERVICE_ID, getNotificationBuilder().build());
return START_STICKY;



private void infiniteRunning()
//do your stuff here
Handler h = new Handler();
h.postDelayed(this::infiniteRunning, 300000);//5 minutes interval


@SuppressWarnings("deprecation")
private NotificationCompat.Builder getNotificationBuilder()
return new NotificationCompat.Builder(this)
.setContentIntent(MyApp.pendingIntent)
.setContentText(getString(R.string.notification_text))
.setContentTitle(getString(R.string.app_name))
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher))
.setSmallIcon(R.drawable.ic_stat_tracking_service);





Ignore "Deprecation" and stuff, use them when you have no choice.
I think the code is clear and doesn't need to be explained.
It's just about workaround suggestions and solutions.






share|improve this answer













I suggest you use these:
AlarmManager, PowerManager, WakeLock, Thread, WakefulBroadcastReceiver, Handler, Looper



I assume you already are using those "separate process" and other tweaks too.



So in your Application class:



MyApp.java:



import android.app.AlarmManager;
import android.app.Application;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.util.Log;

public final class MyApp extends Application

public static PendingIntent pendingIntent = null;
public static Thread infiniteRunningThread;
public static PowerManager pm;
public static PowerManager.WakeLock wl;


@Override
public void onCreate()
try
Thread.setDefaultUncaughtExceptionHandler(
(thread, e)->restartApp(this, "MyApp uncaughtException:", e));
catch(SecurityException e)
restartApp(this, "MyApp uncaughtException SecurityException", e);
e.printStackTrace();

pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if(pm != null)
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TAG");
wl.acquire(10 * 60 * 1000L /*10 minutes*/);


infiniteRunningThread = new Thread();

super.onCreate();


public static void restartApp(Context ctx, String callerName, Throwable e)
Log.w("TAG", "restartApp called from " + callerName);
wl.release();
if(pendingIntent == null)
pendingIntent =
PendingIntent.getActivity(ctx, 0,
new Intent(ctx, ActivityMain.class), 0);

AlarmManager mgr = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
if(mgr != null)
mgr.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + 10, pendingIntent);

if(e != null)
e.printStackTrace();

System.exit(2);




And then in your service:



ServiceTrackerTest.java:



import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.PowerManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.WakefulBroadcastReceiver;

public class ServiceTrackerTest extends Service

private static final int SERVICE_ID = 2018;
private static PowerManager.WakeLock wl;

@Override
public IBinder onBind(Intent intent)
return null;


@Override
public void onCreate()
super.onCreate();
try
Thread.setDefaultUncaughtExceptionHandler(
(thread, e)->MyApp.restartApp(this,
"called from ServiceTracker onCreate "
+ "uncaughtException:", e));
catch(SecurityException e)
MyApp.restartApp(this,
"called from ServiceTracker onCreate uncaughtException "
+ "SecurityException", e);
e.printStackTrace();

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if(pm != null)
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TAG");
wl.acquire(10 * 60 * 1000L /*10 minutes*/);



Handler h = new Handler();
h.postDelayed(()->

MyApp.infiniteRunningThread = new Thread(()->
try
Thread.setDefaultUncaughtExceptionHandler(
(thread, e)->MyApp.restartApp(this,
"called from ServiceTracker onCreate "
+ "uncaughtException "
+ "infiniteRunningThread:", e));
catch(SecurityException e)
MyApp.restartApp(this,
"called from ServiceTracker onCreate uncaughtException "
+ "SecurityException "
+ "infiniteRunningThread", e);
e.printStackTrace();


Looper.prepare();
infiniteRunning();
Looper.loop();
);
MyApp.infiniteRunningThread.start();
, 5000);


@Override
public void onDestroy()
wl.release();
MyApp.restartApp(this, "ServiceTracker onDestroy", null);


@SuppressWarnings("deprecation")
@Override
public int onStartCommand(Intent intent, int flags, int startId)
if(intent != null)
try
WakefulBroadcastReceiver.completeWakefulIntent(intent);
catch(Exception e)
e.printStackTrace();


startForeground(SERVICE_ID, getNotificationBuilder().build());
return START_STICKY;



private void infiniteRunning()
//do your stuff here
Handler h = new Handler();
h.postDelayed(this::infiniteRunning, 300000);//5 minutes interval


@SuppressWarnings("deprecation")
private NotificationCompat.Builder getNotificationBuilder()
return new NotificationCompat.Builder(this)
.setContentIntent(MyApp.pendingIntent)
.setContentText(getString(R.string.notification_text))
.setContentTitle(getString(R.string.app_name))
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher))
.setSmallIcon(R.drawable.ic_stat_tracking_service);





Ignore "Deprecation" and stuff, use them when you have no choice.
I think the code is clear and doesn't need to be explained.
It's just about workaround suggestions and solutions.







share|improve this answer












share|improve this answer



share|improve this answer










answered Apr 12 '18 at 12:06









M D PM D P

3,2481 gold badge14 silver badges26 bronze badges




3,2481 gold badge14 silver badges26 bronze badges












  • As far as I can see this restarts the service after 5 to 10 minutes. Is this faster or more reliable than the system wise restart for START_STICKY?

    – leonardkraemer
    Apr 12 '18 at 12:45











  • Also since lolipop the alarm manager can not be abused in this way see stackoverflow.com/questions/29914724/…

    – leonardkraemer
    Apr 12 '18 at 12:59











  • @leoderprofi yes, START_STICKY is just a joke, and no it doesn't restart after interval, I copied from my own app that is being used for over 2 years now, it saves last best location on every interval inside infiniteRunning() method, it only restarts when an error happens. and don't worry about lollipop, I've set minSdkVersion to 14 and targetSdkVersion and compileSdkVersion to 27. and it's working just fine even on android N.

    – M D P
    Apr 12 '18 at 16:44












  • It certainly should be reliable since people are getting paid based on the location history my app reports to server. so yes it's more reliable.

    – M D P
    Apr 12 '18 at 16:52











  • @M D P that is not how minSdkVersion works, it doesn't change how a certain version of android behaves, just on what devices the app runs. Can you elaborate what mechanism restarts the app, when it was closed due to memory pressure and what mechanisms are used to prevent closing?

    – leonardkraemer
    Apr 12 '18 at 16:59

















  • As far as I can see this restarts the service after 5 to 10 minutes. Is this faster or more reliable than the system wise restart for START_STICKY?

    – leonardkraemer
    Apr 12 '18 at 12:45











  • Also since lolipop the alarm manager can not be abused in this way see stackoverflow.com/questions/29914724/…

    – leonardkraemer
    Apr 12 '18 at 12:59











  • @leoderprofi yes, START_STICKY is just a joke, and no it doesn't restart after interval, I copied from my own app that is being used for over 2 years now, it saves last best location on every interval inside infiniteRunning() method, it only restarts when an error happens. and don't worry about lollipop, I've set minSdkVersion to 14 and targetSdkVersion and compileSdkVersion to 27. and it's working just fine even on android N.

    – M D P
    Apr 12 '18 at 16:44












  • It certainly should be reliable since people are getting paid based on the location history my app reports to server. so yes it's more reliable.

    – M D P
    Apr 12 '18 at 16:52











  • @M D P that is not how minSdkVersion works, it doesn't change how a certain version of android behaves, just on what devices the app runs. Can you elaborate what mechanism restarts the app, when it was closed due to memory pressure and what mechanisms are used to prevent closing?

    – leonardkraemer
    Apr 12 '18 at 16:59
















As far as I can see this restarts the service after 5 to 10 minutes. Is this faster or more reliable than the system wise restart for START_STICKY?

– leonardkraemer
Apr 12 '18 at 12:45





As far as I can see this restarts the service after 5 to 10 minutes. Is this faster or more reliable than the system wise restart for START_STICKY?

– leonardkraemer
Apr 12 '18 at 12:45













Also since lolipop the alarm manager can not be abused in this way see stackoverflow.com/questions/29914724/…

– leonardkraemer
Apr 12 '18 at 12:59





Also since lolipop the alarm manager can not be abused in this way see stackoverflow.com/questions/29914724/…

– leonardkraemer
Apr 12 '18 at 12:59













@leoderprofi yes, START_STICKY is just a joke, and no it doesn't restart after interval, I copied from my own app that is being used for over 2 years now, it saves last best location on every interval inside infiniteRunning() method, it only restarts when an error happens. and don't worry about lollipop, I've set minSdkVersion to 14 and targetSdkVersion and compileSdkVersion to 27. and it's working just fine even on android N.

– M D P
Apr 12 '18 at 16:44






@leoderprofi yes, START_STICKY is just a joke, and no it doesn't restart after interval, I copied from my own app that is being used for over 2 years now, it saves last best location on every interval inside infiniteRunning() method, it only restarts when an error happens. and don't worry about lollipop, I've set minSdkVersion to 14 and targetSdkVersion and compileSdkVersion to 27. and it's working just fine even on android N.

– M D P
Apr 12 '18 at 16:44














It certainly should be reliable since people are getting paid based on the location history my app reports to server. so yes it's more reliable.

– M D P
Apr 12 '18 at 16:52





It certainly should be reliable since people are getting paid based on the location history my app reports to server. so yes it's more reliable.

– M D P
Apr 12 '18 at 16:52













@M D P that is not how minSdkVersion works, it doesn't change how a certain version of android behaves, just on what devices the app runs. Can you elaborate what mechanism restarts the app, when it was closed due to memory pressure and what mechanisms are used to prevent closing?

– leonardkraemer
Apr 12 '18 at 16:59





@M D P that is not how minSdkVersion works, it doesn't change how a certain version of android behaves, just on what devices the app runs. Can you elaborate what mechanism restarts the app, when it was closed due to memory pressure and what mechanisms are used to prevent closing?

– leonardkraemer
Apr 12 '18 at 16:59

















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f49637967%2fminimal-android-foreground-service-killed-on-high-end-phone%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript