(make sure to understand this code before going to the next blog post, though, as that one builds on this one)
(please note: confusingly, Android has added two ways of working for services: background proper that is becoming more and more difficult to use and Foreground processing where the user is aware of the background process. See this link for more details). In the remainder I will use the term background to cover both cases.
You use a background service to provide continuous data collection or processing while the app is no longer in the foreground (i.e. it has been minimised and another app is displayed) or even when the app has been closed by the user - or killed by Android (this happens when the operating system is running out of resources, e.g. memory).
A typical example of an app that requires a never ending background service is a pedometer that tracks your steps 24/7. No matter if the app is not in the foreground, you still want to count your steps.
This is how to create the ever ending background service.
There are three parts in the code: (i) an Activity (the foreground app), (ii) a Service and (iii) a BroadcastReceiver which will receive a signal when someone or something kills the service; its role is to restart the service.
First of all you will need an app (an Activity). We will create a very simple app that does not display anything (just the string "Hello World"). This is pretty straightforward. AndroidStudio will do it for you.
Here is the Manifest
<intent-filter> <action android:name="uk.ac.shef.oak.ActivityRecognition.RestartSensor"/> </intent-filter>
This is no longer possible in Android. Receivers must be declared explicitly in the receiver Java code.
The app is very simple: it launches the service if not already active and will stop the service when killed (so that the service is restarted immediately after the app dies.
Here is the service:
In this case, the service sends a message to the BroadcastReceiver which will restart the service after the service stop (it is an asynchronous call so it will not be affected by the death of the service.
The Broadcast receiver is defined in this way:
Now if you run the app when the phone is connected to AndroidStudio, you will see the counting printed out in the Log. When the app is killed, the service will be stopped, the broadcast receiver will print out
Service Stops! Oooooooooooooppppssssss!!!!
and the service will start again (by resetting the counter to zero because it is a new service!).
Download the code
Some Additional Points and FAQs
You can but in that case the service will not be restarted if your app is in the background and Android decides to kill your service because it needs resources. I.e. your service would not be guaranteed to work indefinitely
What is I do not want the counter to restart when the process is killed?
Yes this is the usual case. Well you cannot directly. The only way is to save the status of the service and to reload it when the service is started. You will do this by using the following code:
try {
SharedPreferences prefs= getSharedPreferences("uk.ac.shef.oak.ServiceRunning", MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt("counter", counter);
editor.apply();
//Long.i("MoveMore", "Saving readings to preferences");
} catch (NullPointerException e) {
Log.e(TAG, "error saving: are you testing?" +e.getMessage());
ServerOperations.database.addError(e.getMessage());
}
in the inDestroy of the service and the following code in the onStartCommand of the service:
SharedPreferences prefs= ctx.getSharedPreferences("uk.ac.shef.oak.ServiceRunning", ctx.MODE_PRIVATE);
boolean found=prefs.getInt("counter", 0);
This should save the value of counter. Note that this is a general method: should you have a very large data structure, you can Gson it and save it as String.
What is the Timer in the SensorService class?
A timer wakes up every n seconds to perform a tasks. In this case it just increments counter and prints out its value.