I've read just about every Stackoverflow answer that exists on this topic, but none of them worked.
Goal: Keep my service running 24/7, all the time
Problem: Whenever my device is on sleep mode for an hour or more, the service is killed
What I've tried to fix it:
Returning
START_STICKY
fromonStartCommand()
and usingstartForeground()
public int onStartCommand(Intent intent, int flags, int startId) { notification = makeStickyNotification(); //I've simplified the irrelevant code, obviously this would be a real notification I build startForeground(1234, notification); return START_STICKY; }
This works fine, and it even restarts my service whenever the device is low on memory, but it is not enough to fix the problem that occurs when my device goes to sleep for a while.
Using Alarm Manager in
onCreate()
of my Activity and inonStartCommand()
of my Service to call a Broadcast Receiver that calls my serviceIntent ll24 = new Intent(this, AlarmReceiver.class); PendingIntent recurringLl24 = PendingIntent.getBroadcast(this, 0, ll24, PendingIntent.FLAG_CANCEL_CURRENT); AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE); alarms.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000*60, recurringLl24); // Every minute
This helps keep my service active, but again, doesn't solve my problem
Using Schedule Task Executor to keep it alive
if (scheduleTaskExecutor == null) { scheduleTaskExecutor = Executors.newScheduledThreadPool(1); scheduleTaskExecutor.scheduleAtFixedRate(new mainTask(), 0, 1, TimeUnit.SECONDS); } ... class mainTask implements Runnable { public void run() { // 1 Second Timer } }
This also just keeps the service active but doesn't keep it alive after a long sleep.
Separate task Manifest
android:launchMode="singleTop"
This did nothing
How can I (1) test this issue without having to put my phone to sleep and check every hour and (2) keep my service running despite the device going to sleep?
Your service was killed by Doze or Standby mode of Android. That was introduced in Android 6.0 (API level 23).
So system ignored your
Alarm Clocks, Scheduler
, etc.In Android Oreo release Android defined limits to background services.
Still if app need to run its service always, then we can create foreground service.
So create a foreground service. In which you will put a notification for user while your service is running. See this answer (There are many others)
Now what if you don't want a notification for your service. A solution is for that.
You can create periodic task with Alarm Manager, Job Scheduler, Evernote-Jobs or Work Manager.
I created forever running service with Work-Manager, that is working perfectly.
Starting from SDK 26 a Service should have its relative "MainActivity" in foreground OR this Service should be started as in foreground using "startForegroundService()". The "startForeground()" doesn't work as expected if the target SDK is 26+ but need the other way I just explained.
After this you can use following code to Kill and restart the App from scratch (yes, even the Service is killed in this way):
The murder mystery has been solved, and I know what killed my service. Here's what I did:
startsticky
,startforeground
,alarmmanager
,scheduleTaskExecutor
, and evenwakelock
were unable to save my service, I realized the murderer couldn't be the Android system, because I had taken every measure possible to prevent the system from killing my service and it still would get killed.I realized I needed to look for another suspect, since the service wasn't dying because of the system. For that, I had to run an investigation. I ran the following command:
adb shell dumpsys activity processes > tmp.txt
This would give me a detailed log of all the processes running and their system priorities. Essentially,
tmp.txt
would be the detective in this murder mystery.I looked through the file with lots of detail. It looked like my service was prioritized properly by the system:
Proc #31: adj=prcp /FS trm= 0 2205:servicename.service/uID (fg-service)
The above line indicates the exact priority of a process running on the Android device.
adj=prcp
means the service is a visible foreground service.At this point, I realized that my service must be encountering some error a couple hours after running, so I let it run and die. After it died, I produced a
dumpsys
again to examine the error:tmp.txt
file. Excited, I scrolled to the bottom of thedumpsys
and solved the mystery!The stack trace that caused the killing of my service was displayed right there! Essentially, a variable that would check for the foreground app being used would become null after a few hours of inactivity, which would cause an exception, and kill the service!
Key Takeaways: If your service is getting killed, and you've done everything you can to make sure that it shouldn't be killed, perform a
dumpsys
and examine the nitty gritty of your device's activity process. I guarantee you will find the issue that way.I still would like to have the bounty awarded to @Khemraj since his answer could be a great solution for someone who hasn't started their service properly. However, I am accepting this answer since it is the solution that actually fixed the issue.
Doze mode kills services to save battery. Only valid solution for you is to create a foreground service in Oreo and above. https://developer.android.com/about/versions/oreo/background
onDestroy() is really unreliable and won't be called often that you want. Same for onLowMemory() callbacks. There is no way to take a guaranteed callback if android decides to kill your process or if user decides to Force Stop your app.
That's normal that than user device go to sleep mode, your service dies. Read about wakelocks. Try something like that in your service: In manifest:
In service:
But it's rly tricky for user and totally anti-pattern in android world, cuz of battery consumption.
Another option is to trigger service something like every 10 mins. Make pending intent on WakefulBroadcastReceiver(where you can start your service) and schedule it with alarm manager with flag RTC_WAKE_UP