Service 详解

     网上关于service的各种阐述五花八门。有些带有很深的写作者的主观理解,如果写作者有一点偏颇的话,对阅读者容易造成云深雾里的感觉。其实读api 一切都描述的很详细,这是一篇service的api 文档。 每一段我都会翻译过来 。

A Service is an application component that can perform long-running operations in the background and does not provide a user interface. Anotherapplication component can start a service and it will continue to run in the background even if theuser 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, allfrom the background

 Service 是一个能够处理后台长期运行操作的组件,并且它不提供用户界面。其他组件能够启动一个服务,即使用户切换到其他应用上去,这个服务也会继续在后台运行,除此之外 其他组件和这个service进行交互或者进程间通信可以通过绑定的方式。例如,一个服务能够处理网络事务,音乐播放,处理文件的I/O,或者和content provide 进行交互,所有的这些都在后台运行。

A service can essentially take two forms:

基本上一个服务能采用两种方式:

Started 方式:

A service is "started" when an application component (such as an activity) starts it by callingstartService(). Once started, a servicecan 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, theservice should stop itself。

一个服务被其他应用组件(例如activity)启动通过调用startService();一旦启动,这个服务会无限期的运行在后台,即使启动它的那个组件已经被销毁了。通常个start方式的启动的服务处理一个单一的操作而且不会给调用者返回结果。例如:通过网络上传或者下载网络。当操作完成时,这个服务会自动停止。

Bound 方式:

A service is "bound" when an application component binds to it by callingbindService(). A bound service offers a client-server interface that allows components to interact with the service, send requests, get results, and evendo 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 andonBind() to allow binding.

尽管这个文档大致分别讨论了这两种类型的service ,但是你的服务能够同时两种方式的工作——能够启动(Started) 这个服务(无限期的运行)的同时也允许绑定。这种简单做法取决于你是否去实现一对回调方法:onStartCommand()允许组件去start 这个服务,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 anIntent. However, you can declarethe service as private, in the manifest file, and block access from other applications. This is discussed more in the section aboutDeclaring the service in themanifest.


无论你的应用是started ,bound或者两者都用,任何应用组件都能够用到这个服务(甚至别的其他的应用),和其他组件使用一个activity相同的方式--通过一个Intent 来启动它。当然了 你可以在Manifestfile中声明这个服务为私有,这样能阻止其他应用访问它,这个详细的讨论在后面的Declaring the service in themanifest.中。


Caution: A service runs in the main thread of its hosting process—the service doesnot create its own thread and doesnot 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 play back 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错误的风险,应用的主线程也会继续用作和activity用户交互操作。

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


创建一个服务,你必须创建一个service(或者Service 已经存在的子类)的子类。在实现的过程中,你需要适当的重载几个回调方法,这些回调方法是处理service生命周期的关键环节,而且它们提供了组件绑定services的一个机制。大部分必须重载的回调方法有:

onStartCommand()

The system calls this method when another component, such as an activity,requests that the service be started, by callingstartService(). 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 callingstopSelf() orstopService(). (If you only want to provide binding, you don't need to implement this method.)
    当其他组件,例如一个activity ,通过调用StartService()来请求服务的启动时 系统调用这个方法,一旦这个方法执行,服务就会启动并且在后台无止境的运行下去。如果你实现这个方法,当它的工作完成时你将有责任通过调用stopSelf()或者stopService()方法来关闭这个服务。(如果你只是想绑定服务,你不需要去实现这个方法)


onBind()
The system calls this method when another component wants to bind with the service (such as to perform RPC), by callingbindService(). In your implementation of this method, you must provide an interface that clients use to communicate with the service, by returning anIBinder. You must always implement this method, but if you don't want to allow binding, then you should return null.
 当其他组件通过调用bindService()来绑定service(就像是操作RPC)的时候系统调用这个方法,如果你实现这个方法,你必须提供一个客户端界面通过返回一个IBinder来和服务器进行交流,这个方法是必须实现的,如果你不想绑定这个方式,那么你可以返回一个null。 onCreate()
The system calls this method when the service is first created, to perform one-time setup procedures (before it calls eitheronStartCommand() oronBind()). 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 toonStartCommand()), then the service remains running until it stops itself withstopSelf() or anothercomponent stops it by callingstopService().

如果一个组件通过调用startService()(导致调用onStartCommand()方法)来启动一个服务,那么这个服务会持续运行,直到它自己通过stopSelf()来停止服务,或者其他组件通过调用stopService()来停止服务


If a component calls bindService() to create the service (andonStartCommand() isnot 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 positionin the list of background tasks over time and the service will become highly susceptible to killing—if your service is started, then you must design it to gracefully handle restarts by the system. If the system kills your service, it restarts it as soon as resources become available again (though this also depends on the value you return fromonStartCommand(), as discussed later). For more information about when the system might destroy a service, see theProcesses and Threading document.



android系统会在内存低的情况下强制停止服务,这样是恢复系统资源为用户焦点所在的activity。如果一个服务被一个处于焦点的activity绑定,那么它不太可能会被杀死,如果这个服务被声明在前台运行(后面会讨论),那么它几乎不会被杀死。否则如果这个服务是被启动的而且是正在长时间运行,那么随着时间的推移系统会降低后它在台任务列表中的位置,而且这个服务会变得非常容易被杀死--如果 你的服务已经启动了,那么你必须设计的优雅去处理被系统重启。如果系统杀死了你的服务,当资源变的可用的时候服务会立刻重启(尽管这也取决于从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

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:

像activity(其他的组件),一样,你必须在你的应用的manifestfile 中声明所有的services,声明的方式就是,添加一个<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. Theandroid:nameattribute is the only required attribute—it specifies the class name of the service. Once you publish your application, you should not change this name, because if you do, you might break some functionality where explicit intents are used to reference your service (read the blog post, ThingsThat Cannot Change).

可以在<service>元素中添加其他的属性来定义服务的特性例如启动服务需要的权限,和服务所运行在的线程。android:name属性是唯一需要的属性--它指定了服务的类名称,一旦你发布了你的应用,你就不能改变这个名称,因为如果你修改的话,你会破坏了反应你应用明确意图的功能(读这个博客,ThingsThat Cannot Change);


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

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


关于在manifest中声明你的服务可以去看<service>元素参考 获得更多的信息。


就像是activity一样,一个服务能定义意图过滤器,允许其他的组件通过隐式的意图来访问这个服务。通过声明意图过滤器,安装在用户手机的上任何应用的组件能够潜在的启动你的服务,如果你的服务定义了一个其他应用传递给startService()意图的意图过滤器


If you plan on using your service only locally (other applications do not use it), then youdon'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 informationabout starting a service is discussed below.

如果你的服务仅仅是局部的(其他的应用不能够使用它),那么你不必要(不应该)提供任何意图过滤器,没有任何意图过滤器,你必须用一个有明确服务类的意图来启动你的服务,更多的关于启动一个服务的信息会在后面讨论。


Additionally, you can ensure that your service is private to your application only ifyou include theandroid:exportedattribute and set it to"false". This is effective even if your service supplies intentfilters


除此之外,如果你的服务包括android:exported属性而且它的值设置为“false” 那么你能够确保你的服务队你的应用来说是私有的,即使是你的服务提供了意图过滤器 这也是有效的

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

关于为你的服务创建意图过滤器的更多的信息,请参照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'sonStartCommand() method.

一个启动的服务是有其他组件通过调用startService()方法启动,致使调用服务的onstartCommand()方法;


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

当一个服务被启动之后,它的生命周期独立于启动它的那个组件,服务会无止境的运行于后台,即使启动它的那个组件已经被销毁,因此当服务的工作完成之后 服务应该调用自身的stopself()方法或者其他组件调用stopService()方法来停止服务


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


一个像activity这样的应用组件能够通过调用startServie()方法其他服务,它会传递一个指定service和包含任意为服务去使用的数据的意图。服务在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 tostartService(). The service receives the intent inonStartCommand(), connects to the Internet and performs thedatabase transaction. When the transaction is done, the service stops itself and it isdestroyed.


例如,假设一个activity 需要向一个在线数据库保存一些数据,这个activity 就可以启动一个与之相应的服务 并且通过传递意图到startService()的方式把数据交付给服务去保存,服务在instartCommand()方法中接收这些意图,连接到网络并处理这个数据库操作,当这些操作完成之后,服务自动关闭,并且会被销毁掉



Caution: AA services runs in the same process as the applicationin which it is declared and in the main thread of that application, by defaul. So, if your serviceperforms intensive or blocking operations while the user interacts with an activity from the sameapplication, the service will slow down activity performance. To avoid impacting applicationperformance, 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 thatyou create a new thread in which to do all the service's work, because the service uses yourapplication's main thread, by default, which could slow the performance of any activity yourapplication is running.
这个是所有服务的基类,当你继承这个类的时候,创建一个线程去做服务上的操作是非常重要的,因为这个服务默认用的是你的应用的主线程,这样会降低任何运行在你应用上的界面的性能

IntentService
This is a subclass of Service that uses a worker thread to handle allstart requests, one at a time. This is the best option if you don't require that your servicehandle multiple requests simultaneously. All you need to do is implement onHandleIntent(), which receives the intent for eachstart request so you can do the background work.

这个是一个用一个工作线程一次一个的处理所有的启动请求的service 的子类,如果你不要求你的服务同时处理多个请求这是最好的选择,你所做的就是去实现onHandleIntent(),它接收每次请求的意图,所以你可以做后台工作


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


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 youimplement your service using theIntentService class.

The IntentService does the following:

  • Creates a default worker thread that executes all intents delivered to onStartCommand() separate from your application's mainthread.
  • Creates a work queue that passes one intent at a time to your onHandleIntent() implementation, so you never have toworry about multi-threading.
  • Stops the service after all start requests have been handled, so you never have to callstopSelf().
  • Provides default implementation of onBind() thatreturns null.
  • Provides a default implementation of onStartCommand() that sends the intent to the work queue and then to your onHandleIntent() implementation.

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


因为大多数被启动的服务都不需要去处理同时多个请求(这其实是一个危险的多线程场景),用IntentS而voice类来实现你的服务大概是最好的方式

ItentService做以下几步:

1,创建一个区别与你应用主线程的工作线程来执行所有交付给onstartCommand()方法的意图

2,创建一个工作每次交一个意图给onhandlerIntent去执行的工作队列,所以你不用去担心多线程。

3,当所有的请求被处理完之后停止这个服务,所以你不用去调用stopSelf()

4,默认实现返回null 的onbind方法

5默认实现onstartCommand方法,这个方法会发送意图到工作队列中,接着会被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(), oronDestroy(), be sure to call the super implementation, sothat theIntentService can properly handle the life of the worker thread.

你所需需要的是:一个构造方法和一个onhandleIntent的实现

如果你想要去重写其他的回调方法 ,例如oncreate ,onstartConmand 或者on destory,一定要确保调用super实现,这样IntentService能够妥善处理工作线程的生命周期

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


例如onstartCommand必须返回默认的执行(就是意图怎样被交付到onhandleIntent()中去Besides onHandleIntent(), the only methodfrom which you don't need to call the super class is onBind() (but you only need to implement that if your service allows binding).)


@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 methodfrom which you don't need to call the super class is onBind() (but you only need to implement that if your service allows binding).


除了onhanleIntent外 唯一不需要调super类的方法是onbind(但是如果你的服务运行绑定的话 只需要实现这个方法)


Extending the Service class

As you saw in the previous section, using IntentService makes yourimplementation of a started service very simple. If, however, you require your service toperform multi-threading (instead of processing start requests through a work queue), then youcan extend theService class to handle each intent.

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

就像是你看到的一样,用IntentSevice使你实现一个启动的服务非常的简单,但是如果你要求你的服务去处理多线程(不是通过工作队列处理启动请求) 那么你可以继承service类来处理每一个意图


作为比较 下面的例子代码是一个实现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);
      }
  }

  @Override
  public void onCreate() {
    // Start up the thread running the service.  Note that we create a
    // separate thread because the service normally runs in the process's
    // main thread, which we don't want to block.  We also make it
    // background priority so CPU-intensive work will not disrupt our UI.
    HandlerThread thread = new HandlerThread("ServiceStartArguments",
            Process.THREAD_PRIORITY_BACKGROUND);
    thread.start();
    
    // Get the HandlerThread's Looper and use it for our Handler 
    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
      Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();

      // For each start request, send a message to start a job and deliver the
      // start ID so we know which request we're stopping when we finish the job
      Message msg = mServiceHandler.obtainMessage();
      msg.arg1 = startId;
      mServiceHandler.sendMessage(msg);
      
      // If we get killed, after returning from here, restart
      return START_STICKY;
  }

  @Override
  public IBinder onBind(Intent intent) {
      // We don't provide binding, so return null
      return null;
  }
  
  @Override
  public void onDestroy() {
    Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); 
  }
}

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

如你所见,这个比I用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 aninteger. The integer is a value that describes how the system should continue the service in theevent that the system kills it (as discussed above, the default implementation forIntentService handles this for you, though you are able to modify it). The return valuefromonStartCommand() must be one of the followingconstants:

注意 onstartcommand方法必须返回一个整形的数,这个数值描述了在系统杀死它的事件中系统如何继续这个服务(像上面讨论的一样,默认的IntentService实现已经为你处理了尽管你也能够改变这个它) 这个返回的值必须是包含在下面:

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 方法,但并不会重新传递最后的意图,相反 系统会用一个空的意图来调用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 theservice. Any pending intents are delivered in turn. This is suitable for services that areactively performing a job that should be immediately resumed, such as downloading a file.

如果系统杀死这个服务在onstartCommand返回之后,重建这个服务,调用onstartcommand方法传递最后被分配给这个服务的意图,任何未完成的意图依次被传过来,这个那种处理能够立刻被回复的工作的服务。类似于下载一个文件


Starting a Service

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


你能够通过一个activity或者其他应用组件传入一个Intent(指定服务去启动)到startService()来启动一个服务,android系统会调用服务的onstartCommand方法并且把intent传过去(你不能直接调用onstartCommand方法)



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

例如,一个activity能够启动前面这个示例服务(HelloService)在startService里用一个明确的intent

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

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

这个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 theapplication component and the service. However, if you want the service to send a result back, thenthe client that starts the service can create a PendingIntent for a broadcast(withgetBroadcast()) and deliver it to the servicein theIntent that starts the service. The service can then use thebroadcast to deliver a result.


如果服务不提供绑定,传递给startService()的intent是应用组件和它启动的服务通信的唯一的模式,如果你i想你的服务返回一个结果,那么启动这个服务的客户端能够一个广播(通过getBroadcast)创建一个pendingIntent 并且通过intent把它传递给服务,这个服能够用广播传递这个结果。



Multiple requests to start the service result in multiple corresponding calls to the service'sonStartCommand(). However, only one request to stopthe service (with stopSelf() orstopService()) is required to stop it.


多个请求启动服务导致相应的多个请求服务的onstartcommand 然后要求停止这个服务的话 只需要一个请求即可



Stopping a service

A started service must manage its own lifecycle. That is, the system does not stop or destroy the service unless it must recover system memory and the service continues to run afteronStartCommand() returns. So,the service must stop itself by callingstopSelf() or anothercomponent can stop it by callingstopService().

Once requested to stop with stopSelf() orstopService(), the system destroys the service as soon aspossible.

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 usestopSelf(int) to ensure that your request tostop the service is always based on the most recent start request. That is, when you callstopSelf(int), you pass the ID of the start request (thestartIddelivered to onStartCommand()) to which your stop requestcorresponds. 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.

Caution: It's important that your application stops its serviceswhen it's done working, to avoid wasting system resources and consuming battery power. If necessary,other components can stop the service by callingstopService(). Even if you enable binding for the service,you must always stop the service yourself if it ever received a call toonStartCommand().

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


一个启动的服务必须管理自己的生命周期,这就是说系统不会停止或者销毁一个服务,除非这个服务回收了系统的内存并且在onstartCommand返回之后继续运行,所以服务只能通过调用stopself来停止自己或者其他组件调用stopservice来停止服务

一旦用stopself或者stopservice来停止服务,系统会立刻销毁这个服务

然而,如果你的服务同时处理多个请求onstartCommand,那么当你处理完一个请求之后不应该去停止这个服务,因为你可能会接到一个新的启动请求(停止结束前的第一个请求将会终止第二个),要 避免这种问题,你可以用stopSelf(int) 来保证你请求的关闭这个服务永远居于最近一次的请求启动。 这就是说 当你调用stopself(int) 你传递请求启动的id(被传给onstartCommand的启动id)给相对应的关闭请求,那么如果这个服务在你调用stopself(int) 之前接受到一个新的启动请求,那么这个id就不匹配,服务就不会关闭

注意事项:为了避免浪费系统资源和电池电量消耗,在服务完成工作后关闭它是非常重要的,如果有必要,其他的组件能够关闭这个服务通过调用stopService,即使你启动绑定这个服务,你也必须总是去关闭它 即使它接受到一个onstartcommand方法

更多信息在后面的服务的管理生命周期中会提到。


Creating a Bound Service


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

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

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

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

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

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



一个绑定的服务是为了建立一个长连接 服务允许应用组件调用bindservice来绑定它(通常情况下是不允许调用startService来启动的)

当你想要服务和activity 或者其他应用组件交互 或者你de应用想要通过进程间通信(IPC)暴露出你应用的功能给其他的应用,那么你应该建立一个绑定的服务。

建立一个绑定的服务你应该实现onbind回调方法 并且会反悔一个IBinder,这个是定义的和进程通信的接口,其他的应用组件能够通过调用bindserbice来取回这个接口,然后调用service里面的方法。这个服务依赖于绑定它的应用组件,如果没有组件去绑定这个服务,系统会销毁了它(当服务通过onstartcommand启动,你不必必须去关闭它如果它被绑定的话)


创建一个绑定的服务 第一件事情要做的就是去定义一个指定客户端和服务通信的接口,这个接口必须是从你服务的onbind放回返回的一个实现,一旦客户端接到这个Ibinder

它就可以通过这个接口立刻通服务进行通信,多个客户端能够绑定服务,当一个客户端和服务完成通信之后,它会调用unbindserbice去解绑定,一旦没有其他客户端来绑定这个服务,系统会销毁这个服务


Sending Notifications to the User


Once running, a service can notify the user of events using Toast Notifications or 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).

Usually, a status bar notification is the best technique when some background work has completed(such as a file completeddownloading) 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 Notificationsdeveloper guides for more information.


一旦运行,服务能用Toast Notifications orStatus Bar Notifications.来通知用户时间


一个Toast通知是一个出现在界面上一会 然后消失的信息,状态栏通知提供一带有图标的信息在状态栏里,用户可以选择去执行一个动作(例如启动一个activity)

通常状态栏通知是一个最好的机器当后台工作完成的时候(例如文件下载完成) 用户可以去执行一个动作当用户从扩展的界面选择这个通知的时候,通知能够启动一个activity(例如去文件下载的界面)



Running a Service in the Foreground


A foreground service is a service that's considered to be something theuser 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 theforeground, because the user is explicitly awareof its operation. The notification in the status bar might indicate the current song and allowthe 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可以请求你的服务运行在前台,这个方法带两个参数,一个int类型的唯一指定通知 ,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 theservice. However, if you stop the service while it's still running in the foreground, then thenotification is also removed.


调用stopForeGround可以从前台移除服务,这个方法有个boolean 参数,说明是否也移除状态栏通知,这个方法不会停止服务,然而如果服务在前台运行的时候停止它 通知也会被移除


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 twodifferent paths:

  • A started service

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

  • A bound service

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

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


服务的生命周期比activity简单的多,但是它更重要以至于你要付更多的注意在你的服务是怎么样创建和销毁的,因为服务是运行在后台用户看不到的。


start方式的服务

  当其他组件调用stratservice的时候创建服务,这个服务立刻运行,直到它调用stopSelf()才停止 其他组件调用stopservice也能够停止服务,当服务被停止的时候 系统会销毁它

绑定方式的服务

  当其他组件(一个客户端)调用bindservice的时候服务被创建, 这个客户端通过Ibind接口和服务通信,客户端能够通过调用unbindservice关闭连接,多个客户端能够绑定服务,当所有的解绑定的时候 系统销毁这个服务。(服务不需要去自己关闭自己)

这两个方式并不是完全独立的,也就是说你可以绑定一个已经通过startService启动的服务 例如,一个后台音乐服务能够用一个指定音乐播放的intent 通过startService启动,之后可能用户想要在播放器上做一些操作或者从当前的音乐中获得一些信息,一个activity能够通过调用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:


像activity 一样一个service也有它的生命周期回调方法,你可以实现这些方法来监控服务状态的改变或者再适当的时间处理工作,下面的service框架演示了每一个生命周期的方法


public class ExampleService extends Service {
    int mStartMode;       // indicates how to behave if the service is killed
    IBinder mBinder;      // interface for clients that bind
    boolean mAllowRebind; // indicates whether onRebind should be used

    @Override
    public void onCreate() {
        // The service is being created
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // The service is starting, due to a call to startService()
        return mStartMode;
    }
    @Override
    public IBinder onBind(Intent intent) {
        // A client is binding to the service with bindService()
        return mBinder;
    }
    @Override
    public boolean onUnbind(Intent intent) {
        // All clients have unbound with unbindService()
        return mAllowRebind;
    }
    @Override
    public void onRebind(Intent intent) {
        // A client is binding to the service with bindService(),
        // after onUnbind() has already been called
    }
    @Override
    public void onDestroy() {
        // The service is no longer used and is being destroyed
    }
}

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

注意;与activity不生命周期回调方法会不同的是,你不需要去调用这些回调方法的超类实现






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


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

      一个服务的整个一生从调用oncreate 到ondestory  就像activity 一样,服务在oncreate中进行初始化的操作,在ondestroy中释放资源,例如。一个音乐播放器会在oncreate中创建音乐播放的线程,在ondestroy中关掉这个线程

    服务的活动周期开始于调用onstartcommand或者onbind ,每一个方法都会分别处理被onstartervice或者bindservice传递的intent

   如果服务是被start的方式,这个服务的活动周期和生命周期的结束时间是一致的 (即使是在onstartcommand返回之后服务也是活动的) ,如果服务是绑定的方式 ,当inunbind返回时活动周期结束

Note: Although a started service is stopped by a call toeither stopSelf() or stopService(), there is not a respective callback for theservice (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.

注意 :尽管一个started方式的服务是通过调用stopself或者stopservice来停止服务,但是在服务中没有响应的回调(就是说没有onstop回调),所以除非服务是被绑定到一个客户端,当服务停止系统会销毁它 ondestory是唯一的回调。


Figure 2 illustrates the typical callback methods for a service. Although the figure separatesservices that are created by startService() from thosecreated by bindService(), keepin 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 callsbindService()).


上图说明了服务的典型的回调方法。尽管上图分别用onstartservice 和bindservice创建了服务,一定要牢记,任何服务 不管是怎样启动的能够潜在的允许客户端去绑定它,一个服务初始启动通过onsttartcommand(通过调用startsrvice)仍能够接受onbind的调用(当客户端调用bindservice());














































































  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值