In Android, services are a type of component that runs in the background and performs long-running tasks without requiring any user interaction. They are used for operations that should continue even when the user switches to a different application or turns off the screen. Services can also define a remote interface using AIDL and provide some functionality to other apps. However, unlike system services, which are part of the OS and are always running, application services are started and stopped on demand.
Services can be used for a variety of tasks, such as playing music, downloading files, or monitoring sensors. They can also be used to perform tasks that require network access, such as sending or receiving data from a server.
Type of Services
Background Service
Background services are services that run in the background without any user interaction. They are typically used for tasks that are less important to the user, like syncing data with a server or updating the app's database. Unlike foreground services, background services do not require a notification to be shown to the user.
Pros
Don't need to show a notification.
They consume fewer system resources (like battery and memory) than foreground services, which can help improve device performance.
They can be used to perform tasks that are not time-sensitive, like uploading a backup of user data to a server.
Can have multiple background services running per app.
Cons
Prone to be killed by the system when low on memory or app goes to background.
Strict limits on CPU and network usage in recent Android versions to prevent battery drain.
Foreground Service
Foreground services are ongoing tasks that are noticeable to the user, often through a notification. For example, a music player app playing music or a navigation app providing directions are examples of foreground services. Here are some pros and cons of foreground services:
Pros
Foreground services are visible to the user through notifications, which provides a sense of trust and transparency.
Guaranteed to run by the system even when device is low on memory
Not killed when app goes to background
Cons
Persistent notifications can annoy users if they are not necessary or relevant to the user's needs.
Foreground services might consume more battery as they are less likely to be killed by the system.
Only one foreground service can run per app
Limitations Background Service on Various Android Versions
On Android 6.0 (Marshmallow), Android introduced Doze mode, which imposes restrictions on background services to save battery.
On Android 8 (Oreo), background services can only run for a maximum of 5 minutes at a time. After that, the system will kill the service.
On Android 8 (Oreo), Background services are very prone to being killed when the device is under memory pressure.
On Android 9 (Pie), Background services can only run for a maximum of 30 seconds at a time. After 30 seconds, the system kills the service.
On Android 10 (Q), Background services are heavily rate-limited. They can only run for a few seconds at a time before being killed.
Apps cannot continually restart background services. Frequent restarts will be blocked.
Most use cases for background services should move to using
WorkManager
or JobScheduler
which have better battery optimization.Limitations Background Service on Various Android Versions
On Android 8 (Oreo), An app can only have one foreground service running at a time. If you start a new foreground service, the previous one is promoted to a background service.
On Android 9 (Pie), Foreground services must show a notification to the user. The notification cannot be dismissed by the user.
On Android 9 (Pie), The foreground service notification must be associated with an icon in the status bar. So the app must have an icon in the launcher.
On Android 10 (Q), The foreground service notification title must clearly indicate that the foreground service is running. For example, "Music playing" or "File downloading".
On Android 10 (Q), The notification must have a "Stop" or "Cancel" button to allow the user to stop the foreground service.
On Android 10 (Q), The notification must have an "Ongoing" metadata field set to true. This displays an icon in the status bar indicating an ongoing notification.
Use Cases
Downloading large files: Foreground services can be used for downloading large files, such as app updates or media files, while providing progress updates through notifications.
Playing music or podcasts: Foreground services are ideal for media playback, as they allow the media to continue playing even when the app is not in focus.
Navigation apps: Foreground services can provide real-time navigation instructions and updates.
Data synchronization: Background services can be used to sync data with a server, such as fetching new emails or updating a database.
Scheduled tasks: Android's
JobScheduler
or WorkManager
can be used to schedule tasks that need to be executed periodically, such as checking for new data or running maintenance tasks.Important Methods in Service
onCreate()
: This method is called when the service is first created. You can use it to perform any setup or initialization tasks required by the service, such as initializing variables or setting up listeners.onStartCommand()
: This method is called every time the service is started using startService()
. It allows you to specify what should happen when the service is started, such as performing a specific task or starting a background thread to handle ongoing work.onBind()
: This method is used when the service needs to communicate with an activity or another component in the app. It returns an IBinder object that can be used to communicate with the service.onDestroy()
: This method is called when the service is about to be destroyed. You can use it to perform any cleanup tasks required by the service, such as releasing resources or stopping any ongoing tasks.onTaskRemoved()
: This method is called when the user removes the app from the task list. You can use it to perform any cleanup tasks required by the service before it is destroyed.onLowMemory()
: This method is called when the system is running low on memory. You can use it to release any resources that are no longer needed by the service.What is Binding?
In simple terms, binding is a way for one part of an Android app, like an activity, to communicate with and control another part of the app, like a service. When you bind an activity to a service, the two parts of the app establish a connection that allows them to exchange information and work together.
Some details about onBind():
It should return an IBinder which defines the interface for interacting with the service. Typically this is an instance of a class that extends Binder.
Multiple clients can bind to the same service at once, and the service must handle them concurrently.
While a client is bound to a service, the service will continue running and won't be destroyed. Once all clients have unbound, the service will be destroyed.
Binders allow synchronous communication between the client and service. The client can call methods directly on the binder and get return values immediately.
A common use case is for an Activity to bind to a Service to get data from a database or perform other operations. The Activity can call methods on the Binder to get results and update the UI.
Code Example:
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private MyBinder mBinder = new MyBinder();
public class MyBinder extends Binder {
public String getString() {
return "Hello from the service!";
}
}
Is Binding Same With IPC(Inter Process Communication)?
Binding is not the same as IPC, but it is a way of using IPC in Android. IPC stands for inter-process communication, which is a general term for any method that allows processes to communicate with each other. IPC can be done in different ways, such as using sockets, pipes, shared memory, message queues, etc.
Binding is a specific way of doing IPC in Android, using the Binder mechanism. Binder is a low-level IPC mechanism that allows processes to communicate with each other using shared memory and message passing. Binder provides fast and secure communication between processes by using references, handles, transactions, and parcels.
How Binding work? Is android use TCP/IP for Binding Process?
Binding is a way of connecting an application component (such as an activity) to a service, so that the component can interact with the service, send requests, receive responses, and perform inter-process communication (IPC). Binding also lets the service know that there is an active client that it should not stop itself.
To bind to a service, the client app must call
bindService()
with an intent that identifies the service to bind to. The service must implement the onBind()
method to return an IBinder
object that defines the interface for communication with the service. The binding is asynchronous, and bindService()
returns immediately without returning the IBinder
to the client.The Android system then calls the
onServiceConnected()
method on the ServiceConnection
object that the client app provides. This method receives the IBinder
object from the service and can use it to interact with the service. The client app can also call unbindService()
to disconnect from the service.Android does not use TCP/IP to communicate between a client app and a bound service. Instead, it uses Binder, which is a low-level IPC mechanism that allows processes to communicate with each other. Binder provides fast and secure communication between processes by using shared memory and message passing.
Real World Example
A good real world example of using the
onBind()
method is for an Activity to bind to a MusicService
to control music playback.Here is a basic example:
MusicService.java
package lab.seczone64.musicplayerexample
import android.app.Service
import android.content.Intent
import android.os.Binder
import android.os.IBinder
import android.util.Log
class MusicService : Service() {
override fun onBind(intent: Intent): IBinder {
return mBinder
}
private val mBinder: IBinder = MusicBinder()
inner class MusicBinder: Binder() {
fun getService() : MusicService {
return this@MusicService
}
}
fun startMusic(){
Log.v(this::class.java.toString(), "Music Has Been Started.")
}
fun pauseMusic(){
Log.v(this::class.java.toString(), "Music Has Been Paused.")
}
fun stopMusic(){
Log.v(this::class.java.toString(), "Music Has Been Stopped")
}
}
MainActivity.java
package lab.seczone64.musicplayerexample
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private var mBound = false
lateinit var mService: MusicService
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val startBtn: Button = findViewById(R.id.start_btn)
val pauseBtn: Button = findViewById(R.id.pause_btn)
val stopBtn: Button = findViewById(R.id.stop_btn)
startBtn.setOnClickListener { if (mBound) mService.startMusic() }
pauseBtn.setOnClickListener { if(mBound) mService.pauseMusic() }
stopBtn.setOnClickListener { if(mBound) mService.stopMusic() }
}
override fun onStart() {
super.onStart()
val intent = Intent(this, MusicService::class.java )
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
}
private val serviceConnection: ServiceConnection = object : ServiceConnection{
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
Log.v("MainActivity", "Service Bounded")
val binder = service as MusicService.MusicBinder
mService = binder.getService()
mBound = true
}
override fun onServiceDisconnected(name: ComponentName?) {
Log.v("MainActivity", "Service Unbounded")
mBound = false
}
}
}
In this example:
The Activity binds to the MusicService when it starts
In onServiceConnected(), it gets an instance of the MusicBinder from the service
It can then call methods on the MusicBinder like startMusic(), pauseMusic() etc to control playback
This allows the Activity to directly interact with and control the Service.