Develop系列-API Guides-应用组件-Services

Services

Services:可在后台长时间运行,无UI界面。html

Started:android

Services经过其余组件调用startService启动,能在后台一直运行,即便启动它的组件已经销毁。通常这种服务执行特定的操做并且没有返回值,好比经过网络下载或上传一个文件,一旦操做结束,服务须要中止本身。安全

Bound:网络

Service经过其余组件调用bindService绑定,提供一个CS架构的接口容许其余组件与Service交互、发消息、获取返回值、甚至跨进程通讯。bound service与绑定它的组件共存亡,多个组件能够绑定一个服务,当这个服务全部绑定它的组件都解绑后,服务会被销毁。多线程

Caution:Service在宿主进程的主线程运行,也就是说Service不会建立本身的线程,也不会运行在另外一个进程(除非你指定)。这就意味着,若是Service执行一些高CPU负载或阻塞界面操做的任务时,你须要建立新的线程来运行它,以下降ANR的风险。架构

(使用service仍是thread?若是你只是须要在与用户交互时,在主线程以外执行额外的任务,那么你须要建立一个新线程而不是Service。好比在activity在前台显示的时候播放音乐,你须要在onCreate里面建立线程,在onStart执行线程,在onStop里中止线程,固然也可使用AsyncTask或者HandleThread来替代线程类。)app

基础

建立Service的子类,覆写Service生命周期中的关键回调函数,若是有必要,提供绑定Service的机制。最重要的回调函数以下:ide

onStartCommand函数

系统在其余组件调用startService启动Service时执行,以后,Service一直在后台执行。若是你实现了这个方法,那么你有责任在Service完成其工做时经过stopSelf或stopService来中止Service。(若是只是提供绑定Service,能够不用实现这个方法)oop

onBind

系统在其余组件调用bindService绑定Service时执行,在这个方法的实现中,你须要返回一个IBider接口用于clients与service交互。若是你不须要绑定,能够直接返回null

onCreate

Service第一次建立时执行,在onStartCommand和onBind以前,用于执行一次性须要初始化好的数据。

onDestroy

service销毁时执行,用于清理资源,相似线程、注册监听器,receiver等。

 

系统会在低内存时强制中止service。若是service绑定在一个有用户焦点的activity,那么它不多会被销毁;若是服务定义为在前台运行的,那么它永远不会被销毁。

在manifest定义service

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

android:name是惟一必填的属性,其余能够选填。一旦你的应用发布出去了,那么android:name永远不要再变。

为了安全性,请使用显式Intent启动或绑定服务,而不是定义filiters。若是确实容许多个服务来响应,那么请务必在Intent中经过setPackage来指定报名,以下降目标服务匹配出意外值得几率。

设置android:exported为false,能够避免其余应用启动这个服务。

建立service

Service

全部服务的基类,若是你扩展这个类,那么你可能须要建立一个新的线程,由于这个服务室在app的主线程中执行,有可能会下降activity的流畅度

IntentService

Service 的子类,经过工做线程来处理全部请求,每次处理一个。若是你的service不须要同时处理多个请求,IntentService是最佳的选择。

扩展IntentService

由于大部分服务不须要同时处理多个请求(其实是个多线程场景),IntentService是最好的推荐

IntentService工做流程以下:

  • 建立一个默认的新工做线程来执行全部分发给onStartCommand的intents
  • 建立一个工做队列来依次传递intent去执行onHandleIntent具体实现,因此不须要考虑多线程场景
  • 全部请求执行完以后,自动销毁,你不须要执行stopSelf
  • 提供默认的onBind实现:直接返回null
  • 提供onStartCommand默认实现:发送intent给工做线程执行onHandleIntent实现

实际上,你须要作的就是实现onHandleIntent,以下例子:

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

若是你须要覆写其余回调,好比onCreate、onStartCommand、onDestroy,请确保要调用父类的实现,这样IntentService才能处理工做线程的生命周期。onHandleIntent和onBind是例外。

扩展Service

若是服务须要支持多线程(而不是经过工做队列来一一处理),那么你要扩展Service来处理每个intent。

做为对比,以下代码和上面代码功能同样。

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

这个只是模拟IntentService处理,有必要的话,你能够为每个请求建立一个线程。

 

onStartCommand必须返回一个整型,这个值用来描述系统如何处理这个服务,当它被异常销毁时。

START_NOT_STICKY

若是服务执行完onStartCommand后被异常销毁,不须要从新建立服务,除非还有未处理的intents。避免服务被没必要要地启动,你的应用可以很容易地从新启动未完成的工做,选择这个。

START_STICKY

若是服务执行完onStartCommand后被异常销毁,从新建立服务并执行onStartCommand,可是不会使用发给这个服务的最后一个intent,而是经过一个null intent来执行onStartCommand,除非还有未处理的intents。这种状况比较适合不执行命令,一直在后台运行或者等待任务的媒体播放。

START_REDELIVER_INTENT

若是服务执行完onStartCommand后被异常销毁,从新建立服务,用发给这个服务的最后一个intent调用onStartCommand,其余未处理的intents依次分发。这种状况适合执行的任务须要理解恢复的场景,好比下载文件。

启动服务

startService –> onStartCommand

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

startService方法当即返回。

若是service不能绑定,只能经过startService启动,并且须要发送返回值时,能够经过建立带延迟广播的PendingIntent(用getBroadcast)来启动服务,服务能用里面的广播来分发结果。

中止服务

若是服务同步地处理多个请求,那么不能在处理完一个请求直接销毁,有可能其余的请求刚发过来或者还在处理中。为了不这种状况,你能够经过stopSelf(int)来确保关闭的服务就是刚处理完请求的,而不是其余正在处理的服务,整型参数惟一标识服务实例。

建立绑定服务

详见下一章节

发送Notifications给用户

服务一旦运行,能够经过Toast Notifications和Status Bar Notifications提醒用户。

在前台运行服务

在前台运行的服务必须提供一个状态栏的notification,来呈现运行状态,除非服务被中止或者移除,不然notification不会消失。

好比:播放音乐,在状态栏有个notification来告诉用户当前播放的歌曲,提供用户进入音乐播放器的入口

服务须要在前台运行,须要调用startForground,第一个参数是notification的惟一标示(不能为0),第一参数就是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_ID, notification);

中止在前台运行,能够调用stopForeground。

实现生命周期回调

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:不须要执行父类的实现。

 

完整的生命周期:onCreate —> onDestroy

活动的生命周期:onStartCommand/onBind —> onDestroy/onUnbind

相关文章
相关标签/搜索