Android面试系列之【Service你要的都在这里】
1、启动方式和区别
-
startService
其他组件调用startService()
启动一个Service。一旦启动,Service将一直在后台运行,即时启动这个Service的组件被销毁。通常startService会在后台执行单独的操作,并不需要和启动它的组件交互。只有当Service自己调用stopSelf()
或者其他组件调用stopService()
才会终止。 -
bindService
其他组件还可以通过bindService()
的方法来绑定一个Service。可以通过调用Service内部方法,也可以提供组件与Service交互的接口,进行扩进程通信(IPC)。这种方式会让Service和启动它的组件绑定一起,当启动它的组件被销毁,Service也会自动进行unBind操作。同时一个Service可以被多个组件绑定,只有所有绑定它的组件都进行了unBind()
操作,这个Service才会被销毁 -
混合启动模式
当播放音乐的时候,需要调用startService()
启动指定的音乐,又需要获取该音乐的播放进度的时候,又需要调用bindService()
。该方式保证了Service可长期在后台运行,还可让调用者远程调用Service中提供的方法。在这种情况下,除非Service被unBind,在此之前stopService()
和stopSelf()
都不能停止该服务
Service不同的启动方式有不同的生命周期与回调方法,
startService()
启动Service会回调onStartCommand()
,bindService()
绑定Service会回调onBind()
。
无论哪种方式启动Service,任何组件都可以使用Service(甚至其他的应用程序的组件),并通过Intent传递参数。你可以在
AndroidMenifest.xml
中将android:exported="false"
Service配置成私有的,不允许其他应用访问。这样配置不允许其他应用程序启动本应用的Service,即便是显示的Intent也不行。
2、生命周期
找了一个神图这个基本上初级程序员都会学习到的,就不述说了。来说说重点吧!
- 完整生命周期:从
onCreate()
到onDestroy()
返回。和Activity类似,一般在onCreate()
方法中做一些初始化的工作,在onDestroy()方法中做一些资源释放的工作。如若Service在后台播放一个音乐,就需要在onCreate()
方法中开启一个线程启动音乐,并在onDestroy()
中结束线程。- 活动生命周期:从
onStartCommand()
或onBind()
回调开始,由相应的startService()
或bindService()
调用。start 方式的活动生命周期结束就意味着完整证明周期的结束,而 bind 方式,当onUnbind()
返回后,Service 的活动生命周期结束。
注意
- 无论是
startService()
还是bindService()
启动Service,onCreate()
和onDestroy()
均会被调用且只会被执行一次。onStartCommand()
可以执行多次,也就是说一旦Service创建过了,而又没有被销毁的话, 不管是再次调用bindService还是startService都不会再走onCreate()
,onBind()
也只会执行一次,多次调用startService会多次执行onStartCommand()
- Service中的
onBind()
方法返回null的话,无法回调ServiceConnection
3、AndroidManifest里Service的常见属性说明
属性 | 说明 | 备注 |
---|---|---|
android:name | 类名 | |
android:enabled | 系统默认启动 | 不设置则默认为false默认为true,被系统启动。适用于四大组件 |
android:label | 名字 | 若不设置,默认为Service类名 |
android:icon | 图标 | |
android:permission | 申请此Service的权限 | 有提供了该权限的应用才能控制或连接此服务 |
android:process | 是否在另一个进程中运行(远程服务) | 不设置默认为本地服务,remote则设置成远程服务 |
android:exported | 是否能够被其他应用程序所控制或连接 | 不设置默认为false |
4、如何提高service的优先级
1、在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = “1000”这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同时实用于广播。
2、在onStartCommand里面调用 startForeground()方法把Service提升为前台进程级别,然后再onDestroy里面要记得调用stopForeground ()方法。
3、onStartCommand方法,手动返回START_STICKY。
4、 在onDestroy方法里发广播重启service。
service +broadcast 方式,就是当service走ondestory的时候,发送一个自定义的广播,当收到广播的时候,重新启动service。(第三方应用或是在setting里-应用-强制停止时,APP进程就直接被干掉了,onDestroy方法都进不来,所以无法保证会执行)
5、监听系统广播判断Service状态。
通过系统的一些广播,比如:手机重启、界面唤醒、应用状态改变等等监听并捕获到,然后判断我们的Service是否还存活。
6、Application加上Persistent属性。
5、Service的onStartCommand()方法有几种返回值?
-
START_STICKY: 如果 service 进程被 kill 掉,保留 service 的状态为开始状态,但不保留递送的 intent 对象。随 后系统会尝试重新创建 service,由于服务状态为开始状态,所以创建服务后一定会调用
onStartCommand(Intent,int,int)
方法。如果在此期间没有任何启动命令被传递到 service,那么参数 Intent 将为 null。 -
START_NOT_STICKY: 非粘性的”。使用这个返回值时,如果在执行完
onStartCommand()
后,服务被异常 kill 掉,系统不会自动重启该服务。 -
START_REDELIVER_INTENT: 重传 Intent。使用这个返回值时,如果在执行完
onStartCommand()
后,服务被异 常 kill 掉,系统会自动重启该服务,并将 Intent 的值传入。 - START_STICKY_COMPATIBILITY: START_STICKY 的兼容版本,但不保证服务被 kill 后一定能重启。
6、Service的onRebind(Intent)方法什么时候会执行?
如果在 onUnbind()
返回true的情况下会执行,否则不执行。
调用过程:
1、启动服务 onCreate()
,onStartCommand()
方法被回调;
2、绑定服务 onBind()
方法被回调;
3、 解绑服务(可以调用 unBindService()
方法,或退出绑定Service的Activity组件) onUnbind()
方法被回调;
4,重新绑定服务 (eg:再次进入该Activity,调用bindService方法绑定服务) onRebind(Intent)
方法被回调。
7、你一般在什么情况下会使用Service?
-
经验总结:
Service其实就是背地搞事情,又不想让别人知道,举一个生活当中的例子,你想知道一件事情不需要直接去问,你可以通过侧面了解。这就是Service设计的初衷 -
Service为什么被设计出来?
根据Service的定义,我们可以知道需要长期在后台进行的工作我们需要将其放在Service中去做。说得再通熟易懂一点,就是不能放在Activity中来执行的工作就必须得放到Service中去做。如:音乐播放、下载、上传大文件、定时关闭应用等功能。这些功能如果放到Activity中做的话,那Activity退出被销毁了的话,那这些功能也就停止了,这显然是不符合我们的设计要求的,所以要将他们放在Service中去执行。