天天看点

Service 服务

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

Service是一个长期运行在后台,并不提供界面的应用组件。其他组件可以启动一个服务,并且即使用户切换到其他的应用,该服务仍可在后台继续运行。另外,组件可以把某个服务邦定到自己,来与其交互通信,甚至包括执行进程间通信(IPC).例如,某个服务可能在处理来自后台的,网络传输,放音乐,执行文件I/O,或者与内容提供者交流.

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.

当某个应用组件调用startService()方法启动服务时,服务就处于启动态(started).一旦启动,即使启动服务的组件已销毁,该服务仍能无限的运行在后台.   一般,一个启动的服务只执行单一操作,且并不返回结果给它的调用者.比如,某服务可能下载或上传文件到网上,当操作完成,该服务应该自己停止自己.

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.

当一个应用组件调用bindService()方法,邦定服务,该服务就处理邦定态。一个邦定的服务提供一个客户端服务接口,所有的组件通过这个接口与服务交流,发送请求,获取结果,并且甚至是进程间通信。只有其他应用组件邦定到该服务,该邦定服务才运行。可以同时邦定多个组件到该服务,但只有当所有邦定的组件都松邦后,该服务才销毁。

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 and onBind() to allow binding.

虽然本文档概要的分别讨论服务的这两种类型,但你的服务是可以一起工作的—它可以在被运行(无限运行)的同时允许邦定。你只需简单的执行两个方法即可:允许组件启动它的onStartCommand()方法和允许邦定的onBind()方法.

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 an Intent. 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 about Declaring the service in the manifest.

与您的应用被开启,邦定或者同时处理开启,邦定状态无关,应用的任何组件可使用该服务(甚至是独立的其他应用),同样任何组件可使用活动—用Intent意图启动。但是,你可以在manifest文件中,将服务声明为私有,并阻止来自其他应用的访问。关于此的详细讨论,在Declaring the service in the manifest一节中。

Caution: A service runs in the main thread of its hosting process—the service does not create its own thread and does not run 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.

注意:服务运行在它的宿主进程的主线程中—服务不创建它自己的线程,并且不会运行在一个独立的进程里(除非你另有指定)。这里的意思是:如果你的服务要执行任何密集使用CPU的操作,或者阻塞操作(比如MP3回放或者网络),你应该给服务创建一个新的线程来处理那些事情。通过使用独立的线程,你将能减少应用无响应错误的风险(ANR),并且能让应用的主线程保持处理,用户与你的活动之间的交互操作.

The Basics基础

To create a service, you must create a subclass of Service (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:

要创建一个服务,你必须创建Service服务的一个子类(或者它的一个存在的子类).在您的实现中,需要复写处理服务生命周期的一些回调方法,并且在适当的条件下,提供组件邦定到服务的机制。你应该复写的最重要的回调方法是:

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.)

当其他的组件,比如某个活动,调用startService()方法请求启动服务时,系统调用这个方法.一旦这个方法执行,该服务就处于已启动状态,并且无限循环的运行在后台。如果你实现这个方法,当服务的工作处理完成后,你要负责停止这个服务.通过调用stopSelf()方法或stopService()方法。(如你只想提供邦定,你不需要实现这个方法)

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.

当其他的组件,调用bindService()方法,想邦定到该服务时,系统调用该方法。在你的本方法实现中,你必须提供一个接口返回一个IBinder,来让用户通过此接口与服务通信。你必须总是实现这个方法,但是你若不想允许邦定,那么你应该返回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.

当服务第一次被创建时系统调用本方法,执行一次设置程序(调用onStartCommand()方法或onBind()方法之前).如果该服务已经在运行,这个方法不会被调用。

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 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().

如果一个组件调用startService()方法启动了该服务(会导致调用onStartCommand()方法),那么该服务将保持运行,直到它用stopSelf()方法停止了自己,或者另一个组件调用了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.

如果某个组件调用bindService()方法创建服务(并且onStartCommand()没被调用),那该服务只有当该组件邦定到它时才运行。一旦该服务从所有的客户端解除,系统将销毁它.

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 (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 from onStartCommand(), as discussed later). For more information about when the system might destroy a service, see the Processes and Threading document.

只有当缺少内存及必须为用户的焦点活动恢复系统资源时,Android系统将强制停止一个服务。如果服务被邦定到一个捅有用户焦点的活动,那么它很少会被杀掉,并且如果该服务被声明成run in the foreground (运行在前台,后面讨论),那么该服务几乎不被杀掉。否则,如果服务开启后,长期在运行,那么随着时间的延长,系统会降低它在后台任务列表中的位置,并将变得极有可能被杀掉-如果你的服务被开启了,那么你应把它(服务)设置成完全可以由系统重启.如果系统杀掉了你的服务,一旦资源变得可能,系统将尽可能重启它(但这仍然依赖于你从onStartCommand()方法返回的值,后面讨论)。关于系统什么时候可能会销毁服务的,详细信息请看Processes and Threading文档.

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在manifest文档中声明服务

Like activities (and other components), you must declare all services in your application's manifest file.跟活动一样(及其他组件),你必须在你的应用的manifest文件中,声明所有的服务.

To declare your service, add a <service> element as a child of the <application> element. For example:要声明你的服务,需要在<application>元素加入<service>子元素.

<manifest ... >

    <application ... >    

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

    </application>

</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. The android:name attribute 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 might break some functionality where explicit intents are used to reference your service (read the blog post, Things That Cannot Change).

你可以在<service>元素中包含一些其他的属性,来定义像请求开启服务的权限和该服务应该运行的进程。android:name属性是唯一必须要求的属性—它指定了服务的类名.一旦你的应用发布了,你应不要改变这个名字,因为如果你改变了这个名字,可能会破坏那些显式的引用你的服务的功能(读取博文,一些其他不改变的东西Things That Cannot Change)。

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

更多关于在manifest中声明你的服务的信息,请参考<service> 元素索引.

Just like an activity, a service can define intent filters that allow other components to invoke the service using implicit intents. By declaring intent filters, components from any application installed on the user's device can potentially start your service if your service declares an intent filter that matches the intent another application passes to startService().

就像activity一样,服务也可以通过定义意图过滤器,让其他组件使用隐式意图来调用服务。通过声明意图过滤器,如果你声明的意图过滤器与其他应用传给startService()方法的意图相匹配,则安装在用户设备上的任何应用的组件潜在的可启动你的服务.

If you plan on using your service only locally (other applications do not use it), then you don't need to (and should not) supply any intent filters. Without any intent filters, you must start the service using an intent that explicitly names the service class. More information about starting a service is discussed below.

如果你仅让你的服务在局部使用(其他的应用不能使用它),那么你不需要提供一个意图过滤器。因为没有任何意图过滤器,你必须使用显式的指出服务类名的意图来启动该服务。下面的starting a service 中将详细讨论.

Additionally, you can ensure that your service is private to your application only if you include the android:exported attribute and set it to "false". This is effective even if your service supplies intent filters.

另外,只要你包含了属性,并设为"false",那么就能确保你的服务仅为你的应用私有。这样即使你的服务提供了意图过滤器,但你的服务仍然仅为你的应用私有.

For more information about creating intent filters for your service, see the Intents and Intent Filters document.

关于为服务创建意图过滤器,请看Intents and Intent Filters文档.

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.

其他组件调用startService()方法,并导致服务的onStartCommand()方法被调用,这就是一个启动的服务。

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 calling stopSelf(), or another component can stop it by calling stopService().

当一个服务启动后,它就捅有了独立于开启它的组件的生命周期,并且即使开启它的组件被销毁,它也可以在无限循环的运行在后台。因此当服务的工作处理完成后,它应该自己调用stopSelf()方法结束自己,或者其他的组件调用stopService()方法停止服务。

An application component such as an activity can start the service by calling startService() and passing an Intent that specifies the service and includes any data for the service to use. The service receives this Intent in the onStartCommand() method.

某个应用组件,比如activity,可以将一个包含指定服务及服务要用的任意数据的Intent意图,传给startService()方法,来启动一个服务。该服务将会在onStartCommand()方法中接收到这个Intent意图.

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 to startService(). The service receives the intent in onStartCommand(), connects to the Internet and performs the database transaction. When the transaction is done, the service stops itself and it is destroyed.

比如,假设一个活动需要保一些存数到在线数据库。这个活动可以把要保存的数据传给startService()方法,来开启一个协助服务,该服务在onStartCommand()方法接收到这个意图,连接到网上,并处理数据库交换。当交换完成,该服务停止它自己并销毁自己.

Caution: 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 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 Service that 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.

这是一个Service类的子类,它使用一个工人线程处理所有发起的服务,一次处理一个。如果你不想让你的线程同时处理多个服务,这是最好的选择。你所需要做的所有事情,是实现onHandleIntent()方法。在这个实现中接收每个发起请求的意图,以便你做些后台处理。

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 the IntentService class.

因为多数启动的服务不需要同时处理多个请求(实际上同时处理多个请求的情况是多线程),所以可能用IntentService这个类,来实现你的服务是最好的选择。

The IntentService does the following:这个类处理如下事情:

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

创建一个独立于你应用的主线程的工作线程,在这个工作线程中处理所有传给onStartCommand()方法的意图

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

创建一个工作队列,每次传一个意图给你的onHandleIntent()方法实现,所以你永不必担心多线程的问题

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

在所有发起的请求处理完后停止服务,所以你永不必调用stopSelf()方法.

Provides default implementation of onBind() that returns null.

提供一个默认的onBind()方法的实现,该实现返回null.

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

提供一个默认的onStartCommand()方法的实现,来发送意图到工作队列,然后(由工作队列)发到你的onHandleIntent()方法的实现

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

所有这些都基于:实现onHandleIntent()方法,来处理客户端的请求的工作。(因此,你还需要为服务提供一个小构造器).

Here's an example implementation of IntentService:

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.

      long endTime = System.currentTimeMillis() + 5*1000;

      while (System.currentTimeMillis() < endTime) {

          synchronized (this) {

              try {

                  wait(endTime - System.currentTimeMillis());

              } catch (Exception e) {

              }

          }

      }

}

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

If you decide to also override other callback methods, such as onCreate(), onStartCommand(), or onDestroy(), be sure to call the super implementation, so that the IntentService can properly handle the life of the worker thread.

所有你需要做的是:一个构造器和一个onHandleIntent()方法的实现.

如果你还想要复写其他的回调方法,比如onCreate(), onStartCommand(), onDestroy(),。确保调用了超类实现,以便IntentService类可以正确处理工作线程的生命周期.

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

比如,onStartCommand()方法必须返回默认实现(这是意图传递到onHandleIntent()方法的途径)

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

    Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();

    return super.onStartCommand(intent,flags,startId);

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

除了onHandleIntent()方法之外,onBind()方法是唯一不需要调用的超类的方法(但如果你的服务允许邦定,你只需实现它)

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

在下面的部分,你将明白当继承了Service基类时,怎样实现相同的服务;这种方代码稍多一些,但是如果需要处理同时发起的多个请求,这种方式可能理适合您。

Extending the Service class继承服务Service类

As you saw in the previous section, using IntentService makes 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 the Service class to handle each intent.

就如上面你所看到的,使用IntentService类,你可以简单的启动服务。但,若要求你的服务处理多线程(不是用一个工作队列来处理启动请求),那么可以继承Service类来处理每个意图.

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

通过比较,下面的例子是实现Service类,与上面使用IntentService类处理的工作完全相同。对于每个发起的请求,它使用一个工作线程执行工作,并且每次只处理一个.

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.

          long endTime = System.currentTimeMillis() + 5*1000;

          while (System.currentTimeMillis() < endTime) {

              synchronized (this) {

                  try {

                      wait(endTime - System.currentTimeMillis());

                  } catch (Exception e) {

                  }

          // Stop the service using the startId, so that we don't stop

          // the service in the middle of handling another job

          stopSelf(msg.arg1);

  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);

  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;

  public IBinder onBind(Intent intent) {

      // We don't provide binding, so return null

      return null;

  public void onDestroy() {

    Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();

As you can see, it's a lot more work than using IntentService.如你所见,它比使用IntentService类,要做的事多很多。

However, because you handle each call to onStartCommand() 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).

然而,因为你可自己处理每个对onStartCommand()的调用,所以你可以同时执行多个请求。这段例子没有那样做,但是如果你想要那样做,那么可以为每个请求创建一个新线程,并且以正确的方法运行它。(而不是等到前一个请求执行完成.)

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

注意,方法必须返回一个整数值。这个整数值,描述了在系统杀掉本服务的情况下,系统应该如何继续该服务(如上所讨论的,IntentService类的默认实现为你处理了这个事情,但你也可以修改它)。从onStartCommand()该方法返回的值必须是下面常量中的一个.

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 your service when not necessary and when your application can simply restart any unfinished jobs.

在onStartCommand()返回后,如果系统杀掉了该服务,除非有挂起的意图要传送,系统不重创建服务。这是避免不必运行你的服务,及你的应用可以简单的重新开始没有完成的工作时的一种安全的选择。

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. This is suitable for media players (or similar services) that are not executing commands, but running indefinitely and waiting for a job.

     在onStartCommand()返回后,如果系统杀掉了该服务,重创建服务并调用onStartCommand()方法,但是不传递最后的意图.而是系统传一个null,给调用的onStartCommand().除非有挂起的意图启动服务,那样的话,这些意图被传送。这适用于类于多媒体播放器的服务,它们不需要执行命令,但是要无限运行并等待工作。

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.

在onStartCommand()返回后,如果系统杀掉了该服务,重新创建服务并调用onStartCommand()方法,并将最后一个传给服务的意图传给onStartCommand()方法。这适合那要立即恢复并积极主动执行工作的服务,比如下载文件。关于这个返回值的详细情况,请看每个常量链接引用的文档

Starting a Service启动服务

You can start a service from an activity or other application component by passing an Intent (specifying the service to start) to startService(). The Android system calls the service's onStartCommand() method and passes it the Intent. (You should never call onStartCommand() directly.)

你可以通过将一个Intent意图传给startService()方法,从某个活动或其他应用组件中启一个服务.Android系统将调用服务的onStartCommand()方法,并将一个Intent意图传给它。(你应该永远不要直接调用onStartCommand()方法)

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

例如,一个活动可以给startService()方法一个显式意图,启动前的例子服务程序.

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

startService(intent);

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().

startService()方法立即返回,并且系统会调用onStartCommand()方法,如果服务没有正在运行,系统首先调用onCreate(),方法,然后调用onStartCommand()方法。

If the service does not also provide binding, the intent delivered with startService() 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 a PendingIntent for a broadcast (with getBroadcast()) and deliver it to the service in the Intent that starts the service. The service can then use the broadcast to deliver a result.

如果服务还没有邦定,使用startService()方法传送意图,是应用组件与服务通信的唯一模式.然而,如果你想要服务返回一个结果,那么启动服务的客户端,可以创建一个用于广播的PendingIntent挂起意图,并且在启动服务的Intent意图中,将这个挂起意图传给服务.然后服务就可以用这个广播来传递一个结果.

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.

对启动服务的多个请求,会相应的导致多次调用服务的方法。然而,只有一个请求停止服务(stopSelf() or stopService())请求停止它。

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 after onStartCommand() returns. So, the service must stop itself by calling stopSelf() or another component can stop it by calling stopService().

一个启动的服务必须能管理它自己的生命周期。那就是,除非系统要收复系统内存,系统不停止和销毁服务,并且在onStartCommand()方法返回后能继续运行.所以,服务必须调用stopSelf()方法停止自己,或者其他组件调用stopService()方法停止它.

Once requested to stop with stopSelf() or stopService(), the system destroys the service as soon as possible.

一旦用stopSelf()或stopService()方法,发出停止请求,系统将尽可能快的停止服务.

However, if your service handles multiple requests to onStartCommand() 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 use stopSelf(int) to ensure that your request to stop the service is always based on the most recent start request. That is, when you call stopSelf(int), you pass the ID of the start request (the startId delivered to onStartCommand()) to which your stop request corresponds. Then if the service received a new start request before you were able to call stopSelf(int), then the ID will not match and the service will not stop.

然而,如果你的服务正在同时处理多个发给onStartCommand()方法的请求,那么你不应该在处理完一个发起的请求(a start request)后停止服务,因为你可已接到一个新的发起请求(在第一个请求之后停止可能会终结第二个请求).为了避免这个问题,你可以用stopSelf(int)方法,确保你的停止服务的请求,总是基于最后发起的请求的。那就是,当你调用stopSelf(int)方法时,传一个请求停止相应的服务的ID。然后如果服务在你能调用stopSelf(int)方法之前,接收到一个新发起的请求,那么这个ID将不会匹配,并且服务将不停止.

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 calling stopService(). Even if you enable binding for the service, you must always stop the service yourself if it ever received a call to onStartCommand().

注意:当服务处理完工作后,你的应用停止它很重要,以避免浪费系统资源和消耗电池。如果必要的话,其他组件可以用stopService()方法停止它。即使你允许邦定,但如果你曾经收到一个onStartCommand()调用,你必须总是自己停止服务.

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

关于服务的生命周期限,看下面关于Managing the Lifecycle of a Service管理服务的生命周期.

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 calling startService()).

邦定服务是指:允许应用组件调用bindService()方法邦定一个服务,以建立长期的联接。(并且一般不允许组件调用startService()方法开启它。)

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 the onBind() callback method to return an IBinder that defines the interface for communication with the service. Other application components can then call bindService() 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 do not need to stop a bound service in the way you must when the service is started through onStartCommand()).

要创建一个邦定的服务,你必须实现onBind()回调方法,返回一个IBinder,它定义了与服务通信的接口。其他应用组件然后调用bindService()方法取回接口并….只有服务于邦到它的应用组件时,服务才存在,所以当没有组件邦定到服务时,系统销毁它(你不需要停止一个邦定的服务,但当服务是通过onStartCommand()方法启动时,你必须停止它).

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 of IBinder and is what your service must return from the onBind() callback method. Once the client receives the IBinder, it can begin interacting with the service through that interface.

要创建一个邦定的服务,首要的事情是,你必须定义与服务通信的接口。服务与客户端之间的这个接口,必须是一个的IBinder实现,并且这就是为什么你的服务必须从onBind()方法中返回它的原因.

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.

多个客户端可以同时邦定到一个服务。当某个客户端处理完与服务的交互工作时,它可以调用unbindService()松邦.一旦没有客户端邦定到该服务,系统就销毁该服务.

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 about Bound Services.

有许多方法去实现邦定服务,并且它有实现比启动服务复杂得多,所以单独在Bound Services中讨论邦定服务的。

Sending Notifications to the User发送通知给用户

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

当运行时,一个服务可以用Toast Notifications 或Status 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).

吐司通知(弹出的窗口像吐司面包)是一个出现在当前窗口表面的一个消息,显示一会儿然后消失,而状态条消息提一个带有消息的icon显示在状态条上,用户可以选择它,执行一个动作(比如启动一个活动)

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 the Toast Notifications or Status Bar Notifications developer guides for more information.

详细信息,请看Toast Notifications 或者 Status Bar Notifications开发指南

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.

一个前台服务是用户通过综合考虑后特别关心的一个服务,并且在缺少内存时,不是系统要杀掉的候选者。一个前台服务必须为状态条提供一个通知,放在"Ongoing"头下,这个意思是这个通知不能被扔掉,除非服务被停止或者被移到后台.

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, call startForeground(). This method takes two parameters: an integer that uniquely identifies the notification and the Notification for the status bar. For example:

要请求你的服务运行到前台,调用startForeground().方法。这个方法带两个参数:一个标识通知器的整数及状态条的Notification通知器.例如:

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, notification);

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 you stop the service while it's still running in the foreground, then the notification is also removed.

要把该服务从前台移除,调用stopForeground()方法.这个方法带有一个boolean值,表示是否同时将通知也从状态条上移除。这个方法不停止服务。但是,如果你停止一个在前台正在运行的服务,那么该通知将也被移除.

Note: The methods startForeground() and stopForeground() were introduced in Android 2.0 (API Level 5). In order to run your service in the foreground on older versions of the platform, you must use the previous setForeground() method—see the startForeground() documentation for information about how to provide backward compatibility.

注意:startForeground()和stopForeground()这个两方法是在Android 2.0中介绍进来的。为了让你的服务可以旧版本的平台上运行,你必须使用以前的setForeground()方法。关于向后兼容请看startForeground()文档.

For more information about notifications, see Creating Status Bar Notifications.

关于创建通知器,请看Creating 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 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..

该服务是其他组件调用startService()方法创建的。然后服务无限运行并且必须自己调用stopSelf()方法停止自己。其他组也可以调用stopService()方法停止它.当服务停止,系统销毁它..

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.)

该服务是其他组件调用bindService()方法开启的.客户端然后通过IBinder接口与服务通信,客户端可以调用unbindService()方法断开联接。多个客户端可以邦定到同一个服务并且当所有的客户端松邦后,系统销毁该服务(服务不需要自己停止自己)

These two paths are not entirely separate. That is, you can bind to a service that was already started with startService(). For example, a background music service could be started by calling startService() with an Intent that 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 calling bindService(). In cases like this, stopService() or stopSelf() does not actually stop the service until all clients unbind.

这两种方法并不是完全分开的。你可以邦定一个服务到一个用startService()方法开启的服务.比如,通过调用一个带有指定播放音乐的Intent意图的startService()方法,开启一个后台音乐播放服务.后来,用户可能想要对播放器做一些控制或者想获取关于当前音乐的信息,一个活动可以调用bindService()方法邦定到该服务.在像这样的情况下,stopService()或者stopSelf()方法不能真正停止服务,除非所有的客户端解除邦定.

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

    }

    public int onStartCommand(Intent intent, int flags, int startId) {

        // The service is starting, due to a call to startService()

        return mStartMode;

    public IBinder onBind(Intent intent) {

        // A client is binding to the service with bindService()

        return mBinder;

    public boolean onUnbind(Intent intent) {

        // All clients have unbound with unbindService()

        return mAllowRebind;

    public void onRebind(Intent intent) {

        // A client is binding to the service with bindService(),

        // after onUnbind() has already been called

    public void onDestroy() {

        // The service is no longer used and is being destroyed

Note: Unlike the activity lifecycle callback methods, you are not required 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 with startService() and the diagram on the right shows the lifecycle when the service is created with bindService().

图2.服务的生命周期,图的左边演示的是用startService()方法创建的服务的生命周期,图的右边演示的是用bindService()方法创建的服务的生命周期.

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

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

The entire lifetime of a service happens between the time onCreate() is called and the time onDestroy() returns. Like an activity, a service does its initial setup in onCreate() and releases all remaining resources in onDestroy(). For example, a music playback service could create the thread where the music will be played in onCreate(), then stop the thread in onDestroy().

The onCreate() and onDestroy() methods are called for all services, whether they're created by startService() or bindService().

服务的整个的生命时间,发生在onCreate()方法被调用时和onDestroy()方法返回时.与活动一样,服务在onCreate()方法中执行初始化操作,并在onDestroy()方法中释放保持的资源.比如,音乐回放服务可能在onCreate()方法中创建播放音乐线程,并在onDestroy()方法中停止线程.无论它们由startService() 或者bindService()创建,所有服务都会调用onCreate()和onDestroy()方法.

The active lifetime of a service begins with a call to either onStartCommand() or onBind(). Each method is handed the Intent that was passed to either startService() or bindService(), respectively.

服务的激活生命时间,开始于对onStartCommand()方法或onBind()方法的调用.每个方法相应的处理传给startService()方法或者bindService()方法的Intent意图.

If the service is started, the active lifetime ends the same time that the entire lifetime ends (the service is still active even after onStartCommand() returns). If the service is bound, the active lifetime ends when onUnbind() returns.

如果服务是开启的,该激活生命时间的结束时间同整个生命时间一样(即使onStartCommand()方法返回了,服务仍然是激活的)。如果服务是结束邦定的,激活的生命时间结束于onUnbind()方法返回.

Note: Although a started service is stopped by a call to either stopSelf() or stopService(), there is not a respective callback for the service (there's no onStop() 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.

注意:虽然一个开启的服务可能通过调用stopSelf()或者stopService()方法停止,但服务没有与此相应的回调方法(没有onStop()回调)。除非服务邦定到一个客户端,否则当服务停止时系统就销毁它—onDestroy() 方法是唯一回调接收方法.

Figure 2 illustrates the typical callback methods for a service. Although the figure separates services that are created by startService() from those created by bindService(), 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 with onStartCommand() (by a client calling startService()) can still receive a call to onBind() (when a client calls bindService()).

图2说明了一个服务的典型回调方法,虽然该图把服务以由方法创建startService() 的和由bindService()方法创建的分开了,但请记住,不管服务是如何创建的,都能允许客户端邦定到它。所以,用onStartCommand()方法初始化的服务(客户端调用startService()),仍能接收一个onBind()方法的调用。

For more information about creating a service that provides binding, see the Bound Services document, which includes more information about the onRebind() callback method in the section about Managing the Lifecycle of a Bound Service.

关于创建提供邦定的服务的详细信息,看Bound Services文档,在那里的Managing the Lifecycle of a Bound Service一节,有更多关于onRebind() 回调方法的更详细信息.

上一篇: web service
下一篇: 远程互访

继续阅读