转发:原文连接http://blog.csdn.net/mad1989/article/details/22492519java
最近项目要实现这样一个效果:运行后,要有一个service始终保持在后台运行,无论用户做出什么操做,都要保证service不被kill,这可真是一个难题。参考了现今各类定制版的系统和安全厂商牛虻软件,如何能保证本身的Service不被杀死呢?android
其实除了常规的手段,咱们能够参考一下微信和360,设置-程序-正在运行,能够看到微信是同时开启了两个进程和服务:shell
【有兴趣能够研究一下 守护进程 和 AIDL 】缓存
我猜测它应该是相互监听,若是有一方被kill掉,另外一个捕获到当即启动,以达到service永远都在运行的状态,貌似360也是这个原理,具体是否是这个样子,还有待参考,目前我尚未参透它们是如何实现的,先简单说一下我本身的防控措施吧,首先介绍一下Service概念,记性很差,重复造一下车轮,高手能够直接看最后。安全
Service是在一段不定的时间运行在后台,不和用户交互应用组件。每一个Service必须在manifest中 经过<service>来声明。能够经过contect.startservice和contect.bindserverice来启动。和其余的应用组件同样,运行在进程的主线程中。这就是说若是service须要不少耗时或者阻塞的操做,须要在其子线程中实现(或者用系统提供的IntentService,它继承了Service,它处理数据是用自身新开的线程)。【固然你也能够在新的线程中startService,这样Service就不是在MainThread了】微信
本地服务 Local Service 用于应用程序内部微信开发
它能够启动并运行,直至有人中止了它或它本身中止。在这种方式下,它以调用Context.startService()启动,而以调用Context.stopService()结束。它能够调用Service.stopSelf() 或 Service.stopSelfResult()来本身中止。不论调用了多少次startService()方法,你只须要调用一次stopService()来中止服务。app
【用于实现应用程序本身的一些耗时任务,好比查询升级信息,并不占用应用程序好比Activity所属线程,而是单开线程后台执行,这样用户体验比较好】eclipse
远程服务 Remote Service 用于Android系统内部的应用程序之间ide
它能够经过本身定义并暴露出来的接口进行程序操做。客户端创建一个到服务对象的链接,并经过那个链接来调用服务。链接以调用Context.bindService()方法创建,以调用 Context.unbindService()关闭。多个客户端能够绑定至同一个服务。若是服务此时尚未加载,bindService()会先加载它。
【可被其余应用程序复用,好比天气预报服务,其余应用程序不须要再写这样的服务,调用已有的便可】
1,Service的生命周期
2,Service运行方式
以startService()启动服务,系统将经过传入的Intent在底层搜索相关符合Intent里面信息的service。若是服务没有启动则先运行onCreate,而后运行onStartCommand (可在里面处理启动时传过来的Intent和其余参数),直到明显调用stopService或者stopSelf才将中止Service。不管运行startService多少次,只要调用一次stopService或者stopSelf,Service都会中止。使用stopSelf(int)方法能够保证在处理好intent后再中止。onStartCommand ,在2.0后被引入用于service的启动函数,2.0以前为public void onStart(Intent intent, int startId) 。
以bindService()方法启用服务,调用者与服务绑定在了一块儿,调用者一旦退出,服务也就终止。onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,屡次调用Context.bindService()方法并不会致使该方法被屡次调用。采用Context.bindService()方法启动服务时只能调用onUnbind()方法解除调用者与服务解除,服务结束时会调用onDestroy()方法。
3,拥有service的进程具备较高的优先级
官方文档告诉咱们,android系统会尽可能保持拥有service的进程运行,只要在该service已经被启动(start)或者客户端链接(bindService)到它。当内存不足时,须要保持,拥有service的进程具备较高的优先级。
1. 若是service正在调用onCreate,onStartCommand或者onDestory方法,那么用于当前service的进程则变为前台进程以免被killed。
2. 若是当前service已经被启动(start),拥有它的进程则比那些用户可见的进程优先级低一些,可是比那些不可见的进程更重要,这就意味着service通常不会被killed.
3. 若是客户端已经链接到service (bindService),那么拥有Service的进程则拥有最高的优先级,能够认为service是可见的。
4. 若是service可使用startForeground(int, Notification)方法来将service设置为前台状态,那么系统就认为是对用户可见的,并不会在内存不足时killed。
5. 若是有其余的应用组件做为Service,Activity等运行在相同的进程中,那么将会增长该进程的重要性。
onStartCommand方法,返回START_STICKY
StartCommond几个常量参数简介:
一、START_STICKY
在运行onStartCommand后service进程被kill后,那将保留在开始状态,可是不保留那些传入的intent。不久后service就会再次尝试从新建立,由于保留在开始状态,在建立 service后将保证调用onstartCommand。若是没有传递任何开始命令给service,那将获取到null的intent。
二、START_NOT_STICKY
在运行onStartCommand后service进程被kill后,而且没有新的intent传递给它。Service将移出开始状态,而且直到新的明显的方法(startService)调用才从新建立。由于若是没有传递任何未决定的intent那么service是不会启动,也就是期间onstartCommand不会接收到任何null的intent。
三、START_REDELIVER_INTENT
在运行onStartCommand后service进程被kill后,系统将会再次启动service,并传入最后一个intent给onstartCommand。直到调用stopSelf(int)才中止传递intent。若是在被kill后还有未处理好的intent,那被kill后服务仍是会自动启动。所以onstartCommand不会接收到任何null的intent。
【结论】 手动返回START_STICKY,亲测当service因内存不足被kill,当内存又有的时候,service又被从新建立,比较不错,可是不能保证任何状况下都被重建,好比进程被干掉了....
提高service优先级
在AndroidManifest.xml文件中对于intent-filter能够经过android:priority = "1000"这个属性设置最高优先级,1000是最高值,若是数字越小则优先级越低,同时适用于广播。
【结论】目前看来,priority这个属性貌似只适用于broadcast,对于Service来讲可能无效
提高service进程优先级
Android中的进程是托管的,当系统进程空间紧张的时候,会依照优先级自动进行进程的回收。Android将进程分为6个等级,它们按优先级顺序由高到低依次是:
1.前台进程( FOREGROUND_APP)
2.可视进程(VISIBLE_APP )
3. 次要服务进程(SECONDARY_SERVER )
4.后台进程 (HIDDEN_APP)
5.内容供应节点(CONTENT_PROVIDER)
6.空进程(EMPTY_APP)
当service运行在低内存的环境时,将会kill掉一些存在的进程。所以进程的优先级将会很重要,可使用startForeground 将service放到前台状态。这样在低内存时被kill的概率会低一些。
在onStartCommand方法内添加以下代码:
注意在onDestroy里还须要stopForeground(true),运行时在下拉列表会看到本身的APP在:
【结论】若是在极度极度低内存的压力下,该service仍是会被kill掉,而且不必定会restart
onDestroy方法里重启service
service +broadcast 方式,就是当service走ondestory的时候,发送一个自定义的广播,当收到广播的时候,从新启动service;
在onDestroy时:
在BootReceiver里
也能够直接在onDestroy()里startService
【结论】当使用相似口口管家等第三方应用或是在setting里-应用-强制中止时,APP进程可能就直接被干掉了,onDestroy方法都进不来,因此仍是没法保证~.~
Application加上Persistent属性
看Android的文档知道,当进程长期不活动,或系统须要资源时,会自动清理门户,杀死一些Service,和不可见的Activity等所在的进程。可是若是某个进程不想被杀死(如数据缓存进程,或状态监控进程,或远程服务进程),能够这么作:
【结论】听说这个属性不能乱设置,不过设置后,的确发现优先级提升很多,或许是至关于系统级的进程,可是仍是没法保证存活
监听系统广播判断Service状态
经过系统的一些广播,好比:手机重启、界面唤醒、应用状态改变等等监听并捕获到,而后判断咱们的Service是否还存活,别忘记加权限啊。
BroadcastReceiver中:
【结论】这也能算是一种措施,不过感受监听多了会致使Service很混乱,带来诸多不便