IM即时通讯应用开发中无法解决的“顽疾”
Android进程和Service的保活,是困扰Android开发人员的一大顽疾。因涉及到省电和内存管理策略,各厂商基于自家的理解,在自已ROOM发布于都对标准Android发行版作为或多或少的改动,使得应用层程序在处理进程和Service保活问题上变的异常复杂,且很难兼容,因为说不定哪款手机或者哪个版本的省电策略发生改变,那么随之而来的就是进程和Service保活的差异。
在应用场景上,由于即时通讯应用(包括IM聊天应用、消息推送服务等)为了保证消息的全时、实时送达能力,必须要实现进程或Service的保活。而就这一看似不起眼的问题,实际处理起来,因为众多Android手机和Android系统版本的差异,让问题的处理充满了不确定性。
以小米手机为例,MIUI的神隐模式让很多IM和推送开发同行纠结不已:在MIUI深度休眠之后,默认会彻底断开后台应用的socket。但微信、QQ这样的应用,MIUI官方的帖子说了:给这2个应用特殊照顾。好吧,特殊照顾,普通的APP只能继续折腾了。
为什么我们的后台进程/Service会被结束掉?
我想到的是有三个方面:
Android系统内存回收机制;
各厂商对后台程序的一个管理制度(就是允许程序后台运行那个);
第三方软件的清理(360什么的)。
其中有的后台程序保护把程序结束的同时会把程序弄成停止状态,导致无法接收广播!
我们的保活方案有哪些?
1控制onStartCommand函数的返回值:
我对这个函数的理解是:当服务被异常终止时,是否重启服务?有些文章里面在用这个做保活时,修改的是flag,在我实际测试中是无效。有效的做法是直接返回参数。另外默认的flags值为0,是START_STICKY_COMPATIBILITY。
具体代码如下
@Override
publicintonStartCommand(Intent intent,intflags,intstartId) {
// TODO Auto-generated method stub
returnSTART_STICKY;
//return super.onStartCommand(intent, flags, startId);
}
测试结果:
魅族的机子无效,不管默认还是修改参数,在DDMS里面直接结束进程后都不会重启服务。其它三台机子(9100没测):默认参数的情况下就会重启服务,return START_STICKY 会重启,return START_NOT_STICKY 不会重启。
另外:用360一键清理,或者360超级ROOT的手机优化,会杀死进程,过会儿还是会重启,只是会慢很多,大概是在排队重启服务。
2在service 的onDestory里面重启服务:
这个在所有能触发onDestory的情况下都是有效的。4台测试机都测试过。直接startService 或者发送广播重启都可以 。
但能触发onDestory的情况,我不知道内存回收会不会触发。另外两种情况(2,3)是不触发的。我的测试方法是在“设置”-> 应用管理-> 正在运行-> 停止服务。(这个是正常停止服务,会触发onDestory,所以上面的onStartCommand效果不会触发。)
3提高服务的优先级:
这个主要是针对第一种kill服务的情况,内存回收机制。由于这个测试比较难搭建。360清理什么把后台的进程都杀的,体现不出优先级这样的概念。我的建议是能提高就提高,下面几个实验。即时通讯聊天软件app开发可以加蔚可云的v:weikeyun24咨询
[1] 前台service:
创建一个通知使自己成为前台service
测试结果:
360一键清理和手机优化,不会把该service结束掉。
[2] 对于后台保护:
华为G730不结束service,魅族和华为TL00H都会结束service。通知栏的保活效果还是可以的,一般的应用要求基本能满足了。
[3] 若有root权限:
android:persistent="true",并放入system/app中
测试结果:
效果一般,三星9100上用360等清理工具杀不掉进程,在华为G730上没什么效果.(这个测试跟onStartCommand有点干扰)。
4守护进程:
双服务:360会同时杀掉两个服务,分两个apk也一样。
native守护进程:360不会杀掉native的守护进程,但在魅族和华为TL00H中待机一段时间后还是会被杀掉。
结论和待续:
1. 一般的应用添加到后台保护进程后,改个onStartCommand返回值,再加个通知。基本上大部分都能保活了。
2. 双服务我觉得没有native守护进程来的好,虽然360,微信什么的都有几个进程服务,但如果不添加到后台保活的话,效果一样不能保活,也会进入停止状态。
3. 但是.360手机助手会创建双natice守护进程做相互的看守。存活的效果会高一点点。“没添加到后台保活”一般只会杀一次,(魅族是屏幕关闭后5分钟,华为TL00H是屏幕关闭时)。
附个native守护进程:利用socket来判断服务是否存在,需要在被保活的服务里创建一个监听socket。调试信息会在SD卡目录下创建一个daemon.log。使用方法:NDKFork port包名/.服务名。
Android应用实现保活的基本原理总结
都是通过双进程互拉以及设置进程的重要性,除非你root后,把自己的进程设置成系统进程。
互拉的方式有很多种:
可以通过监听系统广播来把自己拉起来
可以多个app相互拉
可以把自己的服务搞成前台服务
在service的onstart方法里返回 STATR_STICK
添加Manifest文件属性值为android:persistent=“true”
覆写Service的onDestroy方法
服务互相绑定
设置闹钟,定时唤醒
自己的app在native层fork一个子进程来与主进程互拉。
综上所述,总结下来就是,目前实现Android后台保活没有完美实现,只能针对不同的机型综合使用上面列举的方法,同时祈祷自已APP的用户不要遇到奇葩机型的保活问题。