I want to study this pdf file in a 30 minutes. I know almost nothing about its concept and I want you to:
1. create an index from all the contents it provides 2. Give me a comprehensive, but casual description about what it contains in a way that I understand the main points of this pdf file, (If it could make a sense you may gimme an example in which contains a scenario related to the main point of this pdf)


© G. Malnati, C. Barberis, 2012-23
Android services
2022-23© G. Malnati, C. Barberis, 2012-23 2
Introduction
• A service is an application component that performs operations
in background
o It does not provide any user interface
• A component can connect to a service and interact with it
o Even if it belongs to another process
• Two types of services:
o Started services
o Bound services© G. Malnati, C. Barberis, 2012-23 3
Started services
• A service is “started” when an application component, such as
an activity starts it by calling the startService(…) method
o Once started, a service can run indefinitely in background (almost)
o Even if the component that started it has been destroyed, provided it
shows its presence in the status bar (ForegroundService)
o Generally, a “started” service runs a single operation and does not return
any result to the calling component
▪ For example, a file can be downloaded from the network and saved in the device file system
o When the task ends, the service can stop itself© G. Malnati, C. Barberis, 2012-23 4
Bound services
• A service is called “bound” when an application component
invokes it using the bindService(…) method
o This offers a client-server interface
o It allows the invoking component to interact with the service, sending
requests, obtaining results, supported by an inter-process communication
(IPC) mechanism
o The lifecycle of a bound service is tied to the component to which it is
connected to
o Several components can be associated to the same service at the same
time, but when all the associated component are disassociated from it, the
service is destroyed© G. Malnati, C. Barberis, 2012-23 5
Using services
• Any application component can use a service
o It can be declared private in the manifest file, to prevent access from other
applications
• A service runs in the main thread of the hosting process
o By default, it does not create a thread of its own
o Nor it runs in a separated process
o If the service performs expensive computational operations, they should
be carried out in a separate thread© G. Malnati, C. Barberis, 2012-23 6
The android.app.Service class
• It is the base class from which all service implementations derive
• It requires some methods to be overridden
o To manage key life cycle aspects
o To supply a mechanism be able to associate components
• onStartCommand(…)
o The system calls this method whenever another component, such as an
activity, request the activation of the service, via the startService(…)
method
o Once this method is executed, the service is started and can run in
background indefinitely
o To stop it, it is required to call stopSelf(…) or stopService(…), passing the
suitable intent© G. Malnati, C. Barberis, 2012-23 7
The android.app.Service class
• onBind(…)
o The system calls this method when an other component wants to associate
with the service, invoking bindService(…)
o This method should return an object implementing the IBinder interface or
null
▪ In the former case, the returned object will be marshalled to the invoker, offering a way to
interact with the service
▪ In the latter case, no interaction will be allowed© G. Malnati, C. Barberis, 2012-23 8
The android.app.Service class
• onCreate(…)
o The system calls this method when the service object has just been created
o Call happens before either onStartCommand(…) or onBind(…)
o If the service has already been started, this method is not called© G. Malnati, C. Barberis, 2012-23 9
The android.app.Service class
• Method onDestroy(…)
o The system calls this method when the service is no more used and it is to
be destroyed
o Services should implement this method in order to release resources
▪ Thread, registered listener, receiver, …
o It is the last call received by the service© G. Malnati, C. Barberis, 2012-23 10
Declaring a service in the manifest file
• It is necessary to declare all services in the application manifest
file
o Add an element of type <service> as a child of the <application> one
<manifest ... >
...
<application ... >
<service android:name=".ExampleService" />
...
</application>
</manifest>
• Attribute android:name is mandatory
• It can define other properties
o Service permissions, …© G. Malnati, C. Barberis, 2012-23
Services lifecycle
11© G. Malnati, C. Barberis, 2012-23
Started service lifecycle
12
MyActivity
startService(intent)
MyService
onCreate()
onStartCommand(intent) thread{ … }
stopSelf()
onDestroy() x
constructor© G. Malnati, C. Barberis, 2012-23 13
Extending the Service class
• A service may be implemented extending the Service class
• In the onCreate(…) method, is it possible to create and start an
HandlerThread to manage requests
o The constructor of this object takes a Looper as input
o This is used to manage messages queued inside the handler
• In the method onStartCommand(…)
o For each incoming request, a message is sent to the handler
o The service ID is forwarded, so that it can be used when the service will
have to be stopped© G. Malnati, C. Barberis, 2012-23 14
Extending the Service class
• The onStartCommand(…) method must return an integer, that
indicates how the system will manage the service, in the case it
had to stop it
o START_NOT_STICKY: the service is not re-created, unless there are pending
Intent requests
▪ It is used when the service is no longer necessary
o START_STICKY: the service is re-created, but the last intent is not returned.
The system calls onStartCommand(…) passing a null intent, unless there
are pending Intent requests
▪ It is suitable for media player that are not executing any commands, but they run
indefinitely waiting for a task
o START_REDELIVER_INTENT: the service is created and the last Intent
returned
▪ It is suitable for services that are executing a task that must be recovered immediately, for
example a file download© G. Malnati, C. Barberis, 2012-23
Extending the Service class
15
class HelloService : Service {
private lateinit var mServiceLooper:Looper;
private lateinit var mServiceHandler:ServiceHandler;
// Handler receives messages from thread
class ServiceHandler(looper:Looper) : Handler(looper) {
override fun handleMessage(msg: Message) {
// Implementation
when(msg.what) {
1 -> { /* do somenthing */ }
2 -> { /* do something else */ }
else -> { /* … */}
}
// Stops the process using the reqeustID,
// In this way it does not stop the service
// in the middle of the operation of another job
stopSelf(msg.arg1);
}
}© G. Malnati, C. Barberis, 2012-23
Extending the Service class
16
override fun onCreate() {
// Create a thread to service request.
// The thread has background priority
// so operations that require a lot of CPU
// do not affect the main thread
val thread = HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = ServiceHandler(mServiceLooper);
}© G. Malnati, C. Barberis, 2012-23
Extending the Service class
17
override fun onStartCommand(Intent intent,
int flags, int startId): Int {
Toast.makeText(this, "processing request starting",
Toast.LENGTH_SHORT).show();
// For each request received,
// send a message to the looper
// together with a start ID,
// to find when to terminate it
val msg = mServiceHandler.obtainMessage(
intent.getIntExtra("cmd",0));
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
// should the service be stopped, it will be resumed
return START_STICKY;
}
override fun onBind(intent: Intent): IBinder? { return null;}
}© G. Malnati, C. Barberis, 2012-23 18
Background execution limitations
• Starting with Android 8.0 (API level 26) limitations have been
imposed on background execution
o A distinction is made between foreground services and background ones
• A foreground service performs some operation that is noticeable
to the user
o By displaying a Notification on the task bar
• When a background service is running the user may not notice
its presence
o Thus this mode is only allowed in limited situations© G. Malnati, C. Barberis, 2012-23 19
Foreground apps
• An app is considered to be in the foreground if any of the
following is true:
o It has a visible activity, even if it is paused
o It has a foreground service
o Another foreground app is connected to it by binding to one of its services
or by making use of one of its content providers
• In all other cases the app is considered to be in the background© G. Malnati, C. Barberis, 2012-23 20
Background apps
• When in background, an app has a window of several minutes in
which it is still allowed to create and use services
o When the window expires, the app becomes idle
o All its background services are (cleanly) stopped by the system
• A background app can renew its run window if it handles a task
that is visible to the user
o An incoming Firebase Cloud Messaging or a SMS message
o Executing a PendingIntent from a notification
o Starting a VPN service© G. Malnati, C. Barberis, 2012-23 21
Handling background tasks
• The Jetpack WorkManager API offers a simple way to schedule
deferrable, asynchronous tasks
o That are guaranteed to run reliably, even if the requesting app or device
restarts
o But the task can be run later on, when the system deems reasonable to do
it
dependencies {
implementation "androidx.work:work-runtime-ktx:2.7.1"
}© G. Malnati, C. Barberis, 2012-23 22
Handling background tasks
• To use the WorkManager API, the following tasks need to be
performed
o Create a background task, by extending the androidx.work.Worker class
o Configure how and when it should be run, using a work request Builder
instance
o Hand it off to the system, via the WorkManager enqueue(…) method
• WorkManager implementations will override method doWork()
o This will return a Result object, informing the WorkManager service
whether the work succeded and, and in case of failure, whether is should
be retried or not© G. Malnati, C. Barberis, 2012-23 23
Handling background tasks
class MyWorker(appCtx: context, params: WorkerParams):
Worker(appCtx, params) {
override fun doWork(): Result {
// Perform here the job
return Result.success() //or .failure() or .retry()
}
}
val constraints = Constraints.Builder()
.setRequiresDeviceIdle(true)
.build()
val myRequest = OneTimeWorkRequestBuilder<MyWorker>()
.setConstraints(constraints)
.build()
WorkManager.getInstance(context).enqueue( myRequest )© G. Malnati, C. Barberis, 2012-23 24
Types of persistent work
• WorkManager handles three types of persistent work:
o Immediate: Tasks that must begin immediately and complete soon;
submitted through a OneTimeworkRequest instance, may be expedited
o Long Running: Tasks which might run for longer, potentially longer than 10
minutes; submitted through any WorkRequest instance
o Deferrable: Scheduled tasks that start at a later time and can run
periodically; submitted through a PeriodicWorkRequest instance© G. Malnati, C. Barberis, 2012-23 25
Types of persistent work© G. Malnati, C. Barberis, 2012-23
Bound service lifecycle
26
MyActivity
bindService(intent,
connection,
flag)
MyService
onCreate()
onBind(intent)
onUnbind()
constructor
IBind
er
constructor Connection
onServiceConnected(…) IBind
er
unbindService(connection)
onDestroy()© G. Malnati, C. Barberis, 2012-23 27
Bound services
• A bound service operates as a server in a client-server interface
o It allows activities (or other components) to bind to itself in order to send
requests and receive responses, possibly across process boundaries
• A bound service implements the onBind() method returning an
object implementing the IBinder interface
o This is a sort of “remote control” that let the client request operations to
the service© G. Malnati, C. Barberis, 2012-23 28
The onBind() method
• This method is responsible to create and return a IBinder object
o The OS guarantees that this method is invoked only once, the first time
that a client component invokes bindService(…)
o The returned object is cached by the OS, and returned to all other clients
invoking bindService, as long as the service is running
• When the last client disconnects from the IBinder object, the
service is destroyed© G. Malnati, C. Barberis, 2012-23 29
Implementing IBinder
• This is the API that let clients access the functionality provided
by the service
o It need to be carefully designed
• There exist three possible implementations
o Extending the Binder class – simple, it works only when clients are in the
same process as the service
o Using a Messenger – medium complexity, requires the creation of a
HandlerThread that process messages
o Creating a remote component via AIDL – high complexity, it requires to
properly deal with multithreading issues© G. Malnati, C. Barberis, 2012-23 30
Extending the Binder class
• Simple way to let other components to directly access public
methods of the service
o It is common to provide a getService() method that simply returns the
service instance to the client
o This lets the client directly invoke methods of the service class© G. Malnati, C. Barberis, 2012-23
Extending the Binder class
31
class BoundService : Service() {
private val myBinder = MyLocalBinder(this);
override fun onBind(intent: Intent?): IBinder {
return myBinder;
}
fun getSomeServiceFunctionality(someParam:Int): String {
//perform here the request job
return “SomeServiceResult”;
}
fun getSomeOtherFunctionality(whatever: String): Int {
//perform here the request job
return 1;
}
class MyLocalBinder(val service:BoundService) : Binder()
}© G. Malnati, C. Barberis, 2012-23 32
Connecting to a bound service
• A component can connect to a bound service by invoking the
ctx.bindService(…) method
o Providing a ServiceConnection implementation that receives notifications
about the binding lifecycle
o When binding is created, the forwarded IBinder argument can be used to
transparently access the service functionalities© G. Malnati, C. Barberis, 2012-23
Example activity
33
class MainActivity : AppCompatActivity() {
private var svc: BoundService.MyLocalBinder? = null
val conn = object:ServiceConnection {
override fun onServiceConnected(name: ComponentName?,
service: IBinder?) {
svc = service as BoundService.MyLocalBinder
//Notify here that service is BOUND
}
override fun onServiceDisconnected(name: ComponentName?) {
svc = null
//Notify here that service is now unbound
}
}
private fun bind():Boolean {
val intent = Intent(this, BoundService::class.java)
return bindService(intent, conn, Context.BIND_AUTO_CREATE)
}
}