`

【翻译】(7)服务

 
阅读更多

【翻译】(7)服务

 

see

http://developer.android.com/guide/topics/fundamentals/services.html

 

原文见

http://developer.android.com/guide/topics/fundamentals/services.html

 

-------------------------------

 

Services

 

服务

 

Quickview

 

快速概览

 

* A service can run in the background to perform work even while the user is in a different application

 

* 一个服务可以运行在后台执行工作,即便用户在不同的应用程序中

 

* A service can allow other components to bind to it, in order to interact with it and perform interprocess communication

 

* 服务可以允许其它组件绑定到它,以便与它交互并执行进程间通信

 

* A service runs in the main thread of the application that hosts it, by default

 

* 默认,服务运行在持有它的应用程序的主线程中

 

In this document

 

本文目录

 

* The Basics 基础

* Declaring a service in the manifest 在清单中声明服务

* Creating a Started Service 创建启动的服务

* Extending the IntentService class 扩展IntentService类

* Extending the Service class 扩展Service

* Starting a service 启动服务

* Stopping a service 停止服务

* Creating a Bound Service 创建绑定服务

* Sending Notifications to the User 向用户发送通知

* Running a Service in the Foreground 在前台运行服务

* Managing the Lifecycle of a Service 管理服务的生命周期

* Implementing the lifecycle callbacks 实现生命周期回调

 

Key classes

 

关键类

 

Service

IntentService

 

Samples

 

例子

 

ServiceStartArguments

LocalService

 

Articles

 

文章

 

* Multitasking the Android Way 

 

* Android的多任务方式

 

* Service API changes starting with Android 2.0 

 

* 从Android 2.0开始服务API的更改

 

See also

 

另见

 

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

 

服务是一种应用程序组件,可以在后台执行长期运行的操作而不提供用户界面。另一个应用组件可以启动一个服务,让它继续在后台执行,即便用户切换到另一个应用程序。额外地,一个组件可以绑定到一个服务以便与之交互,甚至执行进程间通信(IPC)。例如,一个服务可以处理网络事务,播放音乐,执行文件输入输出,或与内容提供者交互,所有这些都来自于后台。

 

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()启动一个服务时,这个服务处于“被启动”状态。一旦被启动,一个服务可以无限期运行于后台,即便启动它的组件被销毁。通常,一个被启动服务执行一个单一操作,并且不会返回结果给调用方。例如,它可能通过网络下载或上传一个文件。当完成操作时,服务应该停止它自身。

 

* 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()绑定到一个服务时,这个服务处于“被绑定”状态。一个被绑定服务提供一个客户端-服务器接口,允许组件与服务交互,发送请求,获取结果,甚至用进程间通信(IPC)跨进程地完成这些事情。一个被绑定服务,仅当另一个应用程序组件绑定到它时,才会运行。多个组件可以立刻绑定到服务,但当它们都解除绑定时,服务就会被销毁。

 

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.

 

不管你的应用程序是被启动,被绑定,还是都有,任何应用程序组件都可以用与任意组件使用活动相同的方式使用服务(它甚至可以来自另一个应用程序)——通过用意图来启动它。然而,你可以在清单文件内声明服务为私有的,并拒绝来自其它应用程序的访问。在关于在清单中声明服务的章节中将更详细地讨论这一点。

 

-------------------------------

 

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

 

基础

 

-------------------------------

 

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 in onCreate(), start running it in onStart(), then stop it in onStop(). Also consider using AsyncTask or HandlerThread, instead of the traditional Thread class. See the Processes and Threading document for more information about threads.

 

如果你需要在你的主线程外执行工作,但仅当用户正在与你的应用程序交互时,那么你可能应该创建一个新线程而非服务。例如,如果你想播放一些音乐,但仅当你的活动正在运行时才播放,那么你可能在onCreate()创建一个线程,并在onStart()中运行它,然后在onStop()中停止它。另外还应该考虑AsyncTask或HandlerThread,而非传统的Thread类。关于线程的更详细信息请参见进程和线程文档。

 

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 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()与服务绑定(诸如要执行RPC)(注:RPC是远过程调用的缩写)时系统调用此方法。在你对这个方法的实现中,你必须通过返回一个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系统将强制停止一个服务,仅当内存过低而它必须回收系统资源供获取用户焦点的活动使用。如果服务被绑定到一个拥有用户焦点的活动,那么它不太可能被杀死,而如果服务被声明为在前台运行(后面会讨论),那么它将几乎从不被杀死。否则,如果服务被启动并长期运行,那么系统将在不久后降低它在后台任务列表中的位置,而服务将变得非常容易被杀死——如果你的服务是被启动的,那么你必须设计它以优雅地处理被系统重启的情况。如果系统杀死你的服务,那么当资源变得再次可用时系统会重启它(虽然这还依赖于你从onStartCommand()中的返回值,正如后面讨论的)。想获取更多关于系统可能何时销毁服务的信息,请参见进程和线程文档。

 

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:

 

为了声明你的服务,请添加<service>元素作为<application>元素的子元素。例如:

 

-------------------------------

 

<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属性是唯一必要的属性——它指定服务的类名。一旦你发布你的应用程序,你不应改变这个名称,因为如果你这么做,你可能破坏某些功能,而显式的意图用那些功能来引用你的服务(阅读博客文章,不能改变的东西)。

 

See the <service> element reference for more information about declaring your service in the 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().

 

正像活动那样,一个服务可以定义意图过滤器,允许其它组件使用隐式意图调用服务。通过声明意图过滤器,如果你的服务声明一个意图过滤器而它匹配另一个应用程序传递给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.

 

如果你打算只是私有地使用你的服务(其它应用程序无法使用它),那么你不需要(也不应该)提供任何意图过滤器。如果没有任何意图过滤器,你必须用显式指定服务类名的意图启动服务。更多关于启动服务的信息在后面会讨论。

 

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.

 

额外地,你可以确保你的服务对于你的应用程序是私有的,仅当你包含android:exported属性并把它设置为false。即使你的服务提供意图过滤器,这个属性也是有效的。

 

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

 

更多关于为你的服务创建意图过滤器的信息,请参见意图和意图过滤器文档。

 

-------------------------------

 

Creating a Started Service

 

创建一个被启动服务

 

-------------------------------

 

Targeting Android 1.6 or lower

 

目标平台是Android 1.6或更低

 

If you're building an application for Android 1.6 or lower, you need to implement onStart(), instead of onStartCommand() (in Android 2.0, onStart() was deprecated in favor of onStartCommand()).

 

如果你正在构建Android 1.6或更低的应用程序,你需要实现onStart(),而非onStartCommand()(在Android 2.0中,onStart()被废弃,用onStartCommand()取代)。

 

For more information about providing compatibility with versions of Android older than 2.0, see the onStartCommand() documentation.

 

想获取更多关于提供比2.0更旧的Android版本的兼容性,请参见onStartCommand()文档。

 

-------------------------------

 

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.

 

一个应用程序组件诸如活动可以通过调用startService()启动服务,传递一个指定服务和包含服务使用数据的意图。服务在onStartCommand()方法中接收这个意图。

 

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

 

扩展IntentService类

 

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:

 

IntentService做以下事情:

 

* 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:

 

这里是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.

   * 构造函数是必需的,并且它必须调用超类的IntentService(String)构造函数,

   * 指定工作线程的名称。

   */

  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.

   * IntentService从默认的工作线程中用启动服务的意图调用这个方法。

   * 当这个方法返回时,IntentService根据情况停止服务。

   */

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

      // 正常情况下我们应该在这里做一些工作,如下载文件。

      // 对于我们的例子,我们只要休眠5秒。

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

 

那是你需要做的所有事情:一个构造函数和一个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.

 

如果你决定还要覆盖其它回调方法,诸如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.

 // 正常情况下我们应该在这里做一些工作,如下载文件。

 // 对于我们的例子,我们只要休眠5秒。

          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

          // 使用startId停止服务,

          // 使我们不会在处理另一个工作的中途停止服务。

          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.

    // 启动运行服务的线程。

    // 注意我们创建独立的线程,因为服务通常运行在进程的主线程(注:从主线程上启动),

    // 而我们不希望主线程被阻塞。

    // 我们还使它取得后台优先级,使CPU密集的工作不会扰乱我们的用户界面。

    HandlerThread thread = new HandlerThread("ServiceStartArguments",

            Process.THREAD_PRIORITY_BACKGROUND);

    thread.start();

 

    // Get the HandlerThread's Looper and use it for our Handler 

    // 获取HandlerThread的循环器(Looper)并把它应用到我们的处理器(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

      // 对于每个启动请求,发送一个消息去启动工作并传递启动ID,

      // 这样我们就知道当我们完成工作时,我们正在停止的是哪个请求。

      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

      // 我们不提供绑定,所以返回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 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:

 

注意onStartCommand()方法必须返回一个整型。这个整型是一个值,描述系统在系统杀死它的事件中应该如何继续执行服务(正如上面讨论的,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.

 

如果系统在onStartCommand()返回后杀死服务,那么重新创建服务,并用最近传给服务的意图调用onStartCommand()。任意等待的意图依次被传递。这适合主动地执行应该立刻恢复的工作的服务,诸如下载文件。

 

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

 

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

 

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

 

例如,一个活动可以对startService()使用显式意图启动前面章节中的示例服务(HelloService):

 

-------------------------------

 

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()方法立刻返回而Android调用服务的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()传递的意图是应用个程序组件与服务之间唯一的通信模式。然而,如果你希望服务发送结果回来。那么客户端可以启动一个服务,该服务创建获取广播(使用getBroadcast())的PendingIntent并把它传递给启动服务的意图内的服务。然后服务可以使用广播传递结果。

 

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.

 

启动服务的多请求导致对服务的onStartCommand()方法的多次相应的调用。然而,只有一个停止服务的请求(使用stopSelf()或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()的请求,那么当你完成处理一个启动请求时,你不应停止服务,因为你可能曾经接收一个新的启动请求(在首个请求的最后停止,将终止第二个请求)。为了避免这个问题,你可以使用stopSelf(int)确保你的请求停止服务总是基于最近的启动请求。就是说,当你调用stopSelf(int)时,你传递启动请求的ID(传递给onStartCommand()的startId)对应你的停止请求。然后如果在你能调用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.

 

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

 

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

 

你应该在你希望活动和其它应用程序组件与服务交互时,或通过进程间通信(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()回调方法中必须返回它。一旦客户端接收到IBinder,你可以通过那个接口开始与服务交互。

 

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.

 

有多种方法实现被绑定的服务,而且实现比被启动的服务更复杂,所以被绑定服务放在关于被绑定服务的单独文档中讨论。

 

-------------------------------

 

Sending Notifications to the User

 

向用户发送通知

 

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

 

一旦运行起来,一个服务可以通知事件的用户使用Toast通知或状态栏通知。

 

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

 

toast(注:吐司,烤面包片,可以想象一下吐司机长什么样子的)通知是一种短时间内出现在当前窗口的表面上然后消失的消息,而状态栏通知则是在状态栏提供图标以及一条消息,让用户可以选择以便采取行动(诸如启动活动)。

 

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通知或状态栏通知的开发者指引。

 

-------------------------------

 

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, 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()。这个方法传入一个布尔值,指示是否也移除状态栏的通知。这个方法不停止服务。然而,如果当服务正在运行于前台时你停止它,那么通知也会被移除。

 

-------------------------------

 

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(API级别5)中引入。为了在更旧版本平台上的前台运行你的服务,你必须使用以前的setForeground()方法——想获取更多关于提供向后兼容性的信息,请参见startForeground()文档。

 

-------------------------------

 

For more information about notifications, see 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()启动的服务。例如,一个背景音乐服务应该通过传入一个意图调用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:

 

类似于活动,一个服务拥有生命周期回调方法,你可以实现它们去监视服务状态的变化并在合适的时候执行工作。下面的框架服务展示每个生命周期方法:

 

-------------------------------

 

(图2的内容翻译见下)

 

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()创建服务时的生命周期。

 

-------------------------------

 

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 指示onRebind是否应该被使用

 

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

        // 服务正在启动,因为调用了startService()

        return mStartMode;

    }

    @Override

    public IBinder onBind(Intent intent) {

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

        // 用bindService()把客户端绑定到服务

        return mBinder;

    }

    @Override

    public boolean onUnbind(Intent intent) {

        // All clients have unbound with unbindService()

        // 已经用unbindService()解除所有客户端的绑定

        return mAllowRebind;

    }

    @Override

    public void onRebind(Intent intent) {

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

        // after onUnbind() has already been called

        // 用bindService()把一个客户端绑定到服务,

        // 在onUnbind()已经被调用后。

    }

    @Override

    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.

 

注意:不像回调生命周期回调方法那样,你不需要调用这些回调方法的超类实现。

 

-------------------------------

 

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

 

* 服务的整个生命期发生在onCreate()被调用与onDestroy()返回之间。如同一个活动,服务在onCreate()中完成它的初始化配置而在onDestroy()中释放所有剩余资源。例如,一个音乐回放服务可以在onCreate()里创建播放音乐的线程,然后在onDestroy()里停止该线程。

 

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

 

对于所有服务来说,onCreate()和onDestroy()方法都会被调用,不管它是被startService()还是被bindService()创建。

 

* 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()是唯一接收到的回调。

 

-------------------------------

 

(图略:

左边 / 右边:

1. 对startService()的调用 / 对bindService()的调用

2. onCreate() / onCreate()

------ 激活的生命期

3. onStartCommand() / onBind()

4. 服务正在运行 / 客户端绑定到服务

5. 服务被自己或一个客户端停止 / 所有客户端通过调用unbindService()解除绑定

6. (无) / onUnbind()

7. onDestroy / onDestroy

-------

8. 服务关闭 / 服务关闭

未被绑定的服务 / 被绑定的服务

 

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()的调用(当客户端调用bindService()时)

 

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.

 

更多关于创建提供绑定功能的服务的信息,请参见被绑定的服务的文档,在关于管理被绑定的服务的生命周期的章节中包含更多关于onRebind()回调方法的信息。

 

Except as noted, this content is licensed under Apache 2.0. For details and restrictions, see the Content License.

 

除特别说明外,本文在Apache 2.0下许可。细节和限制请参考内容许可证。

 

Android 4.0 r1 - 27 Oct 2011 21:16

 

Android 4.0 r1 - 29 Mar 2012 18:25

 

-------------------------------

 

patch:

1. Android 4.0 r1 - 29 Mar 2012 18:25

图被修改过

 

-------------------------------

 

Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.

 

(此页部分内容基于Android开源项目,以及使用根据创作公共2.5来源许可证描述的条款进行修改)


分享到:
评论

相关推荐

    维汉翻译通_维语智能翻译_免费APP下载

    3、人工翻译:维吾尔语专业译者,提供一对一高质量维汉翻译服务,翻译过程严谨,内容保密。 4、收藏功能:翻译后可以收藏维文句子、维语单词,边查边学,有助于学习维语,随时查看;建立词条收藏,高效分类高效学习...

    基于c语言实现Linux屏幕取词翻译源码.7z

    基于c语言实现Linux屏幕取词翻译源码.7z基于c语言实现Linux屏幕取词翻译源码.7z基于c语言实现Linux屏幕取词翻译源码.7z基于c语言实现Linux屏幕取词翻译源码.7z基于c语言实现Linux屏幕取词翻译源码.7z基于c语言实现...

    Windows_7_下搭建LDAP服务器并使用JNDI

    这是照着wiki翻译的,但是有人要问了什么是directory Service(目录服务)? 按照wiki的说法的话讲:在软件行业,目录就如同一个字典,他使得通过某一名称去查找绑定在该名称上的值得方式成为一种可能。有点类似Java...

    大气的翻译服务公司网站模板Html整站.zip

    1.Html 2.整站 3.zip 4.模板 5.服务公司 6.翻译 7.大气 8.网站

    维汉翻译通_维语翻译Windows电脑版1.0.0下载

    3、人工翻译:维吾尔语专业译者,提供一对一高质量维汉翻译服务,翻译过程严谨,内容保密。 4、收藏功能:翻译后可以收藏维文句子、维语单词,边查边学,有助于学习维语,随时查看;建立词条收藏,高效分类高效学习...

    雪人计算机辅助翻译(CAT) 中文-韩语版 v1.30.zip

    7. 质量检查功能:可以检查术语一致、数字校验、漏译、拼写、错别字、一句多译等等。 8. 预翻译:利用记忆库、词典、规则词典、本地术语库和在线翻译相结合等方式进行预翻译,快速生成译文。  雪人CAT韩语版既可以...

    WEB服务器工作机制由浅至深(3):【How Tomcat Works】7~9章翻译分析

    NULL 博文链接:https://sulin.iteye.com/blog/1025115

    翻译工具UTRAN.zip

    [这个软件在脑海里一直想了很久,去年做了一个简单的版本,不太让人满意,功能2、3、7没有实现,没有应对变化的能力,服务提供商的接口一换就不能用了。这次重新设计,以插件的形式来整个不同的数据来源,更加灵活,...

    rfc中文翻译

    7.参考文献 14 8. 安全性考虑 14 9.作者地址 15 10.版权声明 15 1. 介绍 随着实时传输协议(RTP)成为正式的RFC[1]发行,人们对于利用RTP实现不同的网络音视 频应用程序间互操作的兴趣也日益增长。然而,我们也注意到...

    [翻译]SQL注射技术总结文档.7z

    ====||目录||===== -------------------- 1、简介 ...7、MYSQL利用 8、服务名和配置 9、在注册表中找VNC密码 10、刺穿IDS认证 11、在MYSQL中使用char()欺骗 12、用注释躲避IDS认证 13、构造无引号的字符串

    实战Nginx高性能Web服务器

    7、高性能Web服务器Nginx的配置与部署研究(7)核心模块之主模块的非测试常用指令 内容:详解Nginx的主模块中,非测试常用指令的使用方式。 8、高性能Web服务器Nginx的配置与部署研究(8)核心模块之事件模块 内容...

    企业内部的DNS服务器构建.docx

    企业内部的DNS服务器构建 一、关于DNS 什么是DNS DNS( Domain Name System)是"域名系统"的英文缩写,是一种组织成域层次结构的计算机和网络服务命名系统,它用于TCP/IP网络,它主要是用来通过用户亲切而友好的名称...

    ACE技术论文集(已翻译为中文)

    已翻译为中文。具体如下:第1章 ACE自适配通信环境:用于开发通信软件的面向对象网络编程工具包 第2章包装外观(Wrapper Façade):用于在类中封装函数的结构型模式 第3章 IPC SAP:用于高效、可移植和灵活的网络...

    美萍vod视频点播服务器

    功能特点.(VOD是"Video on Demand"三个单词第一个字母的缩写,翻译过来是"视频点播") 1、造价低:使用普通PC服务器充当视频点播服务器,美萍VOD系统以纯软件方式实现视频流 的实时进行处理,大大节约了VOD视频点播...

    aqs中文翻译-by sushengmiyan.pdf

    java大师doug lean 在JDK1.5版本的AQS论文中文翻译。 许可:本作品的全部或部分在不为牟利或商业利益为目的的,且在第一页引述本声明及全完整引用的前提下,以数码或硬拷贝形式供个人或课堂使用的复制或分发不收取...

    基于Django和Python的Radicale-Django CalDAV服务设计源码

    本资源提供了一套基于Django和Python的Radicale-Django CalDAV服务设计源码,包含3229个文件,其中包括1139个MO翻译文件,1139个PO翻译文件,735个Python源代码文件,86个HTML页面文件,以及34个GIF图片文件。...

    Spring Security-3.0.1中文官方文档(翻译版)

    7. 安全过滤器链 7.1. DelegatingFilterProxy 7.2. FilterChainProxy 7.2.1. 绕过过滤器链 7.3. 过滤器顺序 7.4. 使用其他过滤器—— 基于框架 8. 核心安全过滤器 8.1. FilterSecurityInterceptor ...

    QTranslate.exe 单文件版

    1、谷歌翻译(Google Translator):Google(谷歌)免费的在线语言翻译服务,可即时翻译文本和网页。 2、微软百应翻译(Microsoft Bing Translator):微软翻译是一种能翻译 45+多种语言的云服务。 3、Promt:免费在线翻译...

    毕设源码-VB汽车美容管理系统(源代码+系统+外文翻译+英文文献+开题报告+任务书).rar

    本资源是一个完整的VB汽车美容管理系统,包含了源代码、系统、外文翻译、英文文献、开题报告和任务书等全套资料。该系统旨在提供一个高效、便捷的汽车美容服务管理平台,以满足现代汽车美容行业的管理需求。 **功能...

    基于Python搭建的一个多功能QQ机器人源码(聊天、翻译、点歌、闹钟、查天气等)+数据库.zip

    【资源介绍】 基于Python搭建的一个多功能QQ机器人源码(聊天、翻译、点歌、闹钟、查天气等)...7. 可以设定闹钟 8. 可以点歌 ## 未来可能加入的功能 1. 杭电信息的查询服务 2. 抢红包服务 3. 等等你可以想到的任何功能

Global site tag (gtag.js) - Google Analytics