Android - 保活(1)前台服务保活

作者: Allens_Jiang | 来源:发表于2018-01-31 11:55 被阅读2690次
    老婆保佑,代码无BUG

    前言

    项目中遇到一个需求,需要竟可能的上传用户的定位信息,引发了我对目前已知的保活手段的探究,同时也遇到过客户说,推送不能收到,不能像微信那样,MMP的,不想理客户

    目录

    • 一:如何创建前台服务
      • 1.DeskService 前台服务
      • 2.移除前台Service通知栏标志
      • 3.注册服务
      • 4.启动服务
    • 二:查看adj级别

    一:如何创建前台服务

    1.DeskService 前台服务

    package com.cpsc.livedemo;
    
    import android.app.Notification;
    import android.app.NotificationManager;
    import android.app.Service;
    import android.content.Intent;
    import android.os.Build;
    import android.os.IBinder;
    import android.support.annotation.Nullable;
    import android.util.Log;
    
    /**
     * 描述:
     * <p>
     * Created by allens on 2018/1/31.
     */
    
    public class DeskService extends Service {
    
        private static final String TAG = "DaemonService";
        public static final int NOTICE_ID = 100;
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            Log.d(TAG, "DaemonService---->onCreate被调用,启动前台service");
            //如果API大于18,需要弹出一个可见通知
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                Notification.Builder builder = new Notification.Builder(this);
                builder.setSmallIcon(R.mipmap.ic_launcher);
                builder.setContentTitle("KeepAppAlive");
                builder.setContentText("DaemonService is runing...");
                startForeground(NOTICE_ID, builder.build());
                // 如果觉得常驻通知栏体验不好
                // 可以通过启动CancelNoticeService,将通知移除,oom_adj值不变
                Intent intent = new Intent(this, CancelNoticeService.class);
                startService(intent);
            } else {
                startForeground(NOTICE_ID, new Notification());
            }
        }
    
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            // 如果Service被终止
            // 当资源允许情况下,重启service
            return START_STICKY;
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            // 如果Service被杀死,干掉通知
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                NotificationManager mManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                mManager.cancel(NOTICE_ID);
            }
            Log.d(TAG, "DaemonService---->onDestroy,前台service被杀死");
            // 重启自己
            Intent intent = new Intent(getApplicationContext(), DeskService.class);
            startService(intent);
        }
    
    }
    
    

    2.移除前台Service通知栏标志

    package com.cpsc.livedemo;
    
    import android.app.Notification;
    import android.app.NotificationManager;
    import android.app.Service;
    import android.content.Intent;
    import android.os.Build;
    import android.os.IBinder;
    import android.os.SystemClock;
    import android.support.annotation.Nullable;
    
    /**
     * 描述:
     * <p>
     * Created by allens on 2018/1/31.
     */
    
    public class CancelNoticeService extends Service {
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2) {
                Notification.Builder builder = new Notification.Builder(this);
                builder.setSmallIcon(R.mipmap.ic_launcher);
                startForeground(DeskService.NOTICE_ID, builder.build());
                // 开启一条线程,去移除DaemonService弹出的通知
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        // 延迟1s
                        SystemClock.sleep(1000);
                        // 取消CancelNoticeService的前台
                        stopForeground(true);
                        // 移除DaemonService弹出的通知
                        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                        manager.cancel(DeskService.NOTICE_ID);
                        // 任务完成,终止自己
                        stopSelf();
                    }
                }).start();
            }
            return super.onStartCommand(intent, flags, startId);
        }
    }
    
    

    3.注册服务

    
            <service
                android:name=".DeskService"
                android:enabled="true"
                android:exported="true"
                android:process=":daemon_service" />
    
    
            <service
                android:name=".CancelNoticeService"
                android:enabled="true"
                android:exported="true"
                android:process=":service" />
    

    4.启动服务

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

    二:查看adj级别

    adb shell

    ps|grep <package_name> 查看基本信息

    1|root@generic_x86:/ # ps|grep com.cpsc.livedemo                               
    u0_a63    6834  1348  1285208 43884 SyS_epoll_ b73712b5 S com.cpsc.livedemo
    u0_a63    6884  1348  1271160 28944 SyS_epoll_ b73712b5 S com.cpsc.livedemo:daemon_service
    
    解释
    u0_a63 USER 进程当前用户
    6834 进程ID
    1348 进程的父进程ID
    1285208 进程的虚拟内存大小
    43884 实际驻留”在内存中”的内存大小
    com.cpsc.livedemo 进程名

    cat /proc/<进程id>/oom_adj

    root@generic_x86:/ # cat /proc/6884/oom_adj                                    
    1
    root@generic_x86:/ # cat /proc/6884/oom_adj                                    
    1
    root@generic_x86:/ # 
    
    
    adj级别 说明
    UNKNOWN_ADJ 16 预留的最低级别,一般对于缓存的进程才有可能设置成这个级别
    CACHED_APP_MAX_ADJ 15 缓存进程,空进程,在内存不足的情况下就会优先被kill
    CACHED_APP_MIN_ADJ 9 缓存进程,也就是空进程
    SERVICE_B_ADJ 8 不活跃的进程
    PREVIOUS_APP_ADJ 7 切换进程
    HOME_APP_ADJ 6 与Home交互的进程
    SERVICE_ADJ 5 有Service的进程
    HEAVY_WEIGHT_APP_ADJ 4 高权重进程
    BACKUP_APP_ADJ 3 正在备份的进程
    PERCEPTIBLE_APP_ADJ 2 可感知的进程,比如那种播放音乐
    VISIBLE_APP_ADJ 1 可见进程
    FOREGROUND_APP_ADJ 0 前台进程
    PERSISTENT_SERVICE_ADJ -11 重要进程
    PERSISTENT_PROC_ADJ -12 核心进程
    SYSTEM_ADJ -16 系统进程
    NATIVE_ADJ -17 系统起的Native进程

    参考作者链接

    相关文章

      网友评论

        本文标题:Android - 保活(1)前台服务保活

        本文链接:https://www.haomeiwen.com/subject/nuhkzxtx.html