AServiceis 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). For example, a service might handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background.

A service can essentially take two forms:

Started
A service is "started" when an application component (such as an activity) starts 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. For example, it might download or upload a file over the network. 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-server 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.

Although this documentation generally discusses these two types of services separately, your service can work both ways—it can be started (to run indefinitely) and also allow binding. It's simply a matter of whether you implement a couple callback methods:onStartCommand()to allow components to start it andonBind()to allow binding.

Regardless of whether your application is started, bound, or both, any application component can use the service (even from a separate application), in the same way that any component can use an activity—by starting it with anIntent. However, you can declare the service as private, in the manifest file, and block access from other applications. This is discussed more in the section aboutDeclaring the service in the manifest.

Caution:A service runs in the main thread of its hosting process—the service doesnotcreate its own thread and doesnotrun in a separate process (unless you specify otherwise). This means that, if your service is going to do any CPU intensive work or blocking operations (such as MP3 playback or networking), you should create a new thread within the service to do that work. By using a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the application's main thread can remain dedicated to user interaction with your activities.

The Basics

Should you use a service or a thread?

A service is simply a component that can run in the background even when the user is not interacting with your application. Thus, you should create a service only if that is what you need.

If you need to perform work outside your main thread, but only while the user is interacting with your application, then you should probably instead create a new thread and not a service. For example, if you want to play some music, but only while your activity is running, you might create a thread inonCreate(), start running it inonStart(), then stop it inonStop(). Also consider usingAsyncTaskorHandlerThread, instead of the traditionalThreadclass. See theProcesses and Threadingdocument for more information about threads.

Remember that if you do use a service, it still runs in your application's main thread by default, so you should still create a new thread within the service if it performs intensive or blocking operations.

To create a service, you must create a subclass ofService(or one of its existing subclasses). In your implementation, you need to override some callback methods that handle key aspects of the service lifecycle and provide a mechanism for components to bind to the service, if appropriate. The most important callback methods you should override are:

onStartCommand()
The system calls this method when another component, such as an activity, 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 you implement this, it is your responsibility to stop the service when its work is done, by calling stopSelf()or stopService(). (If you only want to provide binding, you don't need to implement this method.)
onBind()
The system calls this method when another component wants to bind with the service (such as to perform RPC), by calling bindService(). In your implementation of this method, you must provide an interface that clients use to communicate with the service, by returning an IBinder. You must always implement this method, but if you don't want to allow binding, then you 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. Your service should implement this to clean up any resources such as threads, registered listeners, receivers, etc. This is the last call the service receives.

If a component starts the service by callingstartService()(which results in a call toonStartCommand()), then the service remains running until it stops itself withstopSelf()or another component stops it by callingstopService().

If a component callsbindService()to create the service (andonStartCommand()isnotcalled), 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 torun in the foreground(discussed later), 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 your service is started, then you must design it to gracefully handle restarts by the system. If the system kills your service, it restarts it as soon as resources become available again (though this also depends on the value you return fromonStartCommand(), as discussed later). For more information about when the system might destroy a service, see theProcesses and Threadingdocument.

In the following sections, you'll see how you can create each type of service and how to use it from other application components.

Declaring a service in the manifest

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

To declare your service, add a<service>element as a child of the<application>element. For example:

<manifest ... > ... <application ... >   <service android:name=".ExampleService" />   ... </application></manifest>

See the<service>element reference for more information about declaring your service in the manifest.

There are other attributes you can include in the<service>element to define properties such as permissions required to start the service and the process in which the service should run. Theandroid:nameattribute is the only required attribute—it specifies the class name of the service. Once you publish your application, you should not change this name, because if you do, you risk breaking code due to dependence on explicit intents to start or bind the service (read the blog post,Things That Cannot Change).

To ensure your app is secure,always use an explicit intent when starting or binding yourServiceand do not declare intent filters for the service. If it's critical that you allow for some amount of ambiguity as to which service starts, you can supply intent filters for your services and exclude the component name from theIntent, but you then must set the package for the intent withsetPackage(), which provides sufficient disambiguation for the target service.

Additionally, you can ensure that your service is available to only your app by including theandroid:exportedattribute and setting it to"false". This effectively stops other apps from starting your service, even when using an explicit intent.

Creating a Started Service

A started service is one that another component starts by callingstartService(), resulting in a call to the service'sonStartCommand()method.

When a service is started, it has a lifecycle that's independent of the component that started it and the service can run in the background indefinitely, even if the component that started it is destroyed. As such, the service should stop itself when its job is done by callingstopSelf(), or another component can stop it by callingstopService().

An application component such as an activity can start the service by callingstartService()and passing anIntentthat specifies the service and includes any data for the service to use. The service receives thisIntentin theonStartCommand()method.

For instance, suppose an activity needs to save some data to an online database. The activity can start a companion service and deliver it the data to save by passing an intent tostartService(). The service receives the intent inonStartCommand(), connects to the Internet and performs the database transaction. When the transaction is done, the service stops itself and it is destroyed.

Caution:A service 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 your 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 application performance, you should start a new thread inside the service.

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

Service
This is the base class for all services. When you extend this class, it's important that you create a new thread in which to do all the service's work, because the service uses your application's main thread, by default, which could slow the performance of any activity your application is running.
IntentService
This is a subclass of Servicethat uses a worker thread to handle all start requests, one at a time. This is the best option if you don't require that your service handle multiple requests simultaneously. All you need to do is implement onHandleIntent(), which receives the intent for each start request so you can do the background work.

The following sections describe how you can implement your service using either one for these classes.

Extending the IntentService class

Because most started services don't need to handle multiple requests simultaneously (which can actually be a dangerous multi-threading scenario), it's probably best if you implement your service using theIntentServiceclass.

TheIntentServicedoes the following:

  • Creates a default worker thread that executes all intents delivered toonStartCommand()separate from your application's main thread.
  • Creates a work queue that passes one intent at a time to youronHandleIntent()implementation, so you never have to worry about multi-threading.
  • Stops the service after all start requests have been handled, so you never have to callstopSelf().
  • Provides default implementation ofonBind()that returns null.
  • Provides a default implementation ofonStartCommand()that sends the intent to the work queue and then to youronHandleIntent()implementation.

All this adds up to the fact that all you need to do is implementonHandleIntent()to do the work provided by the client. (Though, you also need to provide a small constructor for the service.)

Here's an example implementation ofIntentService:

public class HelloIntentService extends IntentService { /** * A constructor is required, and must call the super IntentService(String) * constructor with a name for the worker thread. */ public HelloIntentService() {   super("HelloIntentService"); } /** * The IntentService calls this method from the default worker thread with * the intent that started the service. When this method returns, IntentService * stops the service, as appropriate. */ @Override protected void onHandleIntent(Intent intent) {   // Normally we would do some work here, like download a file.   // For our sample, we just sleep for 5 seconds.   try {     Thread.sleep(5000);   } catch (InterruptedException e) {     // Restore interrupt status.     Thread.currentThread().interrupt();   } }}

That's all you need: a constructor and an implementation ofonHandleIntent().

If you decide to also override other callback methods, such asonCreate(),onStartCommand(), oronDestroy(), be sure to call the super implementation, so that theIntentServicecan properly handle the life of the worker thread.

For example,onStartCommand()must return the default implementation (which is how the intent gets delivered toonHandleIntent()):

@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {  Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();  return super.onStartCommand(intent,flags,startId);}

BesidesonHandleIntent(), the only method from which you don't need to call the super class isonBind()(but you only need to implement that if your service allows binding).

In the next section, you'll see how the same kind of service is implemented when extending the baseServiceclass, which is a lot more code, but which might be appropriate if you need to handle simultaneous start requests.

Extending the Service class

As you saw in the previous section, usingIntentServicemakes your implementation of a started service very simple. If, however, you require your service to perform multi-threading (instead of processing start requests through a work queue), then you can extend theServiceclass to handle each intent.

For comparison, the following example code is an implementation of theServiceclass that performs the exact same work as the example above usingIntentService. That is, for each start request, it uses a worker thread to perform the job and processes only one request at a time.

public class HelloService extends Service { private Looper mServiceLooper; private ServiceHandler mServiceHandler; // Handler that receives messages from the thread private final class ServiceHandler extends Handler {   public ServiceHandler(Looper looper) {     super(looper);   }   @Override   public void handleMessage(Message msg) {     // Normally we would do some work here, like download a file.     // For our sample, we just sleep for 5 seconds.     try {       Thread.sleep(5000);     } catch (InterruptedException e) {       // Restore interrupt status.       Thread.currentThread().interrupt();     }     // Stop the service using the startId, so that we don't stop     // the service in the middle of handling another job     stopSelf(msg.arg1);   } } @Override public void onCreate() {  // Start up the thread running the service. Note that we create a  // separate thread because the service normally runs in the process's  // main thread, which we don't want to block. We also make it  // background priority so CPU-intensive work will not disrupt our UI.  HandlerThread thread = new HandlerThread("ServiceStartArguments",      Process.THREAD_PRIORITY_BACKGROUND);  thread.start();  // Get the HandlerThread's Looper and use it for our Handler  mServiceLooper = thread.getLooper();  mServiceHandler = new ServiceHandler(mServiceLooper); } @Override public int onStartCommand(Intent intent, int flags, int startId) {   Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();   // For each start request, send a message to start a job and deliver the   // start ID so we know which request we're stopping when we finish the job   Message msg = mServiceHandler.obtainMessage();   msg.arg1 = startId;   mServiceHandler.sendMessage(msg);   // If we get killed, after returning from here, restart   return START_STICKY; } @Override public IBinder onBind(Intent intent) {   // We don't provide binding, so return null   return null; } @Override public void onDestroy() {  Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); }}

As you can see, it's a lot more work than usingIntentService.

However, because you handle each call toonStartCommand()yourself, you can perform multiple requests simultaneously. That's not what this example does, but if that's what you want, then you can create a new thread for each request and run them right away (instead of waiting for the previous request to finish).

Notice that theonStartCommand()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 (as discussed above, the default implementation forIntentServicehandles this for you, though you are able to modify it). The return value fromonStartCommand()must be one of the following constants:

START_NOT_STICKY
If the system kills the service after onStartCommand()returns, do notrecreate the service, unless there are pending intents to deliver. This is the safest option to avoid running your service when not necessary and when your 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 notredeliver 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. This is suitable for media players (or similar services) that are not executing commands, but running indefinitely and waiting for a job.
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. Any pending intents are delivered in turn. This is suitable for services that are actively performing a job that should be immediately resumed, such as downloading a file.

For more details about these return values, see the linked reference documentation for each constant.

Starting a Service

You can start a service from an activity or other application component by passing anIntent(specifying the service to start) tostartService(). The Android system calls the service'sonStartCommand()method and passes it theIntent. (You should never callonStartCommand()directly.)

For example, an activity can start the example service in the previous section (HelloSevice) using an explicit intent withstartService():

Intent intent = new Intent(this, HelloService.class);startService(intent);

ThestartService()method returns immediately and the Android system calls the service'sonStartCommand()method. If the service is not already running, the system first callsonCreate(), then callsonStartCommand().

If the service does not also provide binding, the intent delivered withstartService()is the only mode of communication between the application component and the service. However, if you want the service to send a result back, then the client that starts the service can create aPendingIntentfor a broadcast (withgetBroadcast()) and deliver it to the service in theIntentthat starts the service. The service can then use the broadcast to deliver a result.

Multiple requests to start the service result in multiple corresponding calls to the service'sonStartCommand(). However, only one request to stop the service (withstopSelf()orstopService()) 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 continues to run afteronStartCommand()returns. So, the service must stop itself by callingstopSelf()or another component can stop it by callingstopService().

Once requested to stop withstopSelf()orstopService(), the system destroys the service as soon as possible.

However, if your service handles multiple requests toonStartCommand()concurrently, then you shouldn't stop the service when you're done processing a start request, because you might have since received a new start request (stopping at the end of the first request would terminate the second one). To avoid this problem, you can usestopSelf(int)to ensure that your request to stop the service is always based on the most recent start request. That is, when you callstopSelf(int), you pass the ID of the start request (thestartIddelivered toonStartCommand()) to which your stop request corresponds. Then if the service received a new start request before you were able to callstopSelf(int), then the ID will not match and the service will not stop.

Caution:It's important that your 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 callingstopService(). Even if you enable binding for the service, you must always stop the service yourself if it ever received a call toonStartCommand().

For more information about the lifecycle of a service, see the section below aboutManaging the Lifecycle of a Service.

Creating a Bound Service

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

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

To create a bound service, you must implement theonBind()callback method to return anIBinderthat defines the interface for communication with the service. Other application components can then callbindService()to retrieve the interface and begin calling methods on the service. The service lives only to serve the application component that is bound to it, so when there are no components bound to the service, the system destroys it (you donotneed to stop a bound service in the way you must when the service is started throughonStartCommand()).

To create a bound service, the first thing you must do is define the interface that specifies how a client can communicate with the service. This interface between the service and a client must be an implementation ofIBinderand is what your service must return from theonBind()callback method. Once the client receives theIBinder, it can begin interacting with the service through that interface.

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

There are multiple ways to implement a bound service and the implementation is more complicated than a started service, so the bound service discussion appears in a separate document aboutBound Services.

Sending Notifications to the User

Once running, a service can notify the user of events usingToast NotificationsorStatus Bar Notifications.

A toast notification is a message that appears on the surface of the current window for a moment then disappears, while a status bar notification provides an icon in the status bar with a message, which the user can select in order to take an action (such as start an activity).

Usually, a status bar notification is the best technique when some background work has completed (such as a file completed downloading) and the user can now act on it. When the user selects the notification from the expanded view, the notification can start an activity (such as to view the downloaded file).

See theToast NotificationsorStatus Bar Notificationsdeveloper guides for more information.

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.

For example, a music player that plays music from a service should be set to run in the foreground, because the user is explicitly aware of its operation. The notification in the status bar might indicate the current song and allow the user to launch an activity to interact with the music player.

To request that your service run in the foreground, callstartForeground(). This method takes two parameters: an integer that uniquely identifies the notification and theNotificationfor the status bar. For example:

Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),    System.currentTimeMillis());Intent notificationIntent = new Intent(this, ExampleActivity.class);PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);notification.setLatestEventInfo(this, getText(R.string.notification_title),    getText(R.string.notification_message), pendingIntent);startForeground(ONGOING_NOTIFICATION_ID, notification);

Caution:The integer ID you give tostartForeground()must not be 0.

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

For more information about notifications, seeCreating Status Bar Notifications.

Managing the Lifecycle of a Service

The lifecycle of a service is much simpler than that of an activity. However, it's even more important that you pay close attention to how your service is created and destroyed, because a service can run in the background without the user being aware.

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

  • A started service

    The service is created when another component callsstartService(). The service then runs indefinitely and must stop itself by callingstopSelf(). Another component can also stop the service by callingstopService(). When the service is stopped, the system destroys it..

  • A bound service

    The service is created when another component (a client) callsbindService(). The client then communicates with the service through anIBinderinterface. The client can close the connection by callingunbindService(). Multiple clients can bind to the same service and when all of them unbind, the system destroys the service. (The service doesnotneed to stop itself.)

These two paths are not entirely separate. That is, you can bind to a service that was already started withstartService(). For example, a background music service could be started by callingstartService()with anIntentthat identifies the music to play. Later, possibly when the user wants to exercise some control over the player or get information about the current song, an activity can bind to the service by callingbindService(). In cases like this,stopService()orstopSelf()does not actually stop the service until all clients unbind.

Implementing the lifecycle callbacks

Like an activity, a service has lifecycle callback methods that you can implement to monitor changes in the service's state and perform work at the appropriate times. The following skeleton service demonstrates each of the lifecycle methods:

public class ExampleService extends Service {  int mStartMode;    // indicates how to behave if the service is killed  IBinder mBinder;   // interface for clients that bind  boolean mAllowRebind; // indicates whether onRebind should be used  @Override  public void onCreate() {    // The service is being created  }  @Override  public int onStartCommand(Intent intent, int flags, int startId) {    // The service is starting, due to a call to startService()    return mStartMode;  }  @Override  public IBinder onBind(Intent intent) {    // A client is binding to the service with bindService()    return mBinder;  }  @Override  public boolean onUnbind(Intent intent) {    // All clients have unbound with unbindService()    return mAllowRebind;  }  @Override  public void onRebind(Intent intent) {    // A client is binding to the service with bindService(),    // after onUnbind() has already been called  }  @Override  public void onDestroy() {    // The service is no longer used and is being destroyed  }}

Note:Unlike the activity lifecycle callback methods, you arenotrequired to call the superclass implementation of these callback methods.

Figure 2.The service lifecycle. The diagram on the left shows the lifecycle when the service is created withstartService()and the diagram on the right shows the lifecycle when the service is created withbindService().

By implementing these methods, you can monitor two nested loops of the service's lifecycle:

  • Theentire lifetimeof a service happens between the timeonCreate()is called and the timeonDestroy()returns. Like an activity, a service does its initial setup inonCreate()and releases all remaining resources inonDestroy(). For example, a music playback service could create the thread where the music will be played inonCreate(), then stop the thread inonDestroy().

    TheonCreate()andonDestroy()methods are called for all services, whether they're created bystartService()orbindService().

  • Theactive lifetimeof a service begins with a call to eitheronStartCommand()oronBind(). Each method is handed theIntentthat was passed to eitherstartService()orbindService(), respectively.

    If the service is started, the active lifetime ends the same time that the entire lifetime ends (the service is still active even afteronStartCommand()returns). If the service is bound, the active lifetime ends whenonUnbind()returns.

Note:Although a started service is stopped by a call to eitherstopSelf()orstopService(), there is not a respective callback for the service (there's noonStop()callback). So, unless the service is bound to a client, the system destroys it when the service is stopped—onDestroy()is the only callback received.

Figure 2 illustrates the typical callback methods for a service. Although the figure separates services that are created bystartService()from those created bybindService(), keep in mind that any service, no matter how it's started, can potentially allow clients to bind to it. So, a service that was initially started withonStartCommand()(by a client callingstartService()) can still receive a call toonBind()(when a client callsbindService()).

For more information about creating a service that provides binding, see theBound Servicesdocument, which includes more information about theonRebind()callback method in the section aboutManaging the Lifecycle of a Bound Service.

一个服务是可以在后台执行长时间运行操作,并且不提供用户界面的应用组件。另一个应用程序组件可以启动服务,它就会继续在即使用户切换到另一个应用程序在后台运行。此外,一个组件可以绑定到一个服务来与它进行交互,甚至进行进程间通信(IPC)。例如,服务可能处理网络交易,播放音乐,执行文件I / O,或与内容供应商进行互动,所有从背景。

服务基本上可以采取两种形式:

入门
服务是“开始”的时候应用程序组件(如活动)通过调用启动它 startService()。一旦开始,一个服务可以无限期在后台运行,即使启动它的成分被破坏。通常,启动服务执行单次操作和结果不返回给调用者。例如,它可能下载或上传在网络上的文件。当操作完成时,服务应该停止本身。
服务是“必然”,当应用程序组件通过调用绑定到它 bindService()。绑定的服务提供了一个客户端-服务器接口,允许组件与服务交互,发送请求,得到的结果,甚至跨越与进程间通信(IPC)的进程这样做。绑定的服务只只要其他应用程序组件绑定到它运行。多个组件可以绑定到服务一次,但是,当它们全部取消绑定,服务被破坏。

虽然此文件通常分别讨论这两种类型的服务,您的服务可以两种方式工作,它可以启动(无限期运行),也允许绑定。它只是你是否实现了几个回调方法的问题:onStartCommand(),以允许组件启动和onBind()允许绑定。

无论应用程序是否是启动的,结合的,或两者的任何应用程序组件可以使用的服务(甚至从一个单独的应用程序),以同样的方式,任何组件可以由活性与启动它使用意图。但是,你可以声明服务为私有,在清单文件,并阻止来自其他应用程序的访问。这是在有关部分的更多讨论在清单申报服务。

注意:服务在其托管过程中服务不主线程运行不会创建自己的线程,也不会在一个单独的进程中运行(除非另行指定)。这意味着,如果你的服务是打算做任何CPU密集型工作或阻塞操作(如MP3播放或网络),你应该在服务中创建一个新的线程来完成这项工作。通过使用一个单独的线程,你会降低应用风险不响应(ANR)错误和应用程序的主线程可以继续致力于用户交互与你的活动。

基础

如果您使用服务或线程?

服务仅仅是可以在后台,即使用户不与应用程序交互运行的组件。因此,你应该创建一个服务只如果那是你所需要的。

如果你需要你的主线程之外执行的工作,但只有在用户与应用程序交互,那么你或许应该,而不是创建一个新的线程,而不是服务。例如,如果你要玩一些音乐,但你的活动正在运行仅在,你可以创建一个线程的onCreate()开始运行它在onStart()然后停止它的onStop()也可以考虑使用的AsyncTaskHandlerThread而不是传统的,线程类。查看进程和线程关于线程的详细信息的文件。

请记住,如果你使用一个服务,它仍然在默认情况下,您的应用程序的主线程中运行,所以你还是应该在服务中创建一个新的线程,如果它执行密集或阻塞操作。

要创建一个服务,你必须创建的子类服务(或者其现有的一个子类)。在您的实现,你需要重写处理服务生命周期的关键方面的一些回调方法,并提供了一种机制,组件,如果合适的话绑定到服务。你应该重写最重要的回调方法是:

onStartCommand()
系统调用此方法时另一组件,如一个活动,要求该服务被启动,通过调用 startService()。一旦这个方法执行,该服务已启动,可以在后台运行下去。如果实现这一点,这是你的责任,当其工作完成后,通过调用停止服务 stopSelf()stopService()。(如果你只希望提供绑定,你并不需要实现这个方法。)
onBind()
该系统调用此方法时,另一部分要与服务(如执行RPC)绑定,通过调用 bindService()。在实现此方法,您必须提供客户端使用通过返回一个与该服务进行通信,接口 的IBinder。你必须始终实现此方法,但如果你不想让绑定,那么你应该返回null。
的onCreate()
该系统调用时,第一次创建服务这种方法,进行一次性设置程序(它要求无论是之前 onStartCommand()onBind())。如果该服务已在运行,这种方法不会被调用。
的onDestroy()
系统调用当服务不再使用而被销毁此方法。您的服务应实现此清理任何资源如线程,注册的监听器,接收器等,这是服务接收最后一次通话。

如果一个组件通过调用启动服务startService()(其导致一个呼叫onStartCommand()),则服务保持运行,直到其停止本身stopSelf()或另一组件通过调用停止它stopService()

如果一个组件调用bindService()创建服务(和onStartCommand()叫),则服务仅只要该组件绑定到运行。一旦服务是所有客户端绑定,系统破坏它。

只有当内存不足的Android系统将强制停止服务,它必须恢复系统资源为具有用户焦点的活动。如果该服务被绑定到用户具有焦点的活动,那么它不太可能被杀害,而如果该服务被宣布为在前台运行(稍后讨论),那么它几乎不会被杀死。否则,如果该服务已启动,并且是长期运行的,那么系统会降低其在后台任务列表中的位置随着时间的推移,该服务将变得非常容易杀死,如果您的服务已启动,则必须将其设计为优雅地处理由系统重新启动。如果系统杀死你的服务,请尽快重新启动它的资源再次可用(尽管这也取决于你从返回值onStartCommand(),作为稍后讨论)。有关当系统可能会破坏服务的更多信息,请参见进程和线程文件。

在下面的章节中,您将看到如何创建每种类型的服务,以及如何从其他应用程序组件使用它。

声明在清单服务

之类的活动(和其他组件),则必须在应用程序的清单文件中声明的所有服务。

要声明你的服务,增加的<service>元素作为一个孩子<应用程序>元素。例如:

<清单... >  ...  <应用... >    <服务 机器人:名字= “.ExampleService”  />    ...  </应用程序> </清单>

请参阅<服务>有关清单中声明你的服务的更多信息元素引用。

还有其他的属性可以包含在<服务>元素来定义属性,如启动该服务,并在服务应该运行过程中所需的权限。该机器人:名称属性是唯一必需的属性,它指定服务类的名称。一旦你发布你的应用程序,因为如果你这样做,你断码,由于在明确意图来启动或绑定服务的依赖风险不应该更改这个名字,(阅读博客文章,事情可以不更改)。

为确保您的应用程序是安全的,启动或绑定您时请务必使用明确意图服务,不为服务声明意图过滤器。如果它的关键,您允许的歧义一定量的该服务启动时,你可以为你的服务供应意图过滤器,并从排除组件名称意图,但你必须设置包的意图setPackage(),这为目标服务足够消歧。

此外,还可以确保您的服务只提供给您的应用程序通过包括机器人:出口属性并将其设置为“假”。这有效地启动你的服务,使用一个明确的意图,即使停止其他应用程序。

创建一个启动的服务

已启动的服务是一个另一个组件开始通过调用startService(),造成该服务的调用onStartCommand()方法。

当服务启动时,它有一个生命周期的自主启动它,服务可以在后台运行无限期组件,即使启动它的成分被破坏。这样,服务应该停止本身时,其作业是通过调用完成stopSelf(),或其他部件可以通过调用停止stopService()

一个应用程序组件,如一个活性可以通过调用启动服务startService(),并通过一个意图指定服务,并且包括用于向使用该服务的任何数据。服务接收这个意图onStartCommand()方法。

例如,假设一个活动需要一些数据保存到一个在线数据库。活动可以启动一个同伴服务,并提供其数据传递的意图,以节省startService()。服务接收的意图onStartCommand(),连接到互联网,并执行数据库事务。当交易完成时,服务停止本身和它被破坏。

注意:服务在同一个进程中声明它的应用程序,该应用程序的主线程中运行,在默认情况下。所以,如果你的服务,而用户从同一个应用程序的交互活动进行密集或阻塞操作,该服务将减慢活动的表现。为避免影响应用程序的性能,你应该开始在服务中一个新的线程。

传统上,还有你可以扩展创建一个启动的服务两大类:

服务
这是对于所有服务的基类。当你扩展这个类,它是创建在其中做的所有服务工作的一个新的线程,因为该服务使用你的应用程序的主线程,默认情况下,这可能会减慢你的应用程序正在运行的任何活动的表现是很重要的。
IntentService
这是一个亚类 服务,它使用一个工作线程来处理所有的开始请求,一次一个。这是最好的选择,如果你不要求你的服务同时处理多个请求。所有你需要做的是落实 onHandleIntent(),它接收的每个请求的开始,所以你可以做后台工作的意图。

以下各节描述了如何使用任何一个这些类实现您服务。

扩展IntentService类

由于大多数启动的服务并不需要同时处理多个请求(这实际上是一个危险的多线程情况下),如果你使用实现你的服务很可能是最好的IntentService类 ​​。

IntentService执行以下操作:

  • 创建一个默认的工作线程执行交付给所有意图onStartCommand()从应用程序的主线程中分离出来。
  • 创建一个在同一时间到你经过1意图工作队列onHandleIntent()实现,所以你永远不必担心多线程。
  • 毕竟停止服务启动请求已经被处理,所以你从来没有打电话给stopSelf()
  • 提供的默认实现onBind()的返回null。
  • 提供的默认实现onStartCommand()发送的意图的工作队列,然后到您onHandleIntent()实现。

这一切都增加了一个事实,即所有你需要做的就是实现onHandleIntent()做客户端提供的工作。(虽然,你还需要提供该服务的小构造函数)。

下面是一个例子实施IntentService

公共  HelloIntentService  扩展 IntentService  {  / **  *需要一个构造函数,必须调用超级IntentService(字符串)  *构造与工作线程的名称。 * /  公共 HelloIntentService () {    “HelloIntentService” );  }  / **  *本IntentService调用从默认的工作线程这种方法 *启动该服务的意图。此方法返回时,IntentService  *停止服务,根据。 * /  @覆盖 保护 无效onHandleIntent 意向意图 {    //通常我们会做一些工作在这里,就像要下载的文件。   //对于我们的示例,我们只是睡5秒钟。   尝试 {      线程睡觉5000 );    }  赶上 InterruptedException的ē  {      //恢复中断状态。     线程currentThread ()。中断();    }  } }

这就是你需要:一个构造函数和的实现onHandleIntent()

如果您决定还覆盖其他回调方法,如OnCreate()中onStartCommand(),或的onDestroy()时,一定要调用父类的实现,使IntentService能妥善处理工作线程的使用寿命。

例如,onStartCommand()必须返回默认的实现(这是意图如何被传递到onHandleIntent()):

@覆盖公共 INT onStartCommand 意向意图 诠释旗帜 INT startId  {   吐司makeText  “服务启动”  吐司LENGTH_SHORT 显示();   返回 onStartCommand 意图标志startId ); }

除了​​onHandleIntent(),从中你不需要调用超类的唯一方法是onBind()(但你只需要实现,如果你的服务允许绑定)。

在下一节中,您将看到如何延伸的基础,当同类服务实现服务类,这是很多更多的代码,但如果你需要同时处理开始请求这可能是合适的。

扩展服务类

当你在上一节中所看到的,使用IntentService让您一开始服务的实现非常简单。但是,如果你需要你的服务来执行多线程(而不是通过工作队列处理开始请求),那么你可以扩展服务类来处理每一个意图。

为了进行比较,以下示例代码是的实现服务执行完全相同的工作与上述利用示例类IntentService。也就是说,对于每一个启动请求时,它使用一个工作线程来执行该作业和过程在一个时间只有一个请求。

          处理程序,从接收到的消息                                  通常我们会做一些工作在这里,就像要下载的文件。     //对于我们的示例,我们只是睡,持续5秒。     尝试 {        线程睡眠5000 );      }  赶上 InterruptedException的ē  {        //恢复中断状态。       线程currentThread ()。中断();      }      //停止使用startId服务,这样我们就不会停止     //在处理另一份工作中间的服务     stopSelf 味精ARG1 );    }  }  @覆盖 公共 无效的onCreate () {   //启动线程运行的服务。请注意,我们创建了一个  //单独的线程,因为该服务通常在这个过程中的运行  //主线程,这是我们不希望阻止。我们还使它  //背景优先级,CPU密集型的工作不会破坏我们的             获取HandlerThread的活套,并用它为我们的              开始“  吐司LENGTH_SHORT 显示();    //对于每一个开始请求,发送邮件,开始工作并交付   当我们完成这个工作//开始编号,所以我们知道这要求我们停止   消息味精= mServiceHandler obtainMessage ();    味精ARG1 = startId ;    mServiceHandler 的sendMessage MSG );    //如果我们被打死,从这里回国后,重新   返回START_STICKY ;  }  @覆盖 公共 的IBinder onBind 意向意图 {    //我们不'T提供的绑定,所以返回null    返回 ;  }  @覆盖 公共 无效的onDestroy () {   吐司makeText 这个 “做服务”  吐司LENGTH_SHORT 显示();  } }

正如你所看到的,它比使用大量的工作IntentService

但是,因为你处理每个调用onStartCommand()你自己,你可以同时执行多个请求。这不是这个例子做什么,但如果这是你想要的,那么你可以为每个请求创建一个新的线程和运行它们的时候了(而不是等待前一个请求完成)。

请注意,onStartCommand()方法必须返回一个整数。整数是描述系统应如何继续在该系统杀死它时服务(如上面所讨论的,默认的实现值IntentService为您处理此,尽管你可以修改它)。从返回值onStartCommand()必须是以下常量之一:

START_NOT_STICKY
如果系统杀死后服务 onStartCommand()返回时, 重新创建的服务,除非存在未处理的意图来提供。这是为了避免运行服务时,没有必要的,当你的应用程序可以简单地重新启动任何未完成的作业最安全的选择。
START_STICKY
如果系统杀死后,在服务 onStartCommand()返回,重新创建服务并调用 onStartCommand(),但 重新传送的最后一个意图。相反,系统调用 onStartCommand()用空的意图,除非有未决的意图来启动服务,在这种情况下,那些意图传递。这是适合于不执行命令,但无限期运行和等待作业媒体播放器(或类似的服务)。
START_REDELIVER_INTENT
如果系统杀死后,在服务 onStartCommand()返回,重新创建服务并调用 onStartCommand()与被输送到该服务的最后意图。任何挂起的意图被依次传递。这是适合于正在积极执行该应立即工作恢复时,如下载文件的服务。

有关这些返回值的更多详细信息,请参阅各不变链接参考文档。

启动服务

你可以通过传递一个开始从一个活动或其它应用程序组件服务意向书(指定服务启动)到startService()。Android系统调用服务的onStartCommand()方法,并传递给它意图。(你不应该叫onStartCommand()直接。)

例如,一个活动就可以开始在上一节(在示例服务HelloSevice使用具有显式意图)startService()

意向意图=   意图 为HelloService ); startService 意向);

startService()方法立即返回,Android系统调用服务的onStartCommand()方法。如果该服务尚未运行,系统首先调用的onCreate(),然后调用onStartCommand()

如果服务不还提供了绑定,与交付的意图startService()是应用程序组件和服务之间的通信的唯一方式。不过,如果你希望服务的结果发回,然后启动该服务的客户端可以创建的PendingIntent为广播(带getBroadcast()),它在传递到服务意向启动该服务。然后该服务可以使用广播来提供一个结果。

多个请求启动该服务,导致多个相应的调用该服务的onStartCommand()。但是,只有一个要求停止服务(与stopSelf()stopService())来阻止它。

停止服务

已启动的服务必须管理自己的生命周期。也就是说,系统不中断或破坏服务,除非它必须恢复系统内存和服务后继续运行onStartCommand()的回报。因此,该服务必须通过调用自行停止stopSelf()或其他部件可以通过调用停止stopService()

一旦请求停止与stopSelf()stopService()时,系统立即破坏服务成为可能。

但是,如果你的服务处理多个请求onStartCommand()兼任,那么你不应该因为收到一个新的开始请求(在第一年底停止停止服务,当你处理完一个开始请求,因为你可能有请求将终止,第二个)。为了避免这个问题,你可以使用stopSelf(INT),以确保您的要求停止该服务总是基于最新的启动请求。也就是说,当你调用stopSelf(INT),您通过启动请求的ID(该startId交付给onStartCommand())贵停止请求对应。如果服务接收到一个新的开始要求你能打电话之前stopSelf(INT),则该ID将不匹配,该服务将不会停止。

注意:重要的是,您的应用程序停止其服务时,它的完成工作,避免浪费系统资源和消耗电池电量。如果有必要,其他部件可以通过调用停止服务stopService()。即使您启用服务绑定,必须始终自行停止该服务,如果它曾经接到一个电话到onStartCommand()

有关服务的生命周期的更多信息,请参见下面有关管理服务的生命周期。

创建绑定服务

绑定的服务是一个允许应用程序组件通过调用绑定到它bindService()以创造一个长期的连接(一般不会允许组件开始通过调用它startService())。

当你想从活动和其他组件在应用程序或暴露你的一些应用程序的功能到其他应用程序,通过进程间通信(IPC)的服务进行交互,你应该建立一个绑定的服务。

要创建一个绑定服务,必须实现onBind()回调方法返回的IBinder定义与服务通信的接口。然后,其他应用程序组件可以调用bindService()来检索界面,并开始调用服务方法。该服务只生活服务绑定到它的应用程序组件,因此在没有绑定到的服务组件,系统破坏它(你没有需要必须在服务启动时的方式停止绑定服务通过onStartCommand())。

要创建一个绑定的服务,你必须做的第一件事就是定义指定客户端如何与服务通信的接口。服务和客户端之间的这种接口必须的一个实现的IBinder和是什么服务必须从返回onBind()回调方法。一旦客户机接收到的IBinder,它可以开始通过该接口的服务进行交互。

多个客户端可以结合到服务于一次。当客户端完成与服务交互,它调用unbindService()解除绑定。一旦没有绑定到服务的客户端,系统会破坏该服务。

有实现绑定服务多种方式和实现比启动服务的更多复杂,所以绑定服务的讨论出现在大约一个单独的文件绑定服务。

将通知发送给用户

一旦运行后,服务可以通知使用事件的用户敬酒通知或状态栏通知。

Toast通知是片刻然后消失当前窗口的表面上出现一则消息,而状态栏通知提供了一条消息,用户可以以采取行动选择状态栏(这样的图标作为启动活动)。

通常情况下,一个状态栏通知是最好的技术时,一些后台的工作已经完成(如文件下载完成)和用户现在可以采取行动。当用户选择从展开图的通知时,该通知可以开始一个活动(例如,以查看下载的文件)。

见敬酒通知或状态栏通知开发者指南获取更多信息。

运行在前台服务

前台服务是被认为是东西服务的用户正在积极了解并因此不会对系统杀死时内存不足的候选人。前台服务必须为状态栏,这是摆在“持续”的标题,这意味着该通知不能被解雇,除非该服务停止或从前台删除的通知。

例如,从服务播放音乐的音乐播放器应设置在前台运行,因为用户是明确地知道它的操作。在状态栏中的通知可能表明当前歌曲,并允许用户启动的活动与音乐播放器进行交互。

请求您的服务在前台运行,调用startForeground()。这种方法有两个参数:一个唯一标识的通知和一个整数的通知状态栏。例如:

Notification notification =  new  Notification ( R . drawable . icon , getText ( R . string . ticker_text ),     System . currentTimeMillis ()); Intent notificationIntent =  new  Intent ( this ,  ExampleActivity . class ); PendingIntent pendingIntent =  PendingIntent . getActivity ( this ,  0 , notificationIntent ,  0 ); notification . setLatestEventInfo ( this , getText ( R . string . notification_title ),     getText ( R . string . notification_message ), pendingIntent ); startForeground ( ONGOING_NOTIFICATION_ID , notification );

注意:你给整数IDstartForeground()不能为0。

要从前台服务,请致电stopForeground()。此方法需要一个布尔值,指示是否可以取消状态栏通知为好。这种方法虽然不能停止服务。但是,如果你停止服务,而它仍然在前台运行,则该通知也将被删除。

有关通知的详细信息,请参阅创建状态栏通知。

管理服务生命周期

服务的生命周期比一个活动要简单得多。然而,它更重要的是你要密切关注如何您的服务创建和销毁,因为服务可以在用户不知道的后台运行。

服务生命周期 - 从当它创建时,它的破坏,可以遵循两条不同的路径:

  • 已启动的服务

    当另一个组件调用创建服务startService()。然后服务将无限期运行,必须通过调用自行停止stopSelf()。另一个组件还可以通过调用停止服务stopService()。如果该服务停止,系统破坏它..

  • 绑定的服务

    当另一个组件(客户端)调用创建服务bindService()。然后,客户端通过一个服务进行通信的IBinder接口。客户端可以关闭通过调用连接unbindService()。多个客户端可以结合到相同的服务,当它们全部取消绑定,则系统会破坏该服务。(该服务并没有需要自行停止。)

这两条路径都没有完全分开。也就是说,你可以绑定到已经启动与服务startService()。例如,一个背景音乐服务可以通过调用启动startService()意图标识音乐播放。以后,可能当用户想要实行一些控制播放器或获取有关当前歌曲的信息,一个活动可以通过调用绑定到服务bindService()。在这种情况下,stopService()stopSelf()实际上并没有停止服务,直到所有客户端解除绑定。

实施生命周期回调

就像一个活动,一个服务具有可以实现监控服务的状态变化,并在适当的时候进行的工作生命周期回调方法。下面的骨骼服务演示每个生命周期方法:

公共  ExampleService  延伸 服务 {   INT mStartMode ;     //指示如何表现,如果该服务被杀害  的IBinder mBinder ;    //接口结合客户  布尔mAllowRebind ;  //指示onRebind是否应使用  @覆盖  公共 无效 的onCreate() {     / /正在创建的服务  }   @覆盖  公共 INT  onStartCommand意向意图 诠释旗帜 INT startId  {     //该服务正在启动,由于到呼叫startService()    返回 mStartMode ;   }   @覆盖  公共 的IBinder  onBind意向意图 {     //客户端绑定到的服务bindService()    返回 mBinder ;   }   @覆盖  公共 布尔 onUnbind意向意图 {     //所有客户端绑定与unbindService()    返回 mAllowRebind ;   }   @覆盖  公共 无效 onRebind意向意图 {     //客户端绑定到的服务bindService()     //后onUnbind()已经被调用  }   @覆盖  公共 无效 的onDestroy() {     //该服务不再使用,被销毁  } }

注:与活动生命周期回调方法,你是不是需要调用父类执行这些回调方法。

图2.服务生命周期。左边的图显示了当服务与创建的生命周期()startService和右边的图显示了生命周期时创建服务bindService()

通过实施这些方法,你可以监视服务生命周期的两个嵌套循环:

  • 整个生命周期服务的情况发生的时间之间的onCreate()被调用,时间的onDestroy()的回报。就像一个活动,服务确实在它的初始设置的onCreate(),并释放所有剩余资源的onDestroy()。例如,音乐播放服务可以创造一个音乐将播放线程的onCreate(),然后停止在线程的onDestroy()

    OnCreate()中的onDestroy()方法调用所有服务,无论他们是通过创建startService()bindService()

  • 活动寿命服务的开始到呼叫或者onStartCommand()onBind()。每个方法都交到意图传递给任何startService())bindService(分别。

    如果该服务已启动,活动结束寿命的同时,整个生命周期结束(该服务仍处于活动状态即使onStartCommand()返回)。如果该服务被约束,有效使用期限结束时onUnbind()的回报。

注意:虽然开始服务由到一个呼叫停止stopSelf()stopService(),不存在用于该服务的相应的回调(没有的onStop()回调)。所以,除非服务绑定到客户端,系统破坏它,当服务是stopped-的onDestroy()收到的唯一的回调。

图2示出了用于服务的典型回调方法。虽然这一数字分离由创建的服务startService()从那些创建bindService(),请记住,任何服务,不管它是如何开始的,可能会允许客户端绑定到它。所以,这最初开始与服务)onStartCommand((由客户端调用startService())仍可以接收到呼叫onBind()(当客户端调用bindService())。

有关创建提供绑定服务的更多信息,请参阅绑定服务文档,其中包括有关的更多信息onRebind()中的有关部分回调方法管理一个绑定服务的生命周期。


更多相关文章

  1. android学习指南(2)-应用程序的基本要素
  2. Android应用程序换肤实现系列(一)
  3. Android应用程序进程启动过程的源代码分析(1)

随机推荐

  1. jdbc使用PreparedStatement批量插入数据
  2. SQL Server2019数据库之简单子查询的具有
  3. SQL Server中交叉联接的用法详解
  4. SqlServer 垂直分表(减少程序改动)
  5. sqlserver2017共享功能目录路径不可改的
  6. SQLServer2019 数据库的基本使用之图形化
  7. SQLServer2019 数据库环境搭建与使用的实
  8. SQL SERVER中常用日期函数的具体使用
  9. SQLServer 日期函数大全(小结)
  10. SQLServer2019配置端口号的实现