aoi学院

Aisaka's Blog, School of Aoi, Aisaka University

Android-四大组件-Service

开启服务和绑定服务的区别/优缺点

开启服务:startService() → stopService()(其生命周期为onCreate() → onStartCommand() → onDestroy())

绑定服务:bindService() → unBindService()(其生命周期为onCreate() → onBind() → onUnbind() → onDestroy())

区别:startService()可以长期在后台运行,bindService()不可以在后台长期运行;bindService()启动服务可以跟服务进行通讯,startService()启动服务不可以跟服务进行通讯。

解决方法:混合两种启动方式,先startService()再bindService(),这样又可以长期运行又可以跟服务进行通讯。


Service混合开启模式

生命周期:

  1. 开启服务 → 绑定服务,如果不取消绑定,则无法停止服务

  2. 开启服务 → 多次绑定/解绑服务,服务不会被停止,只能通过stopService()来停止服务

推荐的混合开启服务的方式:

  1. 开启服务 → 为了确保服务可以长期处于后台

  2. 绑定服务 → 为了可以进行通讯

  3. 调用服务的内部方法,例如控制音乐的播放/暂停/停止/快进。

  4. 退出Activity,要记得解绑服务 → 释放资源

  5. 若不使用服务了,要让服务停止,那么就调用stopService()


Android服务(Service)

服务是一个后台运行的组件,执行长时间运行且不需要用户交互的任务,即使应用被销毁也依然可以工作。因此,服务适合执行一段时间不需要显示界面的后台耗时操作(需要另启子线程),比如下载网络数据、播放音乐等。

Service并不是运行在一个独立的进程当中,而是依赖于创建服务时所在的应用程序进程,即Service运行在主线程中。当某个应用程序被杀掉时,所有依赖于该进程的服务都会停止运行。

Service并不会自动开启线程,所有的代码都是默认允许在主线程当中的,也就是说需要在服务的内部手动创建子线程,并在里面执行具体的任务,否则就会出现主线程被阻塞的情况。

服务适用场景:

  1. 下载网络数据(在Android3.0之后,只支持子线程下载,因此此功能应该在子线程中启动服务)

  2. 播放音乐。

  3. 访问文件、数据库等一些业务逻辑功能,可以让Service来实现。

服务基本上包含两种状态:

Started:Android的应用程序组件,如活动,通过startService()启动了服务,则服务是Started状态。一旦启动,服务可以在后台无限期运行,即使启动它的组件已经被销毁。

Bound:当Android的应用程序组件通过bindService()绑定了服务,则服务是Bound状态。Bound状态的服务提供了一个客户服务器接口来允许组件与服务进行交互,如发送请求、获取结果,甚至通过IPC来进行跨进程通信。

服务生命周期:

服务拥有生命周期方法,可以实现监控服务状态的改变,可以在适合的阶段执行工作。左图为服务通过startService()被创建时的生命周期(onStart()被弃用,现在用onStartCommand()),右图则显示了服务通过bindService()被创建时的生命周期:

服务的回调函数:

onStartCommand():其他组件(如活动)通过调用startService()来请求启动服务时,系统调用该方法。如果你实现该方法,你有责任在工作完成时通过stopSelf()或者stopService()方法来停止服务。

onBind():当其他组件想要通过bindService()来绑定服务时,系统调用该方法。如果你实现该方法,你需要返回IBinder对象来提供一个接口,以便客户来与服务通信。你必须实现该方法,如果你不允许绑定,则直接返回null。

onUnbind():当客户中断所有服务发布的特殊接口时,系统调用该方法。

onRebind():当新的客户端与服务连接,且此前它已经通过onUnbind(Intent)通知断开连接时,系统调用该方法。

onCreate():当服务通过onStartCommand()和onBind()被第一次创建的时候,系统调用该方法。该调用要求执行一次性安装。

onDestroy():当服务不再有用或者被销毁时,系统调用该方法。你的服务需要实现该方法来清理任何资源,如线程,已注册的监听器,接收器等。


BUG修改

应用调起第三方支付的模拟alipay服务进行支付(该demo写完有bug,绑定alipay服务失败)

BUG原因:

Android 8.0版本对后台服务做了更加严格的限制(官方Android 8.0更新文档:后台执行限制)

“后台Service限制:处于空闲状态时,应用可以使用的后台 Service 存在限制。 这些限制不适用于前台 Service,因为前台 Service 更容易引起用户注意。”

“在这些情况下,后台应用将被置于一个临时白名单中并持续数分钟。 位于白名单中时,应用可以无限制地启动 Service,并且其后台 Service 也可以运行。”

解决方法:

  1. 把alipay这个Service加入系统的服务白名单

  2. 这个demo降低SDK版本运行(在24版本即Android 7.0版本下运行正常)