學習service

Started

A service is "started" when an application component (such as an activity) starts it bycalling startService(). 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



Bound
A service is "bound" when an application component binds to it by calling bindService(). A bound service offers a client-serverinterface 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 asanother 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.
Caution: A service runs in themain thread of its hosting process—the service does not create its own threadand does not run in a separate process (unless you specify otherwise). This meansthat, if your service is going to do any CPU intensive work or blocking operations (such as MP3playback or networking), you should create a new thread within the service to do that work. By usinga separate thread, you will reduce the risk of Application Not Responding (ANR) errors and theapplication's main thread can remain dedicated to user interaction with your activities.


Caution: A services runs in the same process as the applicationin which it is declared and in the main thread of that application, by default. 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.

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

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) {
              }
          }
      }
  }
}


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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章