Android后台保活实践总结:即时通信应用没法根治的“顽疾”

前言

Android进程和Service的保活,是困扰Android开发人员的一大顽疾。因涉及到省电和内存管理策略,各厂商基于自家的理解,在自已ROOM发布于都对标准Android发行版做为或多或少的改动,使得应用层程序在处理进程和Service保活问题上变的异常复杂,且很难兼容,由于说不定哪款手机或者哪一个版本的省电策略发生改变,那么随之而来的就是进程和Service保活的差别。

在应用场景上,因为即时通信应用(包括IM聊天应用、消息推送服务等)为了保证消息的全时、实时送达能力,必需要实现进程或Service的保活。而就这一看似不起眼的问题,实际处理起来,由于众多Android手机和Android系统版本的差别,让问题的处理充满了不肯定性。

本文基于做者的实践以及相关资料的整理,总结了自已对Android进程和Service保活的理解,但愿能为你的应用开发带来启发。php

学习交流

- 更多即时通信技术资料:http://www.52im.net/forum.php?mod=collection&op=allhtml

- 即时通信开发交流群: 215891622 [推荐]java

概述

近期作了一个Android项目,涉及到了后台进程和Service保活的问题,网上找了不少资料,基本的保活方法都测试了。结果是:不一样的手机,不一样的Android版本保活效果各有差别。最难绕过的是个厂商对“后台程序保活”管理。

本文主要把相应的实践结果和保活方法进行总结。然而,因笔者可用的测试真机有限,可能存有不完整的地方,还请及时提出指正并补充,你们共同进步。android

手机QQ、微信这样的大型IM是如何解决保活问题的?

以小米手机为例,MIUI的神隐模式让不少IM和推送开发同行纠结不已:在MIUI深度休眠以后,默认会完全断开后台应用的socket。但微信、QQ这样的应用,MIUI官方的帖子说了:给这2个应用特殊照顾。好吧,特殊照顾,普通的APP只能继续折腾了。

(关于MIUI的神隐模式的讨论,见此贴的回复:http://www.52im.net/thread-354-1-1.htmlgit

本文实践涉及到的真机型号和版本

手机:三星9100-4.1.2,三星9300-4.3,华为G730-4.1.2,华为TL00H-EMUI3.1(android 5.1.1),魅族MX4-Flyme4.2.8.2c(android 4.4.2)。

手头能用的测试机就这些了。主要测试的service是一个最基本的service,在相应的生命周期的触发函数上作了输出。测试时都没有添加到后台保护中,注:三星的机子没找到有后台保护设置的地方。github

为何咱们的后台进程/Service会被结束掉?

我想到的是有三个方面:微信

  • Android系统内存回收机制;
  • 各厂商对后台程序的一个管理制度(就是容许程序后台运行那个);
  • 第三方软件的清理(360什么的)。


其中有的后台程序保护把程序结束的同时会把程序弄成中止状态,致使没法接收广播!app

咱们的保活方案有哪些?

1)控制onStartCommand函数的返回值:

我对这个函数的理解是:当服务被异常终止时,是否重启服务?有些文章里面在用这个作保活时,修改的是flag,在我实际测试中是无效。有效的作法是直接返回参数。另外默认的flags值为0,是START_STICKY_COMPATIBILITY。

具体代码以下:socket

1
2
3
4
5
6
@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的手机优化,会杀死进程,过会儿仍是会重启,只是会慢不少,大概是在排队重启服务。

ide

2)在service 的onDestory里面重启服务:

这个在全部能触发onDestory的状况下都是有效的。4台测试机都测试过。直接startService 或者发送广播重启均可以 。

但能触发onDestory的状况,我不知道内存回收会不会触发。另外两种状况(2,3)是不触发的。个人测试方法是在“设置”-> 应用管理-> 正在运行-> 中止服务。(这个是正常中止服务,会触发onDestory,因此上面的onStartCommand效果不会触发。)

3)提升服务的优先级:

这个主要是针对第一种kill服务的状况,内存回收机制。因为这个测试比较难搭建。360清理什么把后台的进程都杀的,体现不出优先级这样的概念。个人建议是能提升就提升,下面几个实验。

[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包名/.服务名。具体下载连接:
http://download.csdn.net/detail/pvlking/9412815

Android应用实现保活的基本原理总结

都是经过双进程互拉以及设置进程的重要性,除非你root后,把本身的进程设置成系统进程。

互拉的方式有不少种:

  • 能够经过监听系统广播来把本身拉起来
  • 能够多个app相互拉
  • 能够把本身的服务搞成前台服务
  • 在service的onstart方法里返回 STATR_STICK
  • 添加Manifest文件属性值为android:persistent=“true”
  • 覆写Service的onDestroy方法
  • 服务互相绑定
  • 设置闹钟,定时唤醒
  • 本身的app在native层fork一个子进程来与主进程互拉。


综上所述,总结下来就是,目前实现Android后台保活没有完美实现,只能针对不一样的机型综合使用上面列举的方法,同时祈祷自已APP的用户不要遇到奇葩机型的保活问题。

推荐一个开源的解决方案 

1)源码托管地址

源码托管地址是:https://github.com/52im/MarsDaemon

2)实现原理

原理:使用Jni,在 c端 fork进程,检测Service是否存活,若Service已被杀死,则进行重启Service.  至于检测方式,能够轮询获取子进程Pid,若为1, 则说明子进程被Init进程所领养,已经成为了孤儿进程.    可是这种方式比较消耗电量,而且因为不一样手机系统定制的改变,当应用被强制中止时,父进程并不必定被真正杀死,所以在一些特定机型上是没法经过此方式进行判断. 这里推荐使用liunx socket的方式进行相似心跳包的检测,而且当触发检测Service是否被杀死以前,须要判断应用是否已经被卸载,若是应用已经被卸载,则再也不进行检测Service行为,直接调用exit(0)退出子进程,避免浪费系统资源和消耗电量.

注意: 目前在Android 5.0系统上会把fork出来的进程放到一个进程组里, 当程序主进程挂掉后,也会把整个进程组杀掉,所以用fork的方式也没法在Android5.0及以上系统实现守护进程. 这个是系统层面的限制,固然也是为了优化整个的系统环境,守护进程给手机带来的体验并很差

具体见源码:
http://androidxref.com/5.0.0_r2/ ... /ProcessRecord.java
Android后台保活实践总结:即时通信应用没法根治的“顽疾”_1809710-8f67dfa36f847c43.png 

好消息:
Android5.0 以上目前已在 https://github.com/52im/MarsDaemon 中被黑科技攻克,部分机型可能没法起到做用,但思路很值得借鉴,代码结构也不错, 具体方案请见源码哦。

 

(本文同步发布于:http://www.52im.net/thread-429-1-1.html

相关文章
相关标签/搜索