GRAPPLING WITH ELECTRONICS
  • Blog
  • About
  • Contact

Creating a never ending background service in Android > 7

17/11/2019

37 Comments

 

​Unfortunately this method does not work any more in Android 11 because you cannot restart a foreground process from a background process.I have already found the solution.  I hope to be able to update the blog soon.
However there is a new blog entry for that. Please see this link 



In a previous post, I explained how to create a never ending background service. That solution worked for Android up to Version 7. After that, that method has started misbehaving on an increasing number of vendor specific Android implementations (e.g. Xiaomi) and then finally most of the vendors.
So it is time to give an update.
In order to understand this post, you must understand the previous one as I will build on that code. 
The part that does not work any more in Android > 7 is the sequence Service dying calling the Broadcast receiver which in turn will recreate the server. Since Android 7 (but officially since Lollipop!), any process called by a BroadcastReceiver is run at low priority and hence eventually killed by Android. So the service will end up being killed. Depending on the specific vendor implementation, this may happen in some days (e.g. Samsung) or in some hours (e.g. Xiaomi). 

In order to solve this issue we must create the service in the  BroadcastReceiver in a way that keeps high priority. The suggested way to do it is by use of a JobService. A JobService guarantees that the process will finish. JobServices are cool because they allow also to set a number of conditions attached (e.g. running only if some conditions are true e.g. there is internet connection). We can also require that the job service is restarted if the phone is rebooted.

So the code to make the magic happens is the following. In the Broadcaster Receiver, we will add the following code:

​

    
​As you will see, if the Android version is greater or equal than Lollipop (minimum requirement for JobServices), instead of calling the service creator right away, we go through the JobService. We schedule the job.
Note here two parameters: 
• setOverrideDeadline(0) which is a dummy constraint asking to start immediately (at least one is required)
• setPersisted(true) which requires to restart the Job in case the phone is rebooted. It is really not necessary in our code as the Broadcast will receive a message when the phone is rebooted but good to have
The code for the Job Service is:

    
it will invoke the creation of the service (via the class ProcessMainClass and will register the receiver ready for any request of restart. It will have a method that is called when Android kills the Job Service (it may happen). This method is in charge of requesting to restart itself via the Broadcast Receiver and after a while  afterwards will deregister the receiver (by delaying a bit to avoid unregistering before the receiver receives the message. 

There are some additions here and there to the previous code (and I am afraid I may have changed the names of some classes) but the sense should be clear. 

That is it. It will work on more recent version of Android now. 
Note that there are far more moving parts in the code, so make sure to check the complete code up. It is provided below. 

The code
The code is provide here; licence: MIT, so you can use it for any purpose.
37 Comments
Chizoba
18/11/2019 01:03:43 pm

Thanks for this post. It is really educative.

I have a few questions please:

1. Is it necessary to explicitly register and unregister the broadcast receiver?

2. What benefit does JobService has that makes it work better than Services in this case?

I'd appreciate your response. Thanks!

Reply
Azhar
19/11/2019 11:42:22 am

Notification is removed once you remove the app from recent apps in Oppo phone. Service no longer runs when app is killed.

Reply
Rohitha
27/11/2019 06:59:41 am

me also facing same issue..

Reply
Fabio CIRAVEGNA
27/11/2019 07:46:04 am

If you are running Android >9 you have to allow running in the background under Settings>Apps>Battery (it changes from model to model)

FABIO CIRAVEGNA
4/1/2020 04:24:21 pm

I believe you have to enable restart.
See https://stackoverflow.com/questions/56389829/how-to-get-status-enable-or-disable-for-auto-start-permission-in-android-program

Reply
Marco
10/12/2019 11:33:30 pm

Is it possible with this approach, to restart the application from the service, instead of starting the timer? I have tried without success.Thanks

Reply
abir
13/5/2021 07:01:10 pm

did you found the solution please help me ..

Reply
Kunan
26/12/2019 06:10:38 am

How to stop the service?
I tried many things like cancelAll or cancel(1) or unregister but not working.

Reply
Eric
4/4/2020 02:37:24 pm

I am having the same issue on my Samsung G7 ThinQ Android 9.

At first I thought it was a bug in android studio, but now I am convinced it is an android bug. We jump through hoops to keep the service running and now there is no shutting it down.

I allow my users the option to set a flag in preferences to either run the service in the background or not. You can recreate the bug by commenting out all calls to sendBroadcast in both the onDestroy and onTaskRemoved. In onTaskRemoved be sure to have a call to stopSelf() so that the destructor is called when the user closes the activity.

After the service is destroyed and can launch the profiler in android studio and observe that the process is still running and the memory has not been released. If on your phone you go to App Info ->JobServiceExample->Force Stop then you will see that Android Studio correctly shows that the process was terminated and memory released.

What I have observed is that if you do not create the notification, then the process terminates properly after the user swipes off the activity. But then by not creating a notification, you ruin your chances of having the service run reliably in the background.

The perfect solution would be to programmatically turn on the FLAG_STOP_WITH_TASK at runtime. (You typically do this in your manifest). However I have not found a way to do that. That tells android that the service dies with the activity.

So currently my work around is System.exit(0) or I suppose you could perform an android.os.Process.killProcess(pid) as well. FYI, I also tried the stopJop, cancelAll, notificationManager.cancelAll, etc... with no success.


Reply
Isaac link
29/12/2019 01:58:03 am

When I remove the notification part, the app stop running and it won't work. Any idea of handling that issue?

Reply
FABIO CIRAVEGNA
30/12/2019 06:21:31 pm

why would you remove the notification?

Reply
kfc
11/1/2020 11:19:09 am

Because in real life, app that show notification will have chance to uninstall by user. It is better if we do not show notification.

FABIO CIRAVEGNA
12/1/2020 10:52:39 am

That is the exact reason why Android imposes foreground processes: to let users know that you are running and hence they can stop you if they do not like the idea of you running. You can ask for whitelisting of your process and in that case you do not need a foreground process

Reply
Mohanish
12/2/2020 10:51:58 am

Hello Sir, I liked your idea but as i am trying to make a screen timer I want my application to start foreground after boot up but somehow in devices which have i tried such as samsung and m30 its not working.
It is receiving the BOOT_COMPLETED but not able to create notification and start the service

Reply
Fabio CIRAVEGNA
3/3/2020 07:48:45 am

if you are using a phone like Xiaomi, or a very recent version of Android you will need to set permission for restart in the background

Reply
Coelho
2/3/2020 11:19:29 pm

From what I realized of its implementation, a notification will always appear to the user. Applications like Facebook, instagram, Olx and others manage to keep an active service even without notification. Would you know how this is possible?

Reply
Fabio CIRAVEGNA
3/3/2020 07:47:24 am

Notifications run on a different channel, e.g. the Firebase channel. They are always available

Reply
ali
6/3/2023 01:21:51 am

could you elaborate how

Reply
Deven Bhatt
16/4/2020 12:04:33 pm

Respected Sir,
I came across this page while learning Android programming as I needed such a functionality. Being a novice to Android, I could understand very little but being very much aware of OOPs fundamentals, I could understand the logic. While trying the given code by you, I found that whenever I use "Close All" in my Vivo V7 Plus (Android 8.1), the service disappears and doesn't restart. Can you help me understand this?

Reply
Deven Bhatt
18/4/2020 12:20:00 pm

After going through comments of this thread and previous thread, I found that the author has mentioned at so many places to look at battery optimization and also one user has given a piece of code, I tried my hands on battery and allowed the app "to continue running when the background power consumption is high", the service is surviving any crash.

Reply
Chouaib
20/4/2020 06:22:10 pm

I had tried your method but no effect when I clear the app from recent list , I guess that my Android version or my phone have a problem with keeping service running it kill all process with no but or if please help me,my phone oppo A83 .

Reply
barel
21/4/2020 09:49:15 am

I want to ask you a question,
is it possible to vibrate the phone from my broadcast receiver during incoming call?. I run a service that ensures the phone state it's not vibration mode and although that my vibration not executed.
I think the problem is that the system takes control the vibrate although it not need it. I really need help to done my research

Reply
Aldy
2/5/2020 05:43:23 am

I use this with OneSignal.
When I swipe out the app, still cannot receive the notification.
Please help.

Reply
Hiba
7/7/2020 06:41:40 pm

Hello,
For phone like Xiaomi you mentioned about having auto start permission, but how does this is achieved by DoMobile Applock without auto start permission, it doesn't get killed on clearing recent app when it has accessibility option is granted, i have tried using accessibility service but my accessibility service is also getting killed.

Reply
DS
9/7/2020 10:35:48 pm

Hi Sir,

I am new to Android development and your blog is really helpful. However, I am working on a scenario where I need to send periodic telemetries to cloud server. (every 5 minutes).

Does the approach suits for kind of scenario I mentioned, I am wondering if it impacts performance of device as the service involves accessing network.

Appreciate your time and help

Thanks

Reply
Shubham Raj
11/7/2020 03:06:32 pm

2020-07-11 20:34:54.069 20423-20423/? E/.calllogtracke: Unknown bits set in runtime_flags: 0x8000
2020-07-11 20:34:54.280 20423-20423/com.codewithshubh.calllogtracker I/Perf: Connecting to perf service.
2020-07-11 20:34:54.297 20423-20454/com.codewithshubh.calllogtracker E/Perf: Fail to get file list com.codewithshubh.calllogtracker
2020-07-11 20:34:54.298 20423-20454/com.codewithshubh.calllogtracker E/Perf: getFolderSize() : Exception_1 = java.lang.NullPointerException: Attempt to get length of null array


I am getting this error.

Reply
ChrTopf
28/7/2020 01:52:19 pm

Does your approach still work on Android 10? Cause there are some restrictions for the BroadcastReceiver now:
https://developer.android.com/guide/components/broadcast-exceptions

Reply
FABIO CIRAVEGNA
20/3/2022 08:10:50 pm

No it is not possible to start a foreground service form a background service. I have found the solution but I need to find time to write the blogpost

Reply
Saurabh
21/3/2022 05:22:54 pm

It would be really helpful if you can provide a solution for Android10+ services. Struggling a lot with this.

gjee
10/11/2020 11:29:05 am

On Androind 9, service is not restarting again.

ActivityManager: Process uk.ac.shef.oak.jobserviceexample (pid 18586) has died: prcp FGS

W/ActivityManager: app.persistent false app.isolated false app.removed false app ProcessRecord{d0ce793 18586:uk.ac.shef.oak.jobserviceexample/u0a288

I/ActivityManager: Start proc 15097:uk.ac.shef.oak.jobserviceexample/u0a288 for service uk.ac.shef.oak.jobserviceexample/.Service

W/ActivityManager: Stopping service due to app idle: u0a288 -4h37m8s471ms uk.ac.shef.oak.jobserviceexample/.Service

I/ActivityManager: Killing 15097:uk.ac.shef.oak.jobserviceexample/u0a288 (adj 906): empty #10

W/ActivityManager: app.persistent false app.isolated false app.removed false app ProcessRecord{522cf81 15097:uk.ac.shef.oak.jobserviceexample/u0a288}

Reply
João Pereira
13/7/2021 02:14:47 am

Same here. It worked fine with api 23, but i tested it on api 29 and it didn't work. Did you find any alternatives?

Reply
FABIO CIRAVEGNA
20/3/2022 08:09:51 pm

With Android 11 the issue is that you cannot restart a foreground process from a background process. The programme needs rewriting and simplifying. I have not had much time recently

Luís Alves
24/11/2020 09:06:39 am

Outstanding!

First run, no changes, total success! On Q(10) and Nougat(7.1.1), both emulators, and in my personal Samsung J3 with Lollipop(5.1.1) also. I could barely believe. I spent a lot of time researching and trying.

I took the liberty of use the old version's "isMyServiceRunning(class)" and worked like a charm. This way it just continues the count with the beauty of non-stopping. OnResume of MainActivity was restarting the already running service. It all got very robust and tough.

Thank you, very much, Sir!

P.S.
FYI, I used RedHat's Openjdk 11.0.9.1 with Gradle 6.7.1 on IntelliJ IDEA, with updated dependencies. Everything working nicelly.

Reply
Hassen Elmir
16/12/2020 10:23:49 pm

Hey, I have a problem Android studio cannot resolve symbol ProcessMainClass, What's the problem with it ? do i need to import something ?

Reply
Mustafa Sungur Polater
11/2/2021 08:18:59 pm

I have defined a button to stop the service, but the service is not stopped. (I did minSdkVersion = 21)

public void StopBtnClick(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
JobService.stopJob(getApplicationContext());
}
else {
JobService bck = new JobService();
bck.stopJob(getApplicationContext());
}
}

Reply
john
26/8/2021 11:38:21 am

anybody know what restartSensorServiceReceiver is? could not be found, i try to do it in xamarin android plz help

Reply
gsb
24/7/2023 07:49:23 pm

Crash: Tried to schedule job for non-existent component: ComponentInfo{com.myapp/android.app.job.JobService}

Any clues???

Reply

Your comment will be posted after it is approved.


Leave a Reply.

    Author

    After over 20 years in the UK at the University of Sheffield, I have moved to Università di Torino in Italy as (Full) Professor of Pervasive Computing.  
    My research concerns large scale data acquisition and analysis with a particular focus on mobile applications. I teach mobile computing and advanced Web technologies. 
    These pages are dedicated to random passions like electronics (e.g. using Raspberry Pi and Arduino) and to mobile development. Some of these experiments I do for work, others just for fun. 

    Archives

    October 2022
    May 2022
    November 2019
    January 2016
    April 2014
    January 2014
    December 2013

    Categories

    All

    RSS Feed

Powered by Create your own unique website with customizable templates.