默认
发表评论 0
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
环信:Android进程保活姿势大全01!
阅读(28827) | 评论(0 收藏 淘帖
引用:

哲学上有三个终极问题:“你是谁?你从哪里来?你要到哪里去?”萦绕在APP创业者耳边关于“保活”也有三个终极问题:“我的APP能像微信那样一直在手机运行吗?为什么微信可以一直在手机后台跑着能收到消息?我自己的APP该如何实现进程保活?”关于第一和第二个问题,环信imgeek社区里已经有相关的解决方案和教程(http://www.imgeek.org/article/825308754)。本篇文章主要给大家分享关于微信进程保活的原理以及Android守护进程的实现教程。


1
我的APP能像微信那样一直在手机运行吗?


关于 Android 平台的进程保活,一 直是所有 Android 开发者瞩目的内容之一,也是环信小伙们比较关心的问题,本篇文章给大家分享关于微信进程保活的原理及Android守护进程的实现教程。

2
为啥微信一直在手机后台跑着能收到消息?


国内手机厂商对 android rom 进行了定制,对后台服务以及运行在后台的程序进行了严格的限制,微信等这些大厂商的 app 都已经通过和设备厂商合作在安装时都已经加入了系统的白名单,因此设备并不会限制对方 app 在后台运行;

3
我自己的APP该如何实现进程保活?


1、引导用户把当前 app 加入到设备的白名单中,解除设备对 app 的限制;2、小米和华为设备可以集成对应的推送实现在app 被干掉后依然收推送通知;3、可以自己在 app 端实现守护进程的方式,让 app 在系统级别自动回收的情况下减少被杀死的概率,这种方式对用户主动回收无效。
环信:Android进程保活姿势大全01!_640.jpg

01
什么是守护进程?



    守护进程能让我们的程序在后台运行的时间长一些,或者在被干掉的时候,能够重新站起来,需要注意不是每次都有效,也不是在所有的设备的上都有效的。

02
守护进程的实现原理



1.    提高进程优先级,降低被回收或杀死概率
2.    在进程被干掉后,进行拉起

03
进程的优先级



Process Importance记录在ActivityManager.java类中:
**
 * Path:SDK/sources/android-25/android/app/ActivityManager#RunningAppProcessInfo.java
 * 
 * 这个进程正在运行前台UI,也就是说,它是当前在屏幕顶部的东西,用户正在进行交互的而进程
 */
public static final int IMPORTANCE_FOREGROUND = 100;

/**
 * 此进程正在运行前台服务,即使用户不是在应用中时也执行音乐播放,这一般表示该进程正在做用户积极关心的事情
 */
public static final int IMPORTANCE_FOREGROUND_SERVICE = 125;
/**
 * 这个过程不是用户的直接意识到,但在某种程度上是他们可以察觉的。
 */
public static final int IMPORTANCE_PERCEPTIBLE = 130;

/**
 * 此进程正在运行前台UI,但设备处于睡眠状态,因此用户不可见,意思是用户意识不到的进程,因为他们看不到或与它交互,
 * 但它是相当重要,因为用户解锁设备时期望的返回到这个进程
 */
public static final int IMPORTANCE_TOP_SLEEPING = 150;

/**
 * 进程在后台,但我们不能恢复它的状态,所以我们想尽量避免杀死它,不然这个而进程就丢了
 */
public static final int IMPORTANCE_CANT_SAVE_STATE = 170;

/**
 * 此进程正在运行某些对用户主动可见的内容,但不是直接显示在UI,
 * 这可能运行在当前前台之后的窗口(因此暂停并且其状态被保存,不与用户交互,但在某种程度上对他们可见);
 * 也可能在系统的控制下运行其他服务,
 */
public static final int IMPORTANCE_VISIBLE = 200;

/**
 * 服务进程,此进程包含在后台保持运行的服务,这些后台服务用户察觉不到,是无感知的,所以它们可以由系统相对自由地杀死
 */
public static final int IMPORTANCE_SERVICE = 300;

/**
 * 后台进程
 */
public static final int IMPORTANCE_BACKGROUND = 400;

/**
 * 空进程,此进程没有任何正在运行的代码
 */
public static final int IMPORTANCE_EMPTY = 500;

// 此过程不存在。
public static final int IMPORTANCE_GONE = 1000;

04
进程回收机制



了解进程优先级之后,我们还需要知道一个进程回收机制的东西;这里参考AngelDevil在博客园上的一篇文章:

详情参考:【Android Low Memory Killer】

Android的Low Memory Killer基于Linux的OOM机制,在Linux中,内存是以页面为单位分配的,当申请页面分配时如果内存不足会通过以下流程选择bad进程来杀掉从而释放内存:

alloc_pages -> out_of_memory() -> select_bad_process() -> badness()

在Low Memory Killer中通过进程的oom_adj与占用内存的大小决定要杀死的进程,oom_adj越小越不容易被杀死;
Low Memory Killer Driver在用户空间指定了一组内存临界值及与之一一对应的一组oom_adj值,当系统剩余内存位于内存临界值中的一个范围内时,如果一个进程的oom_adj值大于或等于这个临界值对应的oom_adj值就会被杀掉。

下边是表示Process State(即老版本里的OOM_ADJ)数值对照表,数值越大,重要性越低,在新版SDK中已经在android层去除了小于0的进程状态
// Path:SDK/sources/android-25/android/app/ActivityManager#RunningAppProcessInfo.java 
// 进程不存在。 
public static final int PROCESS_STATE_NONEXISTENT = -1;
// 进程是一个持久的系统进程,一般指当前 UI 进程
public static final int PROCESS_STATE_PERSISTENT = 0;
// 进程是一个持久的系统进程,正在做和 UI 相关的操作,但不直接显示
public static final int PROCESS_STATE_PERSISTENT_UI = 1;
// 进程正在托管当前的顶级活动。请注意,这涵盖了用户可见的所有活动。 
public static final int PROCESS_STATE_TOP = 2;
// 进程由于系统绑定而托管前台服务。
public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 3;
// 进程正在托管前台服务。
public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4;
// 与{@link #PROCESS_STATE_TOP}相同,但设备处于睡眠状态。 
public static final int PROCESS_STATE_TOP_SLEEPING = 5;
// 进程对用户很重要,是他们知道的东西
public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 6;
// 进程对用户很重要,但不是他们知道的
public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 7;
// 进程在后台运行备份/恢复操作
public static final int PROCESS_STATE_BACKUP = 8;
// 进程在后台,但我们不能恢复它的状态,所以我们想尽量避免杀死它,不然这个而进程就丢了
public static final int PROCESS_STATE_HEAVY_WEIGHT = 9;
// 进程在后台运行一个服务,与oom_adj不同,此级别用于正常运行在后台状态和执行操作状态。 
public static final int PROCESS_STATE_SERVICE = 10;
// 进程在后台运行一个接收器,注意,从oom_adj接收器的角度来看,在较高的前台级运行,但是对于我们的优先级,这不是必需的,并且将它们置于服务之下意味着当它们接收广播时,一些进程状态中的更少的改变。 
public static final int PROCESS_STATE_RECEIVER = 11;
// 进程在后台,但主持家庭活动
public static final int PROCESS_STATE_HOME = 12;
// 进程在后台,但托管最后显示的活动
public static final int PROCESS_STATE_LAST_ACTIVITY = 13;
// 进程正在缓存以供以后使用,并包含活动
public static final int PROCESS_STATE_CACHED_ACTIVITY = 14;
// 进程正在缓存供以后使用,并且是包含活动的另一个缓存进程的客户端
public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 15;
// 进程正在缓存以供以后使用,并且为空
public static final int PROCESS_STATE_CACHED_EMPTY = 16;
Process State(即老版本的OOM_ADJ)与Process Importance对应关系,这个方法也是在ActivityManager.java类中,有了这个关系,就知道可以知道我们的应用处于哪个级别,对于我们后边优化有个很好地参考
/** 
 * Path:SDK/sources/android-25/android/app/ActivityManager#RunningAppProcessInfo.java
 *
 * 通过这个方法,将Linux底层的 OOM_ADJ级别码和 android 层面的进程重要程度联系了起来
 */
public static int procStateToImportance(int procState) {
    if (procState == PROCESS_STATE_NONEXISTENT) {
        return IMPORTANCE_GONE;
    } else if (procState >= PROCESS_STATE_HOME) {
        return IMPORTANCE_BACKGROUND;
    } else if (procState >= PROCESS_STATE_SERVICE) {
        return IMPORTANCE_SERVICE;
    } else if (procState > PROCESS_STATE_HEAVY_WEIGHT) {
        return IMPORTANCE_CANT_SAVE_STATE;
    } else if (procState >= PROCESS_STATE_IMPORTANT_BACKGROUND) {
        return IMPORTANCE_PERCEPTIBLE;
    } else if (procState >= PROCESS_STATE_IMPORTANT_FOREGROUND) {
        return IMPORTANCE_VISIBLE;
    } else if (procState >= PROCESS_STATE_TOP_SLEEPING) {
        return IMPORTANCE_TOP_SLEEPING;
    } else if (procState >= PROCESS_STATE_FOREGROUND_SERVICE) {
        return IMPORTANCE_FOREGROUND_SERVICE;
    } else {
        return IMPORTANCE_FOREGROUND;
    }
}
一般情况下,设备端进程被干掉有一下几种情况
进程结束场景结束方式影响范围
Android 系统自身内存回收机制Low Memory KillerProcess State 数值从大到小
第三方管理程序清理进程 无 Root 权限killBackgroundProcessProcess State 数值大于6进程
第三方管理程序清理进程 有 Root 权限force-stop or Kill除当前前台进程外所有非系统进程
Rom 清除进程(用户手动清理)force-stop or Kill所有非系统进程
用户手动强制结束force-stop第三方应用以及非 System 进程
由以上分析,我们可以可以总结出,如果想提高我们应用后台运行时间,就需要提高当前应用进程优先级,来减少被杀死的概率!未完接下篇。

未完请看“保活”—APP创业者永远的痛,Android进程保活姿势大全02!

即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

推荐方案
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部