最近在使用高德地图实时获取定位时遇到了个问题,锁屏后一段时间(5~10分钟左右)后程序会被系统杀死,为了保活,特研究了下进程保活机制。

0、基本操作和概念

针对root过的手机,可以通过下列命令查看内存阈值:

adb shell
su
cat /sys/module/lowmemorykiller/parameters/minfree
会出现6个数字,从小到大

某个数字 * 4KB / 1024KB = 某某MB;
这里的4kb是Linux中一页(one page)的大小;
得到的某某MB就是当系统内存小于某某M的时候,就杀死某些等级的进程。—俗称内存阈值

6个等级分别对应:
前台进程——可见进程——服务进程——后台进程——空进程

1、WakeLock 配合 PowerManager

从源头上把控,不让界面锁屏。

https://blog.csdn.net/IO_Field/article/details/49591429

 WakeLock mWakeLock;//申请设备电源锁public static void acquireWakeLock(Context context){if (null == mWakeLock){PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE, "WakeLock");if (null != mWakeLock){mWakeLock.acquire();}}}//释放设备电源锁public static void releaseWakeLock(){if (null != mWakeLock){mWakeLock.release();mWakeLock = null;}

此法于我无效,继续探索。

2、后台播放无声音乐

这个方法在持续进行位置获取上使用过了,有效,但是仍不能保证我的主进程活着,主进程挂了,音乐播放自然也无效了。

3、1像素Activity保活

OnePixelReceiver.java

package com.jsc4.androidcppsafe.onePixelKeepLive;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;/*** 监听屏幕状态的广播*/
public class OnePixelReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {    //屏幕关闭启动1像素ActivityIntent it = new Intent(context, OnePixelActivity.class);it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(it);} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {   //屏幕打开 结束1像素context.sendBroadcast(new Intent("finish"));Intent main = new Intent(Intent.ACTION_MAIN);main.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);main.addCategory(Intent.CATEGORY_HOME);context.startActivity(main);}}
}

OnePixelActivity.java

package com.jsc4.androidcppsafe.onePixelKeepLive;import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.PowerManager;
import android.util.Log;
import android.view.Gravity;
import android.view.Window;
import android.view.WindowManager;/*** Created by Administrator on 2017/7/10.*/
public class OnePixelActivity extends Activity {private BroadcastReceiver endReceiver;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//设置1像素Window window = getWindow();window.setGravity(Gravity.LEFT | Gravity.TOP);WindowManager.LayoutParams params = window.getAttributes();params.x = 0;params.y = 0;params.height = 1;params.width = 1;window.setAttributes(params);//结束该页面的广播endReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {finish();}};registerReceiver(endReceiver, new IntentFilter("finish"));//检查屏幕状态checkScreen();}@Overrideprotected void onResume() {super.onResume();checkScreen();Log.i("djtest", "OnePixelActivity: onResume");}@Overrideprotected void onStop() {super.onStop();Log.i("djtest", "OnePixelActivity: onStop");}@Overrideprotected void onDestroy() {super.onDestroy();Log.i("djtest", "OnePixelActivity: onDestroy");}/*** 检查屏幕状态  isScreenOn为true  屏幕“亮”结束该Activity*/private void checkScreen() {PowerManager pm = (PowerManager) OnePixelActivity.this.getSystemService(Context.POWER_SERVICE);boolean isScreenOn = pm.isScreenOn();if (isScreenOn) {finish();}}}

在MainActivity.java的onCreate中:

        //注册监听屏幕开启和关闭的广播OnePixelReceiver mOnepxReceiver = new OnePixelReceiver();IntentFilter intentFilter = new IntentFilter();intentFilter.addAction("android.intent.action.SCREEN_OFF");intentFilter.addAction("android.intent.action.SCREEN_ON");intentFilter.addAction("android.intent.action.USER_PRESENT");registerReceiver(mOnepxReceiver, intentFilter);

4、双服务保活

参考:
https://github.com/linliangliang/TwoProcess
https://www.cnblogs.com/lulj/p/7161317.html

(1)在main文件夹上右键,新建AIDL文件IMyAidlInterface.aidl:

// IMyAidlInterface.aidl
package com.jsc4.androidcppsafe;// Declare any non-default types here with import statementsinterface IMyAidlInterface {/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/
//    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
//            double aDouble, String aString);String getServiceName();
}

(2)在java文件夹下新建KeepServiceAlive文件夹,下面创建3个文件:
注意:必须点了运行工程,才能自动导入IMyAidlInterface类。
LocalService.java

package com.jsc4.androidcppsafe.KeepServiceAlive;import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;import com.jsc4.df.IMyAidlInterface;import java.util.Timer;
import java.util.TimerTask;/*** Created by lenovo on 2019/8/5.*/public class LocalService extends Service {private final static String TAG = LocalService.class.getName();private static int count = 0;private static Timer timer = null;private MyBinder mBinder;private ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {IMyAidlInterface iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);try {Log.i("LocalService", "connected with " + iMyAidlInterface.getServiceName());} catch (RemoteException e) {e.printStackTrace();}}@Overridepublic void onServiceDisconnected(ComponentName name) {if (Constans.INSTANCE.isOpenServiceDefend == 1) {Log.i(TAG, "链接断开,重新启动 RemoteService......");startService(new Intent(LocalService.this, RemoteService.class));bindService(new Intent(LocalService.this, RemoteService.class), connection, Context.BIND_IMPORTANT);}}};public LocalService() {}@Overridepublic void onCreate() {super.onCreate();if (timer == null) {timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {Log.i(TAG, "--" + count++);}}, 0, 1000);}}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {if (Constans.INSTANCE.isOpenServiceDefend == 1) {Log.i(TAG, "本地服务启动......");startService(new Intent(LocalService.this, RemoteService.class));bindService(new Intent(LocalService.this, RemoteService.class), connection, Context.BIND_IMPORTANT);}return START_STICKY;}@Overridepublic IBinder onBind(Intent intent) {mBinder = new MyBinder();return mBinder;}private class MyBinder extends IMyAidlInterface.Stub {@Overridepublic String getServiceName() throws RemoteException {return LocalService.class.getName();}}@Overridepublic void onDestroy() {// TODO 自动生成的方法存根super.onDestroy();try {if (timer != null) {timer.cancel();timer=null;}unbindService(connection);} catch (Exception e) {System.exit(0);}}
}

RemoteService.java

package com.jsc4.androidcppsafe.KeepServiceAlive;import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;import com.jsc4.df.IMyAidlInterface;import java.util.Timer;
import java.util.TimerTask;/*** Created by lenovo on 2019/8/5.*/public class RemoteService extends Service {private MyBinder mBinder;private static Timer timer = null;private static int count = 0;private ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {IMyAidlInterface iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);try {Log.i("RemoteService", "connected with " + iMyAidlInterface.getServiceName());} catch (RemoteException e) {e.printStackTrace();}}@Overridepublic void onServiceDisconnected(ComponentName name) {if (Constans.INSTANCE.isOpenServiceDefend == 1) {Toast.makeText(RemoteService.this, "链接断开,重新启动 LocalService", Toast.LENGTH_LONG).show();startService(new Intent(RemoteService.this, LocalService.class));bindService(new Intent(RemoteService.this, LocalService.class), connection, Context.BIND_IMPORTANT);}}};public RemoteService() {}@Overridepublic void onCreate() {super.onCreate();if (timer == null) {timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {Log.i("RemoteService", "==" + count++);}}, 0, 2000);}}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {if (Constans.INSTANCE.isOpenServiceDefend == 1) {Log.i("RemoteService", "RemoteService 启动...");bindService(new Intent(this, LocalService.class), connection, Context.BIND_IMPORTANT);}return START_STICKY;}@Overridepublic IBinder onBind(Intent intent) {mBinder = new MyBinder();return mBinder;}private class MyBinder extends IMyAidlInterface.Stub {@Overridepublic String getServiceName() throws RemoteException {return RemoteService.class.getName();}}@Overridepublic void onDestroy() {// TODO 自动生成的方法存根super.onDestroy();try {if (timer != null) {timer.cancel();timer=null;}unbindService(connection);} catch (Exception e) {System.exit(0);}}
}

Constans.java

package com.jsc4.androidcppsafe.KeepServiceAlive;/*** Created by lenovo on 2019/8/5.*/public enum Constans {//枚举类型实现单例INSTANCE;public static int openServiceDefend = 1;public static int stopServiceDefend = 0;public static int isOpenServiceDefend = 1;//是否开启进程守护,默认开启public static void setIsOpenServiceDefend(int isOpenServiceDefend) {Constans.isOpenServiceDefend = isOpenServiceDefend;}
}

(3)在AndroidMenifest.xml中添加:

        <serviceandroid:name=".KeepServiceAlive.LocalService"android:enabled="true"android:exported="true"/><serviceandroid:name=".KeepServiceAlive.RemoteService"android:enabled="true"android:exported="true"android:process=":RemoteProcess"/>

(4)在MainActivity.java中:

//********************************************************************************************************************************************
// 双进程保活机制 相关函数
//********************************************************************************************************************************************private void startBackService() {startService(new Intent(this, LocalService.class));}private void stopBackService() {stopService(new Intent(this, LocalService.class));}private void stopRemoteService() {stopService(new Intent(this, RemoteService.class));}private void endAllService() {Constans.INSTANCE.isOpenServiceDefend = Constans.INSTANCE.stopServiceDefend;//结束进程守护stopRemoteService();stopBackService();}
在oncreate里,添加:
// 启动双进程保活机制
startBackService();在ondestroy里,添加:
endAllService();// 结束双进程守护

5、前台服务保活

这是我重点想说的功能,该功能亲测有效。
注意:API>26后无法隐藏通知。

ForegroundService.java

package com.jsc4.androidcppsafe.ForegroundServiceKeepLive;import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;import javax.security.auth.login.LoginException;public class ForegroundService extends Service {private static final int SERVICE_ID = 1;@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();Log.i("djtest", "ForegroundService:  前台服务创建了");if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2){ // 4.3以下startForeground(SERVICE_ID, new Notification());}else if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O){ // 4.3-7.0startForeground(SERVICE_ID, new Notification());startService(new Intent(this, InnerService.class));}else{ // 8.0及以上NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);NotificationChannel channel = new NotificationChannel("channel", "andy", NotificationManager.IMPORTANCE_HIGH);manager.createNotificationChannel(channel);Notification notification = new NotificationCompat.Builder(this, "channel").build();startForeground(SERVICE_ID, notification);}}public static class InnerService extends Service{@Overridepublic void onCreate() {super.onCreate();Log.i("djtest", "ForegroundService: InnerService服务创建了");startForeground(SERVICE_ID, new Notification());stopSelf();}@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}}
}

AndroidMenifest.xml

        <service android:name=".ForegroundServiceKeepLive.ForegroundService"/><service android:name=".ForegroundServiceKeepLive.ForegroundService$InnerService"/>

MainActivity.java的oncreate中:

startService(new Intent(this, ForegroundService.class));

6、自启动管理

这是纯粹手机上设置。
将启动管理中的你的APP选择为手动控制。

【Android】锁屏后应用保活、拉活、双进程守护相关推荐

  1. 【Android 进程保活】应用进程拉活 ( 双进程守护 + JobScheduler 保活 | 成功率最高 | 推荐使用 )

    文章目录 一. 双进程守护保活 + JobScheduler 原理 二. 双进程守护保活 + JobScheduler 源码 1.JobService 代码 2.判定服务运行工具类 3.清单文件 4. ...

  2. 【Android 进程保活】应用进程拉活 ( 双进程守护保活 )

    文章目录 一. 双进程守护保活原理 二. 双进程守护保活完整源码 1.AIDL 接口 2.本地前台服务 Service 3.远程前台服务 Service 4.清单配置 5.启动两个服务 5.执行效果 ...

  3. Android 锁屏后handler计时失效

    目录 问题背景 handler失效的原因 排查了解到Doze机制 锁屏后计时解决方案 问题背景 需要记录用户播放音频的时长,我在一个service中开启handler,每隔一秒用户正在播放,将播放时长 ...

  4. Android 锁屏后Service服务保活(支持9.0)

    最近遇到个问题: 后台Service启动正常启动后,锁屏状态下大概80秒左右Service就被暂停了(并没有被杀死),唤醒屏幕后就继续执行. 解决方法: Service启动时创建一条通知,与其绑定,这 ...

  5. android 锁屏后定时器,iOS锁屏或者后台计时器定时解决方法

    我们知道,当程序进入后台时,计时器就会暂时停止,当重新进入程序时,计时器又会重新开始,有时候,我们需要在程序进入后台时,计时器依然能够计时,所以,就想到了一种解决方案,利用进入后台和前台的时间差来让计 ...

  6. Android进程保活拉活

    参考:腾讯视频相关视频公开课 学习资料: 探讨Android6.0及以上系统APP常驻内存(保活)实现-争宠篇 目录 一.进程的一些基本常识 二.如何保活 三.如何拉活 四.总结 一.进程的一些基本常 ...

  7. Android 基于高德地图的锁屏后定位和轨迹自动纠偏(离线版)

    目录 一.后台如何持续获取定位 1.后台以及锁屏后持续定位异常的原因以及应对方案探索 2.后台持续获取定位失败的应对方案 二.对坐标点进行加工处理 (1).为什么要加工处理 (2).如何加工处理 本文 ...

  8. Android仿网易云音乐中锁屏后在开锁界面插屏功能

    这个功能实现起来应该有多种方式,可以使用WindowManager创建window的方法. 在本文中我们使用开启一个Activity来充当锁屏界面. 实现步骤有以下两步: 一.后台开启一个Servic ...

  9. android app应用后台休眠,安卓手机锁屏后程序自动关闭,怎么设置手机app允许锁屏后台运行...

    原标题:安卓手机锁屏后程序自动关闭,怎么设置手机app允许锁屏后台运行 安卓手机锁屏后,很多程序就会自动关闭,实际上,这是安卓手机的一种保护机制.为了使系统能够流畅稳定的运行以及更加省电,它都会在手机 ...

最新文章

  1. python pandas 如何找到NaN、缺失值或者某些元素的索引名称以及位置,np.where的使用
  2. python 调用c++ ffmpeg接收yuv
  3. 下载python后怎样打开-下载python后如何启动
  4. sgmllib Introduction
  5. 必备知识:大数据处理应遵循的原则
  6. OpenStack —— DevStack配置安装
  7. Echarts图表的基本使用
  8. 游戏美术专业人士如何评价Share Creators智能数字资产管理系统
  9. canal.adapter启动报错Could not resolve placeholder ‘HOSTNAME%%.*‘
  10. CHD 常用web端口
  11. 八年老Android开发谈:垃圾中的战斗机,offer都发了,差点无缘Offer
  12. 常用计算机 启动bios,详解各种电脑开机怎么进入bios设置
  13. 计算机操作校本培训教材,小学教师校本培训教材.doc
  14. 我的洛谷冬日绘板计划
  15. android jsoup 课程表,使用jsoup爬取数据实现android课程表
  16. 隐马尔模型----四
  17. Java图片截图缩放工具
  18. 滚动字幕怎么制作,视频的滚动字幕如何制作?
  19. NLP之相似语句识别
  20. 投行排名大洗牌,高盛“跌落神坛

热门文章

  1. 【转】Qt 多线程串口通信问题?
  2. 20201217网警考试题目及题目源码(百度云网盘下载链接)
  3. XMLGregorianCalendar 保留年月日格式
  4. 如何设置hosts文件屏蔽网址
  5. HTML5ul如何去掉圆点,css ul怎么去掉点
  6. 如何调整计算机运存,在BIOS里怎么手动调整内存频率?
  7. (AM3517)修改u-boot与Linux调试串口以及文件系统显示终端串口(瑞泰ICETEK-AM3517)
  8. python学习:python serial
  9. 什么是音箱频率范围和频率响应
  10. Unity学习笔记--赛车的控制代码