什么是Android进程(app)保活、进程保活的方案
想了解什么是Android 进程、Android 进程的生命周期、Android 进程回收策略
可参照地址什么是Android 进程、Android 进程的生命周期、Android 进程回收策略_lmm0513的博客-CSDN博客_android进程是什么
一、app保活
在Android中是一种流氓行为,一方面无端浪费用户手机电量,另一方面给用户一种很困惑的感觉,影响用户体验还有可能导致整个Android系统流畅性变差,所以Google官方一种不推荐该功能,也一直在阻止这方面功能在Android系统上运行,作为一个Android开发人员,应该极力阻止这种无耻的行为!!!
以上内容原文:APP保活_qq_18350329的专栏-CSDN博客_app保活
二、Android 进程保活的两个方案:
运行中保活:提高进程优先级,降低被系统 kill 的概率
被 kill 后拉活:被系统 kill 后,将进程拉活(重启)
1.运行中保活
通过前面章节的论述,我们知道,假设 APP 进程能够一直被认为是前台进程,那么系统就有可能永远不会杀死该进程。当然,这是不可能的,当我们将 APP 退回到后台,改 APP 所属进程就不属于 前台进程了。但是上述假设也让我们有了灵感不是,只要我们尽可能的提高进程的优先级,不就可以最大概率的降低被系统 kill 的可能性了。
那么,提高进程优先级的方法有哪些呢?
(1)利用 Activity 提高权限
监听手机锁屏解锁事件,锁屏时启动一个1像素的 Activity ,解锁时将该 Activity 销毁。此方法能将进程在锁屏状态下提高到最高前台进程( oom_adj 为 0 )的级别。避免出现一些让用户困扰(体验不好)的情况,该 Activity 需设计成用户无感知。
此方案主要解决为了达到省电目的,一些第三方应用或者系统管理工具在检测到锁屏之后一段时间(一般是 5 分钟)内会杀死后台进程。
下面是实例代码:
1像素 Activity:
class KeepLiveActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)KeepLiveManager.keepLiveActivity = this// 设置Activity在左上角window.setGravity(Gravity.START)// 设置window的像素为1window.attributes.run {x = 0y = 0width = 1height = 1}}}
注意,这里一定要设置启动模式为 singleInstance,使该 Activity 单独一个 Activity 回退栈,否则在锁屏且 APP 在后台运行时,启动该 Activity 后,会进程带入前台,解锁后显示该APP界面,体验不好
<activityandroid:name=".KeepLiveActivity"android:launchMode="singleInstance"/>
广播接收者:
class KeepLiveReceiver : BroadcastReceiver() {override fun onReceive(context: Context, intent: Intent) {Log.d("KeepLiveReceiver", "action = ${intent.action}")when(intent.action) {// 锁屏Intent.ACTION_SCREEN_OFF -> {KeepLiveManager.startKeepLiveActivity(context)}// 解锁Intent.ACTION_USER_PRESENT -> {KeepLiveManager.finishKeepLiveActivity()}}}}
管理单例:
object KeepLiveManager {var keepLiveActivity: KeepLiveActivity? = nullfun startKeepLiveActivity(context: Context) {val intent = Intent(context, KeepLiveActivity::class.java)intent.flags = Intent.FLAG_ACTIVITY_NEW_TASKcontext.startActivity(intent)}fun finishKeepLiveActivity() {keepLiveActivity?.finish()}}
注:由于锁屏、解锁的动作频率极高,该类广播在清单文件中注册无效,需要启动服务来注册广播,此部分代码和本章主题关系不大,就不贴代码了。思路就是:启动 APP 时,启动一个注册服务,在服务的 onCreate() 方法中注册广播,在 onDestory() 方法中注销广播。
以下是使用该方案保活前和保活后查看 oom_adj 的对比截图:
保活前
保活后
可见,保活后在锁屏状态,将进程的 oom_adj 由原来的7提高到了 0 。
附:查看进程 oom_adj 的方法 在命令行中使用以下两个命令adb shell ps | grep packageNameadb shell cat /proc/PID/oom_adj如:G:AndroidGithubKeepLive>adb shellshell@armani:/ $ ps | grep com.cy.keepliveu0_a3 5991 213 541548 29976 ffffffff 00000000 S com.cy.keepliveshell@armani:/ $ cat /proc/5991/oom_adj
0
(2)利用 Notification 提升权限
通过 setForeground() 方法可以将后台 Service 设置为前台 Service,可以将服务进程优先级提升为与可见进程一致,这将有效提高进程的优先级,从而大大降低进程被kill的概率。
通过 setForeground() 将后台 Service 设置为前台 Service 时,必须在系统的通知栏发送一条通知,也就是说前台 Service 必须绑定一条可见的通知。
在通知栏发送一条通知,是用户可以感知到的,这可能会对用户造成一定的困扰。可以通过实现一个内部 Service,在外部和内部 Service 中同时发送具有相同 ID 的 Notifacation ,然后将内部 Service 结束。随着内部 Service 的结束,Notification 也会消失掉,但系统的优先级仍然提高了。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {try {Notification notification = new Notification();if (Build.VERSION.SDK_INT < 18) {startForeground(NOTIFICATION_ID, notification);} else {startForeground(NOTIFICATION_ID, notification);// start InnerServicestartService(new Intent(this, InnerService.class));}} catch (Throwable e) {e.printStackTrace();}return super.onStartCommand(intent, flags, startId);}
然后在内部 Service 中也启动一个相同 ID 的 Notifacation ,并调用 stopSelf() 方法,结束内部 Service:
@Override
public void onCreate() {super.onCreate();try {startForeground(NOTIFICATION_ID, new Notification());} catch (Throwable throwable) {throwable.printStackTrace();}stopSelf();}
2、被 kill 后拉活
此类方法暂未实践,后续补充。暂时简单提一下前人研究的可行性方案,不过这类方案都多多少少存在限制条件或者版本兼容性问题。
(1)通过系统广播拉活
简单讲就是监听一些特定的系统广播,当系统发出这些广播时,即可相应事件拉活。
(2)利用第三方应用广播拉活
此方案和第1中方案类似,不同的时该方案接收第三方 TOP 应用广播。通过反编译第三方 TOP 应用(如 QQ、微信、支付宝等,以及个推、极光推送等推送 SDK ),找出它们外放的广播进行监听,响应相应广播事件拉活。
(3)利用系统Service机制拉活
将 Service 设置为 START_STICKY,利用系统机制在 Service 挂掉后拉活。
(4)双进程守护
通过双进程的 Service 相互绑定,在一个进程被 kill 时,另一个进程将其拉活。
(5)利用 JobScheduler 机制拉活
JobScheduler 允许在特定状态与特定时间间隔周期执行任务。可以利用它的这个特点完成保活的功能,效果类似开启一个定时器,与普通定时器不同的是其调度由系统完成。它是在 Android5.0 之后推出的,在 5.0 之前无法使用。
(6)利用 Native 进程拉活
利用 Linux 中的 fork 机制创建 Native 进程,在 Native 进程中监控主进程的存活,当主进程挂掉后,在 Native 进程中立即对主进程进行拉活。
以上内容来自原文:文章-阿里云开发者社区-云计算社区-阿里云
什么是Android进程(app)保活、进程保活的方案相关推荐
- Android进程保活、拉活方案
引言 最近产品提出了一个非常BT的需求,说我们所做的APP要做到像微信和QQ那种即时用户清理了进程还是能收到消息的效果,当时心中就卧槽了一顿,虽然心里一万只曹尼玛翻滚着,但是功能还是要做啊,因为生活还 ...
- 【Android 进程保活】oom_adj 值 ( 简介 | 查询进程 PID | 根据进程 PID 查询 oom_adj 值 )
文章目录 一.oom_adj 值简介 二.查询进程号 PID 三.查询进程对应的 oom_adj 值 一.oom_adj 值简介 oom_adj 值是 Linux 内核为每个进程分配的 , 该值可以反 ...
- 【Android 进程保活】Android 进程优先级 ( 前台进程 | 可见进程 | 服务进程 | 后台进程 | 空进程 )
文章目录 一.Android 进程优先级 二.前台进程 三.可见进程 四.服务进程 五.后台进程 六.空进程 一.Android 进程优先级 Android 进程优先级 : ① 前台进程 > ② ...
- 关于Android安卓APP保活 - 安卓消息推送详解 - 安卓端外推送离线推送
转自:http://zhangtielei.com/posts/blog-android-push.html 说Android端外推送比较烦,实际有两层意思:首先是说实现上比较麻烦,至今业界也没有找到 ...
- Android之APP保活
前言 强烈建议不要这么做,不仅仅从用户角度考虑,它只会滋生更多的流氓应用,拖垮Android 平台的流畅性(假如你手机里装了支付宝.淘宝.天猫.UC等阿里系的app,那么你打开任意一个阿里系的app后 ...
- android 判断App进程是否存在,处在前台,后台,前后台切换,service是否运行,设置为系统app
1.判断进程是否存在 //判断是否在主进程,这个方法判断进程名或者pid都可以,如果进程名一样那pid肯定也一样 //true:当前进程是主进程 false:当前进程不是主进程 public bool ...
- Android退出APP 并杀掉相关的所有进程
Android退出APP 并杀掉相关的所有进程 代码如下: ActivityManager mActivityManager = (ActivityManager) mContext.getSyste ...
- Android中app进程ABI确定过程
更多干货,请关注微信公众号: tmac_lover 所谓的ABI全称是application binary interface,是一个机器语言级别的接口,描述的是二进制代码之间的兼容性,也就是说一起工 ...
- 【Android】系统架构功能+init、zygote、system server、app等进程间关系分析
文章目录 架构功能 Loader层 Linux内核层 硬件抽象层 (HAL) Android Runtime & 系统库 Framework层 App层 Syscall && ...
- Android之adb jdwp获取debug版本app的进程Id
1.adb jdwp命令 adb jdwp获取debug版本app的进程Id 2.用途 带我们运行一个debug版本的app时候,我们需要过滤日志,我们一般采取这种办法 adb shell ps | ...
最新文章
- KV结构的集合,在处理null值的存储上有细微的区别,下列哪些说法是正确的
- Windows下使用gvim格式化xml文件
- 2018.3,GC可控了
- mysql声明declare_mysql8 参考手册--DECLARE ... CONDITION声明
- python4发布_Python 3.4.1 发布
- 翻译网站去除输入内容的换行符/回车符【操作简单】适用谷歌/百度/有道/DeepL/腾讯/必应等
- Spark机器学习-LDA算法09
- STM32WL开发之LORA产品选型
- 【180630】VC++画面炫丽的2D 太空射击游戏源码
- TPM设备管理之设备采购方法及注意事项
- 计算机的内存、外存、主存、辅存
- Bezier曲线生成【计算机图形学】
- 事件2 有源码 可以随意进行练习哈 太棒了 一起加油 一起成长
- 利用 Python 分析 MovieLens 1M 数据集
- 关于将EXCEL文件导入到MYSQL数据库的一些方法
- 在线重定义在线更换分区表分区类型
- assign()函数的使用
- CAP原理以及选取的场景
- 无线wifi丢包的解决办法
- 推荐系统中的EE问题——Bandit算法