目录
Q3:一个Activty先start一个Service后,再bind时会回调什么方法?此时如何做才能回调Service的destory()方法?
Q6:是否能在Service进行耗时操作?如果非要可以怎么做?
Q8:前台服务是什么?和普通服务的不同?如何去开启一个前台服务?
Q9:是否了解ActivityManagerService,谈谈它发挥什么作用?
Service:Service则是在后台运行,默默地为用户提供功能,进行调度和统筹,如果一棵树的地上部分是Activity的话,它庞大的根须就是Service。
相关文章:android编程中service和activity的区别
Q1:谈一谈Service的生命周期?
官方文档提供的Sevice生命周期图如下:
先来看这几种回调方法含义:
onCreate():服务第一次被创建时调用
onStartComand():服务启动时调用
onBind():服务被绑定时调用
onUnBind():服务被解绑时调用
onDestroy():服务停止时调用
Q2:Service的两种启动方式?区别在哪?
- startService():开启Service,调用者退出后Service仍然存在。
- bindService():开启Service,调用者退出后Service也随即退出。
Service生命周期:
- 只是用startService()启动服务:onCreate() -> onStartCommand() -> onDestory
- 只是用bindService()绑定服务:onCreate() -> onBind() -> onUnBind() -> onDestory
- 同时使用startService()启动服务与bindService()绑定服务:onCreate() -> onStartCommnad() -> onBind() -> onUnBind() -> onDestory
Q3:一个Activty先start一个Service后,再bind时会回调什么方法?此时如何做才能回调Service的destory()方法?
一个Activty先start一个Service后,再bind时会调用 onBind()方法。
此时调用onUnBind()方法才能回调Service的destory()方法。注意:调用stopService()方法是不行的。
Q4:Service如何和Activity进行通信?
可以通过bindService的方式,先在Activity里实现一个ServiceConnection接口,并将该接口传递给bindService()方法,在ServiceConnection接口的onServiceConnected()方法里执行相关操作。
Q5:用过哪些系统Service?
参考文章:Android系统服务(SystemService)简介
Q6:是否能在Service进行耗时操作?如果非要可以怎么做?
不可以。
Service和activity是运行在当前app所在的main thread(UI主线程)中的,而耗时操作(如:网络请求、拷贝数据、大文件)会阻塞主线程,给用户不好的体验。
如果要做耗时操作的话,有两种方式:
第一种:Thread。无非就是开一个线程,然后一阵混沌操作。当然,你还可以使用 AysncTask 或 HandlerThread 来替代 Thread 创建线程。
第二种:IntentService 。
IntentService是Service的子类,用来处理异步请求。
IntentService在onCreate()方法中通过HandlerThread单独开启一个线程来处理Intent请求对象所对应的任务,这样可以避免事务处理阻塞主线程。
onHandleIntent()函数针对Intent的不同进行不同的事务处理就可以,执行完一个Intent请求对象所对应的工作之后,如果没有新的Intent请求达到,则自动停止Service; 否则ServiceHandler会取得下一个Intent请求
传入该函数来处理其所对应的任务。
Q7:AlarmManager能实现定时的原理?
AlarmManager是Android中常用的一种系统级别的提示服务,在特定的时刻为我们广播一个指定的Intent。简单的说就是我们设定一个时间,然后在该时间到来时,AlarmManager为我们广播一个我们设定的Intent,通常我们使用 PendingIntent,PendingIntent可以理解为Intent的封装包,简单的说就是在Intent上在加个指定的动作。在使用Intent的时候,我们还需要在执行startActivity、startService或sendBroadcast才能使Intent有用。而PendingIntent的话就是将这个动作包含在内了。
Q8:前台服务是什么?和普通服务的不同?如何去开启一个前台服务?
前台服务和普通服务最大的区别是,前者会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏后可以看到更加详细的信息,非常类似于通知的效果。使用前台服务或者为了防止服务被回收掉,比如听歌,或者由于特殊的需求,比如实时天气状况。
想要实现一个前台服务非常简单,它和之前学过的发送一个通知非常类似,只不过在构建好一个Notification之后,不需要NotificationManager将通知显示出来,而是调用了startForeground()方法。
Q9:是否了解ActivityManagerService,谈谈它发挥什么作用?
ActivityManagerService(AMS)是Android中最核心的服务,主要负责系统中四大组件的启动、切换、调度及应用程序的管理和调度等工作。
AMS所提供的主要功能包括以下几项:
1、统一调度个应用的程序的Activity。应用程序要运行Activity,会首先报告AMS,然后由AMS决定该Activity是否可以启动,如果可以,AMS再通知应用程序指定的Activity。换句话说说运行Activity时各应用程序的内政,AMS并不干预,但是AMS必须知道各应用程序都运行了哪些Activity。
2、内存管理。Android官方声称,Activity退出后,其所在的进程并不会被立即杀死,从而在下次启动该Activity时能够提高启动速度,这些Activity只有当系统内存紧张时,才会被自动杀死,应用程序并不关心这些问题,这些都是在AMS中完成的。
3、进程管理,AMS向外提供了查询系统正在运行的进程信息的API。
Q10:如何保证Service不被杀死?
第一个回答:
在onDestory()中发送广播开启自己,当然,从理论上来讲这个方案是可行的,实验一下结果也是可行的。但是有些情况下,发送的广播在消息队列中排的靠后,就有可能服务还没有接收到广播就销毁了(只是猜想)。所以为了能让这个机制完美运行,可以开启两个服务,相互监听,相互启动。服务A监听B的广播来启动B,服务B监听A的广播来启动A。经过实验,这个方案是可行的。
第二个回答:
1. onStartCommand方式中,返回START_STICKY
首先我们来看看onStartCommand都可以返回哪些值:
调用Context.startService方式启动Service时,如果Android面临内存匮乏,可能会销毁当前运行的Service,待内存充足时可以重建Service。而Service被Android系统强制销毁并再次重建的行为依赖于Service的onStartCommand()方法的返回值。
-
START_NOT_STICKY
如果返回START_NOT_STICKY,表示当Service运行的进程被Android系统强制杀掉之后,不会重新创建该Service。当然如果在其被杀掉之后一段时间又调用了startService,那么该Service又将被实例化。那什么情境下返回该值比较恰当呢?
如果我们某个Service执行的工作被中断几次无关紧要或者对Android内存紧张的情况下需要被杀掉且不会立即重新创建这种行为也可接受,那么我们便可将 onStartCommand的返回值设置为START_NOT_STICKY。
举个例子,某个Service需要定时从服务器获取最新数据:通过一个定时器每隔指定的N分钟让定时器启动Service去获取服务端的最新数据。当执行到Service的onStartCommand时,在该方法内再规划一个N分钟后的定时器用于再次启动该Service并开辟一个新的线程去执行网络操作。假设Service在从服务器获取最新数据的过程中被Android系统强制杀掉,Service不会再重新创建,这也没关系,因为再过N分钟定时器就会再次启动该Service并重新获取数据。 -
START_STICKY
如果返回START_STICKY,表示Service运行的进程被Android系统强制杀掉之后,Android系统会将该Service依然设置为started状态(即运行状态),但是不再保存onStartCommand方法传入的intent对象,然后Android系统会尝试再次重新创建该Service,并执行onStartCommand回调方法,但是onStartCommand回调方法的Intent参数为null,也就是onStartCommand方法虽然会执行但是获取不到intent信息。如果你的Service可以在任意时刻运行或结束都没什么问题,而且不需要intent信息,那么就可以在onStartCommand方法中返回START_STICKY,比如一个用来播放背景音乐功能的Service就适合返回该值。 - START_REDELIVER_INTENT
如果返回START_REDELIVER_INTENT,表示Service运行的进程被Android系统强制杀掉之后,与返回START_STICKY的情况类似,Android系统会将再次重新创建该Service,并执行onStartCommand回调方法,但是不同的是,Android系统会再次将Service在被杀掉之前最后一次传入onStartCommand方法中的Intent再次保留下来并再次传入到重新创建后的Service的onStartCommand方法中,这样我们就能读取到intent参数。只要返回START_REDELIVER_INTENT,那么onStartCommand重的intent一定不是null。如果我们的Service需要依赖具体的Intent才能运行(需要从Intent中读取相关数据信息等),并且在强制销毁后有必要重新创建运行,那么这样的Service就适合返回START_REDELIVER_INTENT。
2.提高Service的优先级
在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = "1000"这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同时适用于广播。
3.提升Service进程的优先级
当系统进程空间紧张时,会依照优先级自动进行进程的回收。
Android将进程分为6个等级,按照优先级由高到低依次为:
- 前台进程foreground_app
- 可视进程visible_app
- 次要服务进程secondary_server
- 后台进程hiddena_app
- 内容供应节点content_provider
- 空进程empty_app
可以使用startForeground将service放到前台状态,这样低内存时,被杀死的概率会低一些。
4.在onDestroy方法里重启Service
当service走到onDestroy()时,发送一个自定义广播,当收到广播时,重新启动service。
5.系统广播监听Service状态
6.将APK安装到/system/app,变身为系统级应用