Services

Services

A service is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC).

A service can essentially take two forms: Started and Bound.

Started:

A service is "started" when an application component (such as an activity) it by calling startService(). Once started, a service can run in the background indefinitely, even if the component that started it is destroyed. Usually, a started service performs a single operation and does not return a result to the caller. When the operation is done, the service should stop itself.

Bound:

A service is "bound" when an application component binds to it by calling bindService(). A bound service offers a client-service interface that allows components to interact with the service, send requests, get results, and even do so across processes with interprocess communication (IPC). A bound service runs only as long as another application component is bound to it. Multiple components can bind to the service at once, but when all of them unbind, the service is destroyed.

Our service can work both ways --- it can be started (to run indefinitely) and also allow binding. It's simply of whether we implement a couple callback methods: onStartCommand() to allow components to start it and onBind() to allow binding.

A service runs in the main thread of its hosting process --- the service dose not create its own thread and does not run in a separate process (unless we specify otherwise). This means that, if our service is going to do any CPU intensive work or blocking operation, we should create a new thread within the service to do that work. By using a separate thread, we will reduce the risk of Application Not Responding (ANR) errors and the application's main thread can remain dedicated to user interaction with our activities.

The Basics

To create a service, we must create a subclass of Service (or one of its existing subclasses).The most important callback methods we should override are:

onStartCommand():

The system calls this method when another component requests that the service be started, by calling startService(). Once this method executes, the service is started and can run in the background indefinitely. If we implement this, it is our responsibility to stop the service when its work is done, by calling stopSelf() or stopService(). (If we only want to provide binding, we don't need to implement this method.)

onBind()

The system calls this method when another component wants to bind with the service, by calling bindService(). In our implementation of this method, we must provide an interface that clients use to communicate with the service, by returning an IBinder. (We must always implements this method, but if we don't want to allow binding, then we should return null.)

onCreate() 

The system calls this method when the service is first created, to perform one-time setup procedures (before it calls either onStartCommand() or onBind()). If the service is already running, this method is not called.

onDestroy()

The system calls this method when the service is no longer used and is being destroyed.

If a component starts the service by calling startService() (which results in a call to onStartCommand()), then the service remains running until it stops itself with stopSelf() or another component stops it by calling stopService().

If a component calls bindService() to create the service (and onStartCommand() is not called), then the service runs only as long as the component is bound to it. Once the service is unbound from all clients, the system destroys it.

The Android system will force-stop a service only when memory is low and it must recover system resources for the activity that has user focus. If the service is bound to an activity that has user focus, then it's less likely to be killed, and if the service is declared to run in the foreground, then it will almost never be killed. Otherwise, if the service was started and is long-running, then the system will lower its position in the list of background tasks over time and the service will become highly susceptible to killing --- if our service is started, then we must design it to gracefully handle restarts by the system. If the system kills our service, it restarts it as soon as resources become available again (though this also depends on the value we return from onStartCommand()).

Declaring a service in the manifest

Like activities (and other components), we must declare all services in our application's manifest file.

To ensure our app is secure, always use an explicit intent when starting or binding our service and do not declare intent filters for the service. Additionally, we can ensure that our service is available to only our app by including the android:exported attribute and setting it to "false".

Creating a Started Service

A started service is one that another component starts by calling startService(), resulting in a call to the service's onStartCommand() method.

A services runs in the same process as the application in which it is declared and in the main thread of that application, by default. So, if our service performs intensive or blocking operations while the user interacts with an activity from the same application, the service will slow down activity performance. To avoid impacting an application performance, we should start a new thread inside the service.

Traditionally, there are two classes we can extend to create a started service:

Service

This is the base class for all services. When we extend this class, it's important that we create a new thread in which to do all the service's work, because the service uses our application's main thread, by default, which could slow the performance of any activity our application is running.

IntentService

This is a subclass of service that uses a worker thread to handle all start requests, one at a time. This is the best option if we don't require that our service handle multiple requests simultaneously. All we need to do is implement onHandleIntent(), which receives the intent for each start request so we can do the background work.

Extending the IntentService class

The IntentService does the following:

a> Creates a default worker thread that executes all intents delivered to onStartCommand() separate from our application's main thread.

b> Creates a work queue that passes one intent at a time to our onHandleIntent() implementation, so we never have to worry about multi-threading.

c> Stops the service after all start requests have been handled, so we never have to call stopSelf().

d> Provides default implementation of onBind() that returns null.

e> Provides a default implementation of onStartCommand() that sends the intent to the work queue and then to our onHandleIntent() implementation.

All our need to do is implement onHandleIntent() to do the work provides by the client. Though, we also need to provide a small constructor for the service, which defines a name for the worker thread.

Beside onHandleIntent(), the only method from which we don't need to call the super is onBind() (but we only need to implement that if our service allows binding).

Extending the Service class

If we require our service to perform multi-threading (instead of processing start requests through a work queue), then we can extend the Service class to handle each intent.

Notice that the onStartCommand() method must return an integer. The integer is a value that describes how the system should continue the service in the event that the system kills it. The return value from onStartCommand() must be one of the following constants:

START_NOT_STICKY

If the system kills the service after onStartCommand() returns, do not recreate the service, unless there are pending intents to deliver. This is the safest option to avoid running our service when not necessary and when our application can simply restart any unfinished jobs.

START_STICKY

If the system kills the service after onStartCommand() returns, recreate the service and call onStartCommand(), but do not redeliver the last intent. Instead, the system calls onStartCommand() with a null intent, unless there were pending intents to start the service, in which case, those intents are delivered.

START_REDELIVER_INTENT

If the system kills the service after onStartCommand() returns, recreate the service and call onStartCommand() with the last intent that was delivered to the service.

This is suitable for services that are actively performing a job that should be immediately resumes, such as download a file.

Starting a Service

We can start a service from an activity or other application component by passing an intent to startService(). 

The startService() method returns immediately and the Android system calls the service's' onStartCommand() method. If the service is not already running, the system first calls onCreate(), then calls onStartCommand().

If we want the service to send a result back, then the client that starts the service can create a PendingIntent for a broadcast and deliver it to the service in the intent that starts the service.

Multiple requests to start the service result in multiple corresponding calls to the service's onStartCommand(). However, only one request to stop the service (with stopSelf() or stopService()) is required to stop it.

Stopping a service

A started service must manage its own lifecycle. That is, the system does not stop or destroy the service unless it must recover system memory and the service continue to run after onStartCommand() returns. So, the service must stop itself by calling stopSelf() or another component can stop it by calling stopService().

However, if our service handles multiple requests to onStartCommand() concurrently, then we shouldn't stop the service when we're done processing a start request, because we might have since received a new start request. To avoid this problem, we can use stopSelf(int) to ensure that our request to stop the service is always based on the most recent start request. That is, when we call stopSelf(int), we pass the ID of the start request (the startId delivered to onStartCommand()) to which our stop request corresponds. Then if the service received a new start request before were able to call stopSelf(int), then the ID will not match and the service will not stop.

It's important that our application stops its services when it's done working, to avoid wasting system resources and consuming battery power. If necessary, other components can stop the service by calling stopService(). Even if we enable binding for the service, we must always stop the service ourselves if is ever received a call to onStartCommand().

Creating a Bound Service

A bound service is one that allows application components to bind to it by calling bindService() in order to create a long-standing connection (and generally does not allow components to start it by startService()).

We should create service when we want to interact with the service from activities and other components in our application or to expose some of our application's functionality to other applications, through interprocess communication (IPC).

To create a bound service, the first thing we must do is define the interface that specifies how a client can communicate with the service.

Multiple clients can bind to the service at once. When a client is done interacting with the service, it calls unbindService() to unbind. Once there are no clients bound to the service, the system destroys the service.

Sending Notifications to the User

Once running, a service can notify the user of events using Toast Notifications or Status Bar Notifications.

Usually, a status bar notification is the best technique when some background work has completed and the user can now act on it.

Running a service in the Foreground

A foreground service is a service that's considered to be something the user is actively aware of and thus not a candidate for the system to kill when low on memory. A foreground service must provide a notification for the status bar, which is placed under the "Ongoing" heading, which means that the notification cannot be dismissed unless the service is either stopped or removed from the foreground.

To request that our service run in the foreground, call startForeground(). This method takes two parameters: an integer that uniquely identifies the notification and the Notification for the status bar. And the integer ID we give to startForeground() must not be 0.

To remove the service from the foreground, call stopForeground(). This method takes a boolean, indicating whether to remove the status bar notification as well. This method does not stop the service. However, if we stop the service while it's still running in the foreground, then the notification is also removed.


Managing the Lifecycle of a Service

The service lifecycle --- from when it's created to when it's destroyed --- can follow two different paths:

a> A started service

The service is created when another component calls startService(). The service then runs indefinitely and must stop itself by calling stopSelf(). Another component can also stop the service by calling stopService(). When the service is stopped, the system destroys it.

b> A bound service

The service is created when another component (a client) calls bindService(). The client then communicates with the service through an IBinder interface. The client can close the connection by calling unbindService(). Multiple clients can bind to the same service and when all of them unbind, the system destroys the service. (The service does not need to stop itself.)

Implementing the lifecycle callbacks

微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码 微信小程序毕业设计期末大作业项目源码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值