android双进程守护耗电,Android实现双进程守护
做过android开发的人应该都知道应用会在系统资源匮乏的情况下被系统杀死!当后台的应用被系统回收之后,如何重新恢复它呢?网上对此问题有很多的讨论。这里先总结一下网上流传的各种解决方案,看看这些办法是不是真的可行。
1.提高优先级
这个办法对普通应用而言,应该只是降低了应用被杀死的概率,但是如果真的被系统回收了,还是无法让应用自动重新启动!
2.让service.onStartCommand返回START_STICKY
通过实验发现,如果在adb shell当中kill掉进程模拟应用被意外杀死的情况(或者用360手机卫士进行清理操作),如果服务的onStartCommand返回START_STICKY,在eclipse的进程管理器中会发现过一小会后被杀死的进程的确又会出现在任务管理器中,貌似这是一个可行的办法。但是如果在系统设置的App管理中选择强行关闭应用,这时候会发现即使onStartCommand返回了START_STICKY,应用还是没能重新启动起来!
3.android:persistent=”true”
网上还提出了设置这个属性的办法,通过实验发现即使设置了这个属性,应用程序被kill之后还是不能重新启动起来的!
4.让应用成为系统应用
实验发现即使成为系统应用,被杀死之后也不能自动重新启动。但是如果对一个系统应用设置了persistent=”true”,情况就不一样了。实验表明对一个设置了persistent属性的系统应用,即使kill掉会立刻重启。一个设置了persistent=”true”的系统应用,在android中具有core service优先级,这种优先级的应用对系统的low memory killer是免疫的!
OK,说了半天,只有core service优先级的应用才能保证在被意外杀死之后做到立刻满血复活。而普通应用要想成为系统应用就必须要用目标机器的签名文件进行签名,但这样又造成了应用无法保证兼容所有不同厂商的产品。那么该怎么办呢?这里就来说一说双进程守护。网上也有人提到过双进程守护的办法,但是很少能搜索到类似的源码!如果从进程管理器重观察会发现新浪微博或者360卫视都有两个相关的进程,其中一个就是守护进程,由此可以猜到这些商业级的软件也采用了双进程守护的办法。
什么是双进程守护呢?顾名思义就是两个进程互相监视对方,发现对方挂掉就立刻重启!不知道应该把这样的一对进程是叫做相依为命呢还是难兄难弟好呢,但总之,双进程守护的确是一个解决问题的办法!相信说到这里,很多人已经迫切的想知道如何实现双进程守护了。这篇文章就介绍一个用NDK来实现双进程保护的办法,不过首先说明一点,下面要介绍的方法中,会损失不少的效率,反应到现实中就是会使手机的耗电量变大!但是这篇文章仅仅是抛砖引玉,相信看完之后会有更多高人指点出更妙的实现办法。
需要了解些什么?
这篇文章中实现双进程保护的方法基本上是纯的NDK开发,或者说全部是用C++来实现的,需要双进程保护的程序,只需要在程序的任何地方调用一下JAVA接口即可。下面几个知识点是需要了解的:
1.linux中多进程;
2.unix domain套接字实现跨进程通信;
3.linux的信号处理;
4.exec函数族的用法;
其实这些东西本身并不是多复杂的技术,只是我们把他们组合起来实现了一个双进程守护而已,没有想象中那么神秘!在正式贴出代码之前,先来说说几个实现双进程守护时的关键点:
1.父进程如何监视到子进程(监视进程)的死亡?
很简单,在linux中,子进程被终止时,会向父进程发送SIG_CHLD信号,于是我们可以安装信号处理函数,并在此信号处理函数中重新启动创建监视进程;
2.子进程(监视进程)如何监视到父进程死亡?
当父进程死亡以后,子进程就成为了孤儿进程由Init进程领养,于是我们可以在一个循环中读取子进程的父进程PID,当变为1就说明其父进程已经死亡,于是可以重启父进程。这里因为采用了循环,所以就引出了之前提到的耗电量的问题。
3.父子进程间的通信
有一种办法是父子进程间建立通信通道,然后通过监视此通道来感知对方的存在,这样不会存在之前提到的耗电量的问题,在本文的实现中,为了简单,还是采用了轮询父进程PID的办法,但是还是留出了父子进程的通信通道,虽然暂时没有用到,但可备不时之需!
OK, 下面就贴上代码!首先是Java部分,这一部分太过简单,只是一个类,提供了给外部调用的API接口用于创建守护进程,所有的实现都通过native方法在C++中完成!
package com.example.dameonservice;
import java.util.ArrayList;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
/**
* 监视器类,构造时将会在Native创建子进程来监视当前进程,
*@authorwangqiang
* @date 2014-04-24
*/
public class Watcher
{
//TODO Fix this according to your service
private static final String PACKAGE = “com.example.dameonservice/”;
private String mMonitoredService = “”;
private volatile boolean bHeartBreak = false;
private Context mContext;
private boolean mRunning = true;
public void createAppMonitor(String userId)
{
if( !createWatcher(userId) )
{
Log.e(“Watcher”, “<>”);
}
}
public Watcher( Context context)
{
mContext = context;
}
private int isServiceRunning()
{
ActivityManager am=(ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
ArrayList runningService = (ArrayList)am.getRunningServices(1024);
for( int i = 0; i < runningService.size(); ++i )
{
if( mMonitoredService.equals(runningService.get(i).service.getClassName().toString() ))
{
return 1;
}
}
return 0;
}
/**
* Native方法,创建一个监视子进程.
*@paramuserId 当前进程的用户ID,子进程重启当前进程时需要用到当前进程的用户ID.
*@return如果子进程创建成功返回true,否则返回false
*/
private native boolean createWatcher(String userId);
/**
* Native方法,让当前进程连接到监视进程.
*@return连接成功返回true,否则返回false
*/
private native boolean connectToMonitor();
/**
* Native方法,向监视进程发送任意信息
* @param 发给monitor的信息
* @return 实际发送的字节
*/
private native int sendMsgToMonitor(String msg);
static
{
System.loadLibrary(“monitor”);
}
}
代码中很多属性都是测试时用的,懒得去掉,其实有些都没用到。只需要关心createAppMonitor这个对外接口就可以了,它要求传入一个当前进程的用户ID,然后会调用createWatcher本地方法来创建守护进程。还有两个方法connectToMonitor用于创建和监视进程的socket通道,sendMsgToMonitor用于通过socket向子进程发送数据。由于暂时不需要和子进程进行数据交互,所以这两个方法就没有添加对外的JAVA接口,但是要添加简直是轻而易举的事!
Ok,JAVA只是个壳,内部的实现还得是C++,为了让程序更加的面向对象,在实现native时,我们用一个ProcessBase基类来对父子进程进行一个抽象,把父子进程都会有的行为抽象出来,而父子进程可以根据需要用自己的方式去实现其中的接口,先来看看这个抽象了父子进程共同行为的ProcessBase基类:
#ifndef _PROCESS_H
#define _PROCESS_H
#include
#include
#include
android双进程守护耗电,Android实现双进程守护相关推荐
- 揭秘!双非渣本Android四年磨一剑,学习路线+知识点梳理
第一次观看我文章的朋友,可以关注.点赞.转发一下,每天分享各种干货技术和程序猿趣事 由于涉及到的面试题较多导致篇幅较长,我根据这些面试题所涉及到的常问范围总结了并做出了一份学习进阶路线图 ...
- 你想学的都在这里!双非渣本Android四年磨一剑,赶紧收藏!
前言 说不焦虑其实是假的,因为无论是现在还是最近几年,很早就有人察觉Android开发的野蛮生长时代已经过去.过去的优势是市场需要,这个技术少有人有,所以在抢占市场的时候,基本上满足需要就已经可以了. ...
- 双非渣本Android四年磨一剑,赶紧收藏!
前言 说不焦虑其实是假的,因为无论是现在还是最近几年,很早就有人察觉Android开发的野蛮生长时代已经过去.过去的优势是市场需要,这个技术少有人有,所以在抢占市场的时候,基本上满足需要就已经可以了. ...
- Android显示日历的函数,android实现双日期选择控件(可隐藏日,只显示年月)
在安卓开发中,会碰到选开始日期和结束日期的问题.特别是在使用Pad时,如果弹出一个Dialog,能够同时选择开始日期和结束日期,那将是极好的.我在开发中在DatePickerDialog的基础上做了修 ...
- Android 系统(265)----Android进程保活全攻略(上)
Android进程保活全攻略(上) 对于每个公司的APP来说,当然都希望自己APP的进程尽量的不被杀死,于是乎,就有了一些列进程保活的方法出现,网上也有很多关于这类的文章,但网上很多资料往往只告诉了思 ...
- Android 系统(146)----Android进程保活招数概览
Android进程保活招数概览 Android中的进程保活应该分为两个方面: 提高进程的优先级,减少被系统杀死的可能性 在进程已经被杀死的情况下,通过一些手段来重新启动应用进程 本文针对这两方面来进程 ...
- 什么是Android进程(app)保活、进程保活的方案
想了解什么是Android 进程.Android 进程的生命周期.Android 进程回收策略 可参照地址什么是Android 进程.Android 进程的生命周期.Android 进程回收策略_lm ...
- Android 系统(270)---开机广播的简单守护以及总结
Android 进程常驻(5)----开机广播的简单守护以及总结 这是一个轻量级的库,配置几行代码,就可以实现在android上实现进程常驻,也就是在系统强杀下,以及360获取root权限下,clea ...
- Android 功耗(15)---Android系统耗电
详解Android系统耗电 首先介绍一下为什么Android手机普遍有电池不耐用的问题. 作为一个开放系统,Android对于应用程序,特别是后台应用程序几乎完全不加以限制.导致了以下几个比较大的问题 ...
最新文章
- 【go】sdk + idea-plugin 开发工具安装
- 几个简单的shell脚本
- android http pos 请求和gson解析处理head头信息
- java8 内置函数(api)总结
- 停牌17个月 汉能薄膜真的要复牌了?
- 拓端tecdat|r语言中对LASSO回归,Ridge岭回归和Elastic Net模型实现
- openpyxl安装_Openpyxl玩转Excel(一)——新建、读取、复制
- 计算机应用基础教程学什么,[电脑基础知识]计算机应用基础教程学习.ppt
- LINUX 线程启动回调函数
- Android智慧城市代码——登录
- 搞懂神经网络处理器的性能指标
- RK3399pro 使用TNN日记 2(Linux系统)
- 淘宝账号如何快速提升到更高等级
- Threejs导入OBJ模型出错的一些经验之谈
- 裸辞后,随便找份工作干着还是等找到满意的为止?
- 【2020年面经】【通用篇】拿了阿里、滴滴、shopee几家公司offer后的经验总结
- 《黑匣子思维:我们如何更理性地犯错》ipad部分
- 理解IaaS、SaaS、paas的含义及区别
- UIImagePickerController编辑图片框大小的问题
- 使用openpyxl进行多个excel数据合并
热门文章
- 修改PostgreSQL数据库默认用户postgres的密码
- html 书架样式css,CSS3 响应式书架布局
- ntu课程笔记7454 期中复习
- pytorch 学习笔记:nn.Sequential构造神经网络
- Spring 的 BeanUtils 踩坑记,你是不是遇到过这些问题?
- tableau实战系列(三十四)-教你如何在tableau中实现3D效果作图
- 使用FP-growth算法发现频繁项集
- java.lang.UnsatisfiedLinkError解决方法汇集
- 机器学习第1天:数据预处理
- LeetCode-动态规划-213. 打家劫舍 II