四大组件——Service使用详解

时间:2021-08-18 10:32:17

Service

  1. 概念:
    Service是一个可以在后台执行长时间运行操作而不提供用户界面的应用组件。服务可由其他应用组件启动,组件可以 绑定服务 ,以与之交互,甚至是执行进程间通信(IPC)。注意: 仅当内存过低且必须回收系统资源时,系统才会强制停止服务。
  2. 作用:
    服务可以处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序交互,而所有这一切均可在后台进行

  3. 开启形式:

    1. 启动:
      当应用组件通过调用startService()启动服务时,服务即处于启动状态。这种方式启动的服务,会在后台无限期运行,即使启动服务的组件已经被销毁,服务也不受影响,直到操作完成,服务才会自动停止运行。已经启动的服务通常执行单一操作,不会将结果返回给调用方。

    2. 绑定:
      当应用组件通过调用bindService()绑定到服务时,服务即处于绑定状态,绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至是利用进程间通信(IPC)跨进程执行这些操作(交互、发送请求、获取结果)。多个组件可以同时绑定到该服务,全部取消绑定后,该服务即会被销毁。

    3. 注意:
      同一个服务既允许startService(),也允许bindService(),也可以同时 使用者两种,关键在于你的服务是否实现了一组回调方法:onStartCommand()(允许组件启动服务)、onBind()(允许绑定服务)。
  4. 启动服务的两种形式

    1. 形式一:创建启动服务: 两种方式:可以扩展两个类来实现创建启动服务
      1. 继承Service:
        继承Service类,在实现中需要重写一些重要的回调方法 以处理生命周期的某些关键方面并提供一种机制将组件绑定到服务。需要重写的重要回调方法包括:
        1. onStartCommand():
          当一个组件(如Activity)通过调用startService()请求启动服务时,系统会调用此方法。一旦执行此方法,服务即会启动并在后台无限期运行。如果实现了此方法,则在服务完成工作 后,需要调用Service的stopSelf()或者其他组件通过调用stopService() 来停止服务。(如果只想使用bindService()则不需要实现此方法)。onStartCommand()返回一个整型数,用于描述系统应如何在服务终止的情况下继续运行服务,返回值必须是一下常量之一:
          1. START_NOT_STICKY:
            除非有挂起的intent,否则不会重建服务。
          2. START_STICKY:
            重建服务时不会重新传递最后一个intent,除非有挂起的intent,否则会通过一个空的intent启动,
          3. START_REDELIVER_INTENT:
            系统在调用onStartCommand()返回后终止服务,则会重建服务,并通过传递给服务的最后一个Intent调用onStartCommand(),任何挂起的Intent都会依次传递。这适用于主动执行应该立即恢复的作业(如下载服务)
        2. onBind():
          当一个组件想通过bindService()与服务绑定时,系统 会回调此方法。在此方法实现中,必须通过放回IBinder提供一个接口,供客户端用来与服务器进行通信。如果不希望允许绑定,则返回null。
        3. onCreate():
          首次创建服务时会回调此方法,在onStartCommand()、onBind()方法之前调用,当服务在运行时,不再回调此方法。
        4. onDestroy():
          当服务不再使用且将被销毁时,系统将调用此方法。服务应该实现此方法来清理所有资源,如线程、注册的侦听器、接收器等。 这是服务接收的最后一个调用。
      2. 继承IntentService:
        1. 概述: 可以逐一处理所有的启动请求(非多线程)。你只需要实现onHandlerIntent()来实现客户端的工作即可。如果需要实现其他方法,需要保证调用超类的实现,以便IntnetService来管理Service的生命周期。
    2. 形式二:创建绑定服务(bindService()) 三种方式

      1. 概述:
        绑定服务是客户端-服务器接口中的服务器。绑定服务可让组件(例如 Activity)绑定到服务、发送请求、接收响应,甚至执行进程间通信 (IPC)。 绑定服务通常只在为其他应用组件服务时处于活动状态,不会无限期在后台运行。
      2. IBinder对象: Client与Service的通信接口
      3. 创建绑定服务:
        创建绑定服务的最重要的环节就是定义onBind()回调方法返回的接口,以提供服务器和客户端进行交互的编程接口。可以有一下三种方式定义接口:

        1. 方式一:扩展Binder类
          1. 概述: 当服务仅供本地应用使用,不需要跨进程工作,则可以实现自有Binder类,让客户端通过该类直接访问服务中的公共方法
          2. 使用步骤一:
            在继承Service类的内部,实现一个继承Binder的内部类,并提供一个可以返回你的Service的方法,然后再你的Service中实例
            化你继承了Binder的内部类。
          3. 使用步骤二:
            使你的Service回调onBind方法并返回你实例化了继承了 Binder类的内部类的对象。
          4. 使用步骤三:
            在绑定的客户端中,实例化ServiceConnection并在 其onServiceConnected的回调方法中接受Binder,并使用提供的方法调用绑 定的服务。
        2. 方式二:使用 Messenger(报信者):

          1. 概述:如果让服务与远程进程通信,可以使用Messenger为服务提供接口,此方法不需要使用AIDL便可实现进程间通信。
          2. 使用步骤一:
            在服务中实现一个Handler,用于处理客户端发送的请求。
          3. 使用步骤二:
            在服务器中使用Handler创建Messenger对象。
          4. 使用步骤三:
            在服务器中使用Messenger创建IBinder,在服务器的onBind()方法中将其返回给客户端。
          5. 使用步骤四:
            客户端通过IBinder对象将Messenger实例化,并通过Messenger将Message发送到服务器端。
          6. 使用步骤五:
            服务端在handler中接收并处理Message。
        3. 使用AIDL(Android Interface Definition Language:Android接口定义语言):

          1. 概述:
            你可以使用AIDL定义客户端和服务器使用IPC进行相互通信都认可的接口。通常情况下,android上,一个进程是无法访问另外一个进程的内存的,但是,进程需要将其对象分解为系统能够识别的原语,并将对象编组成跨越边界的对象,编写编组操作的代码十分复杂,因此android使用AIDL来处理。
  5. 声明Service:

    1. attribute:
      https://developer.android.google.cn/guide/topics/manifest/service-element.html#prmsn
    2. 注意: 尽量使用显示Intent启动或者绑定Service,并不要为Intent提供intent-filter,以确保应用的安全性。如果必须使用隐试,则可为服务提供intent-filter并从Intent中排除相应的组件名称,但随后必须使用setPackage()设置软件的包名,以排除目标服务的不确定性。
  6. 启动Service

    1. 通过startService(intent)启动:
    2. 通过bindService()启动:
      参考:

https://developer.android.google.cn/guide/components/services.html