Service官方教程(2)*IntentService与Service示例、onStartCommand()3个返回值的含义。

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

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

  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.

  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.

Caution: A service runs in the same process as the application in which it is declared and in the main thread 
of that application,
by default. So, if your service performs intensive or blocking operations while the user
interacts with an activity from the same application, the service will slow down activity performance. To avoid
impacting application performance, you should start a new thread inside the service.
默认情况下:服务就在定义它的进程的主线程里,如果费时操作要启动个新线程。
android:process="xxx"情况下:创建新进程。

  Traditionally, there are two classes you can extend to create a started 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.
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.

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

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

  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.
    创建一个独立线程开始工作。
  • Creates a work queue that passes one intent at a time to your onHandleIntent() implementation, so you never have to worry about multi-threading.
    创建工作队列,不用担心多线程。
  • Stops the service after all start requests have been handled, so you never have to call stopSelf().
    自动停止服务,不用手动stopSelf(startId);
  • 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.
    默认就把intent发送到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.)

  Here's an example implementation of IntentService:

 1 public class HelloIntentService extends IntentService {
 2 
 3   /**
 4    * A constructor is required, and must call the super IntentService(String)
 5    * constructor with a name for the worker thread.
 6    */
 7   public HelloIntentService() {
 8       super("HelloIntentService");
 9   }
10 
11   /**
12    * The IntentService calls this method from the default worker thread with
13    * the intent that started the service. When this method returns, IntentService
14    * stops the service, as appropriate.
15    */
16   @Override
17   protected void onHandleIntent(Intent intent) {
18       // Normally we would do some work here, like download a file.
19       // For our sample, we just sleep for 5 seconds.
20       try {
21           Thread.sleep(5000);
22       } catch (InterruptedException e) {
23           // Restore interrupt status.
24           Thread.currentThread().interrupt();
25       }
26   }
27 }

  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.

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

1 @Override
2 public int onStartCommand(Intent intent, int flags, int startId) {
3     Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
4     return super.onStartCommand(intent,flags,startId);
5 }

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

  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.

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

  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.

 1 public class HelloService extends Service {
 2   private Looper mServiceLooper;
 3   private ServiceHandler mServiceHandler;
 4 
 5   // Handler that receives messages from the thread
 6   private final class ServiceHandler extends Handler {
 7       public ServiceHandler(Looper looper) {
 8           super(looper);
 9       }
10       @Override
11       public void handleMessage(Message msg) {
12           // Normally we would do some work here, like download a file.
13           // For our sample, we just sleep for 5 seconds.
14           try {
15               Thread.sleep(5000);
16           } catch (InterruptedException e) {
17               // Restore interrupt status.
18               Thread.currentThread().interrupt();
19           }
20           // Stop the service using the startId, so that we don't stop
21           // the service in the middle of handling another job
22           stopSelf(msg.arg1);
23       }
24   }
25 
26   @Override
27   public void onCreate() {
28     // Start up the thread running the service.  Note that we create a
29     // separate thread because the service normally runs in the process's
30     // main thread, which we don't want to block.  We also make it
31     // background priority so CPU-intensive work will not disrupt our UI.
32     HandlerThread thread = new HandlerThread("ServiceStartArguments",
33             Process.THREAD_PRIORITY_BACKGROUND);
34     thread.start();
35 
36     // Get the HandlerThread's Looper and use it for our Handler
37     mServiceLooper = thread.getLooper();
38     mServiceHandler = new ServiceHandler(mServiceLooper);
39   }
40 
41   @Override
42   public int onStartCommand(Intent intent, int flags, int startId) {
43       Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
44 
45       // For each start request, send a message to start a job and deliver the
46       // start ID so we know which request we're stopping when we finish the job
47       Message msg = mServiceHandler.obtainMessage();
48       msg.arg1 = startId;
49       mServiceHandler.sendMessage(msg);
50 
51       // If we get killed, after returning from here, restart
52       return START_STICKY;
53   }
54 
55   @Override
56   public IBinder onBind(Intent intent) {
57       // We don't provide binding, so return null
58       return null;
59   }
60 
61   @Override
62   public void onDestroy() {
63     Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
64   }
65 }

  As you can see, it's a lot more work than using 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).

  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()返回值只能取下面几个值:
  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()返回后,如果service被杀死,不重启服务,直到有明确的启动服务的意图。
  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()返回后,如果service被杀死,重启服务,并调用一次onStartCommand(),但是这次的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()返回后,如果service被杀死重启服务并调用一次onStartCommand(),这个Intent是结束时的那个。

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

4.Starting a Service 启动一个service,永远不要手动调用onStartCommand()

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

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

1 Intent intent = new Intent(this, HelloService.class);
2 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()后,时如果Service并没有运行,会先创建一个。

  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.

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

Stopping a service 停止一个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().

  除非系统必需释放内存时才会停止或销毁在执行完onCommand()后还在运行的服务。

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

  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.

 停止service有两种方式:
 1,service内部 stopSelf(startId);//
 2,service外部,其它组件stopService();
 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().

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

 

posted @ 2016-09-22 16:32  f9q  阅读(503)  评论(0编辑  收藏  举报