- Service简单概述
- Service在清单文件中的声明
- Service启动服务实现方式及其详解
- Service绑定服务的三种实现方式
- 关于启动服务与绑定服务间的转换问题
- 前台服务以及通知发送
- 服务Service与线程Thread的区别
- 管理服务生命周期的要点
- Android 5.0以上的隐式启动问题及其解决方案
- 保证服务不被杀死的实现思路
1.Service简单概述
服务时可以长时间在后台运行并且没有界面的应用组件。服务一旦被启动将一只会在后台运行,即使启动它的组件被销毁也不会受到影响,它还可以与组件进行绑定,也可以进行IPC通信
- 启动状态
当应用组件通过startService启动服务时,服务将一直在后台运行,除非用户主动停止它,已启动的服务通常是执行单一操作,而且不会将结果返回给调用方。
- 绑定状态
当调用bindService时服务就处于绑定状态,绑定服务提供了一个客户端-服务器的接口,允许组件进行交互,发送请求,获取结果,甚至进行IPC通信,前提是要跟另一个应用的组件绑定,服务才会运行。如果一个服务同时绑定了多个组件,那么而当这些组件全部取消绑定后服务也会被销毁。
2.Service在清单文件中的声明
- android:exported:
能否被其他应用隐式调用,默认值由intent-filter决定,在false的情况下即使intent-filter匹配也无法被打开。
- android:name:
服务的名称
- android:permission:
权限声明
- android:process:
是否要在单独的进程中运行,:remote和remote是不一样的,带有【:】的进程名是APP包名:remote,不带有【:】的则为remote
- android:isolatedProcess:
设置为true是意味着将在一个特殊的进程下运行,这个进程与系统其它进程分开且没有自己的权限。
- android:enabled:
是否可以被实例化
3.Service启动服务实现方式及其详解
创建一个类继承自Service,重写以下方法:
- onBind()
当另一个组件想通过bindService与服务绑定时,系统将调用此方法,此方法在实现中必须返回一个IBinder接口的实现类,供客户端与服务端通信,无论在启动状态还是绑定状态都必须重写但是启动状态时返回null。
- onCreate()
如果服务已经在运行了则不会执行该方法,否则首次启动服务时一定会执行,在里面主要做一些一次性的设置程序
- onStartCommand()
当另一个组件通过调用startService()请求启动服务时,系统就调用此方法,服务就会启动并且在后台保持无限期运行。如果自己实现这个方法那就要记得在工作完成后调用stopSelf()或者stopService()来停止服务。会执行无数次
- onDestory()
服务的最后一个调用方法,当服务不再继续使用且即将被销毁时系统将调用此方法。
- onStartCommand(Intent intent, int flags, int startId)
-
- intent
启动时传递过来的intent
-
- flags
表示启动时有额外数据,可选值有0,START_FLAG_REDELIVERY,START_FLAG_RETRY
-
-
- 0:代表没有
- START_FLAG_REDELIVERY:这个值代表了onStartCommand的返回值为,START_REDELIVERY_INTENT,而且在上一次服务被杀死前会调用stopSelf方法停止服务,其中START_REDELIVERY_INTENT代表当Service因内存不足被杀死后会重建服务,并通过传递给服务的最后一个Intent调用startCommand(),此时Intent是有值的。
- START_FLAG_RETRY:当onStartCommand一直没有返回值时,会尝试重新调用onStartCommand。
-
-
- startId
指明当前服务的唯一ID,与stopSelfResult(int startId)配合使用,stopSelfResult可以更安全的停止服务。
4.Service绑定服务的三种实现方式
- 扩展Binder类
如果服务是提供给自有应用专用的并且服务端与客户端在同一个进程中运行,则应该扩展Binder类并从onBind中返回它的一个实例来创建接口。客户端收到Binder后可利用它直接访问Binder实现中以及service中可用的公共方法。
- 使用Messenger
查看第二章总结
- AIDL
查看第二种总结
5.关于启动服务与绑定服务间的转换问题
- 先绑定服务后启动服务
如果当前service实例先以绑定状态运行,再以启动状态运行那么绑定服务将会转为启动服务,这时如果之前绑定的宿主销毁了,服务是不会受到影响的,直到收到停止服务或者内存不足时才会销毁。
- 先启动服务后绑定服务
如果当前service实例先以运行状态运行再以绑定状态运行,当前启动服务是不会转为绑定服务的,但是还是会与宿主绑定,即使宿主解除绑定后,还是会以启动服务的生命周期运行,直到Context调用了stopService()或是服务本身调用了stopService()方法会内存不足时才会销毁服务。
6.前台服务以及通知发送
7.服务Service与线程Thread的区别
- Thread是CPU的最小单元,Android系统中UI线程也是线程的一种,Thread还可以用来做一些耗时异步操作;Service是一种机制主要运行在主线程上,是由系统进程托管,与其他组件之间的通相当于客户端和服务端,是一种亲量级的IPC通信,通信的在提示binder;
- 在Android系统中,线程一般指的是工作线程,即后台线程,主线程是一种特殊的工作线程,它负责将事件分发给用户界面小工具,如绘图操作,这是诺伊尔耗时的操作,主线程是不建议这么做的,因此这个任务就要交给Thread主去做了;service是Android中的组件,运行在主线程中,因此不可以做一些耗时操作,否则会保ANR异常,service是后台服务,因为它没有界面,用户是无法感知的,如果需要执行一些耗时任务那就需要在里面单独开启线程。
- 当要耗时网络或者数据查询以及其他阻塞UI或密集使用CPU的任务时都应该使用Thread,这样才能保证UI线程不被占用从而影响用户体验;在应用程序中需要长时间运行并且不需要交互的情况下使用。
8.管理服务生命周期的要点
startService:onCreate→onStartCommand→onDestory
bindService:onCreate→onBind→onUnBind→onDestory
无论是绑定服务还是启动服务,onCreate和onDestory都会执行;
服务的有效生命周期是从onStartCommand和onBind开始的,每种方法都有Intent对象,该对象分别传递到startService()和bindService()
对于启动服务有效生命周期与整个生命周期同时结束,对于绑定服务,有效生命周期在onUnBind返回时就结束了。
- 启动服务
通过startService启动服务后,服务将会无限期的运行,除非用户自行调用stopSelf或者通过其他组件调用stopService,服务停止后系统将其销毁
- 绑定服务
其他客户端通过bindService创建,然后客户端通过IBinder接口与服务进行通信,客户端可以通过unbinderService关闭连接,多个客户端可以同时绑定一个服务,当所有绑定取消后,系统将其销毁。
9.保证服务不被杀死的实现思路
服务被杀死有几种个能:
- 系统资源不足被杀死:
系统资源不足时被杀死的服务会调用onDestory,在onSestory中发送一个广播重启就可以了
- 用户手动杀死:
可以开启两个服务,相互监听,相互启动