安卓进程保活那些事,你知道多少?

产品需求


 像QQ、 微信、 高德, 永远不被杀掉。

那么他们是如何做到的呢?

  1. 跟手机厂商商务沟通,app放进系统白名单。
  2. 一像素保活法。
  3. 双进程守护保活法。
  4. 账号同步机制拉活。
  5. 后台播放一个无声的音频。
  6. 开启前台Service。
  7. JobScheduler拉活。
  8. sticky拉活。

他们这么做的原因是什么?

  1. IM(即时通信)保活 (重点 重点 重点)

但这样的做法过于流氓,影响Android手机的性能。不建议使用!!!!但是有时候又没有办法。

8.0之后就会有好的改观,毕竟8.0之后保活Android系统收紧(越来越难做了),但是统一推送联盟介入(IM可以保证),我觉得这事可以成。
统一推送联盟《中国绿色App公约》(以下简称“《公约》”)自2018年4月推出以来,得到了产业界和积极响应,并取得了行业的一致认可。2018年7月,泰尔终端实验室联合华为、小米、OPPO、vivo、腾讯、百度、阿里巴巴以及360共同发起联合行动:自2019年5月1日起,新上架和预置应用应基于Android8.0 (API等级26)及以上版本开发,拒绝上架和更新低API等级应用。这一方案将覆盖《公约》的绝大部分条款,使得正规渠道下载的安卓APP基本满足《公约》要求。

但是8.0之前还有一部分用户,所以保活还是要做,毕竟用户就是我们的“衣食父母”,如何保活呢?当然是降低omm_adj值,尽量保证进程不被系统杀死。

什么是oom_adj? 再介绍oom_adj是什么之前,我们需要知道Android的进程优先级

优先级进程名称oom_adj
1前台进程0
2可见进程1
3服务进程5
4后台进程6
5空进程9-25

什么是oom_adj?
oom(Out of Memory Adjustment)是Android的机制,系统会根据进程的优先级,给每个进程一个oom权重值,android系统在内存不足情况下进行内存调整的重要参数,系统会根据这个优先级去选择将哪些进程杀掉,以腾出空间保证更高优先级的进程能正常运行。

omm_adj < 0时:是系统进程,不会被杀死。
所以为了app保活,我们尽量oom_adj 的值

app保活按类型分为两种 :保活 和 拉活

保活

  1. 一像素保活法:在屏幕关闭时打开一个1px的activity,屏幕亮时关闭此activity(主题透明)

    KeepManagerUtils.getInstance().registerKeep(this);
    
       /**
    * @author:jhonjson
    * @date:2019/11/18 14:56 AM
    * @describe:1像素保活法 Manager
    */
    public class KeepManagerUtils {
       private static final KeepManagerUtils ourInstance = new KeepManagerUtils();
    
       public static KeepManagerUtils getInstance() {
           return ourInstance;
       }
    
       private KeepManagerUtils() {
       }
       private KeepLiveReceiver keepLiveReceiver;
       private WeakReference<Activity> mKeepLiveActivity;
       /**
        * 注册
        * @param context
        */
       public void registerKeepReceiver(Context context){
           IntentFilter filter = new IntentFilter();
           filter.addAction(Intent.ACTION_SCREEN_OFF);
           filter.addAction(Intent.ACTION_SCREEN_ON);
           keepLiveReceiver = new KeepLiveReceiver();
           context.registerReceiver(keepLiveReceiver, filter);
       }
    
       /**
        * 反注册
        * @param context
        */
       public void unRegisterKeepReceiver(Context context){
           if (null != keepLiveReceiver) {
               context.unregisterReceiver(keepLiveReceiver);
           }
       }
    
       /**
        * 启动1个像素的KeepLiveActivity
        * @param context
        */
       public void startKeepLive(Context context) {
           Intent intent = new Intent(context,KeepLiveActivity.class);
           intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
           context.startActivity(intent);
       }
    
       /**
        * finish1个像素的KeepLiveActivity
        */
       public void finishKeepLive() {
           if (null != mKeepLiveActivity) {
               Activity activity = mKeepLiveActivity.get();
               if (null != activity) {
                   activity.finish();
               }
               mKeepActivity = null;
           }
       }
    
       public void setKeepActivity(KeepLiveActivity mKeepLiveActivity) {
           this.mKeepLiveActivity = new WeakReference<Activity>(mKeepLiveActivity);
       }
    }
    
    public class KeepLiveReceiver extends BroadcastReceiver {
        private static final String TAG = "KeepLiveReceiver";
    
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Log.e(TAG, "receive:" + action);
            if (TextUtils.equals(action, Intent.ACTION_SCREEN_OFF)) {
                //灭屏 开启1px activity
                KeepManagerUtils.getInstance().startKeepLive(context);
            } else if (TextUtils.equals(action, Intent.ACTION_SCREEN_ON)) {
                //亮屏 关闭
                KeepManagerUtils.getInstance().finishKeepLive();
            }
        }
    }
    
    public class KeepLiveActivity extends Activity {
    
        private static final String TAG = "KeepLiveActivity";
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            Log.e(TAG, "启动keepLive");
    
            Window window = getWindow();
            //放在左上角
            window.setGravity(Gravity.START | Gravity.TOP);
    
            WindowManager.LayoutParams params = window.getAttributes();
            //设置宽高
            params.width = 1;
            params.height = 1;
            //设置起始坐标
            params.x = 0;
            params.y = 0;
            window.setAttributes(params);
    
            // KeepLiveActivity 创建一个弱引用
            KeepManagerUtils.getInstance().setKeepLive(this);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            Log.e(TAG, "关闭keepLive");
        }
    }
    
  2. 前台服务保活:启动一个前台服务,提高应用的优先级

    /**
         * 绑定服务
         *
         * @param context
         */
    
        public static void bindLocalService(Context context, ServiceConnection serviceConnection) {
            if (context == null || null == serviceConnection) {
                return;
            }
            //通过Intent指定服务端的服务名称和所在包,与远程Service进行绑定
            Intent intent = new Intent();
            intent.setClass(context, ForegroundService.class);
            Bundle bundle = new Bundle();
            intent.putExtras(bundle);
            //绑定服务,传入intent和serviceConnection对象
            context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
        }
    
        /**
         * 解绑服务
         *
         * @param context
         */
        public static void unBindLocalService(Context context, ServiceConnection serviceConnection) {
            if (context == null || null == serviceConnection) {
                return;
            }
            try {
                // 当需要多次调用doSomething()方法的时候,如果直接bindService是会报错的
                context.unbindService(serviceConnection);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    public class ForegroundService extends Service {
    
        private static final String TAG = "ForegroundService";
        privtae static final String KEY_CHANNEL = "新消息"
        private static final int SERVICE_ID = 1;
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
    
            Log.e(TAG, "ForegroundService 服务创建了");
    
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {//4.3以下
                //将service设置成前台服务,并且不显示通知栏消息
                startForeground(SERVICE_ID, new Notification());
            } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { //Android4.3-->Android7.0
                //将service设置成前台服务
                startForeground(SERVICE_ID, new Notification());
                //删除通知栏消息
                startService(new Intent(this, InnerService.class));
            } else { // 8.0 及以上
                //通知栏消息需要设置channel
                NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                NotificationChannel channel = new NotificationChannel(KEY_CHANNEL, "xx", NotificationManager.IMPORTANCE_NONE);
                if (manager != null) {
                    manager.createNotificationChannel(channel);
                    Notification notification = new NotificationCompat.Builder(this, KEY_CHANNEL).build
                    startForeground(SERVICE_ID, notification);
                }
            }
        }
    
        public static class InnerService extends Service {
    
            @Override
            public void onCreate() {
                super.onCreate();
                Log.e(TAG, "InnerService 服务创建了");
                // 让服务变成前台服务
                startForeground(SERVICE_ID, new Notification());
                // 关闭自己
                stopSelf();
            }
    
            @Nullable
            @Override
            public IBinder onBind(Intent intent) {
                return null;
            }
        }
    }
    
    <service android:name="com.xx.service.ForegroundService" />
    <service android:name="com.xx.service.ForegroundService$InnerService" />
    

参考资料:
Android之APP保活
Android后台Service已死 WorkManager崛起
史上最全android保活方案及比较分析

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值