美文网首页
service保活

service保活

作者: 北方的天空2000 | 来源:发表于2017-03-28 16:47 被阅读1088次

    service保活

    在实际开发中,我们会遇到一些要求后台运行的service,但是现在Android手机型号太多,而且国内的系统都是各大厂商定制过得,加入了自己的一些优化设置(比如省电方面的)。造成的的问题是:当service在后台运行一段时间后,如果是比较耗电,会被系统kill,service里的逻辑操作也就停止了,对我们的业务造成困扰。那么该如何处理呢?

    主要有2种方法:手动设置和代码设置混合使用

    手动设置

    在手机设置界面中,有锁屏保护和省电管理或者手机管家中的内存优化都要进行处理。

    锁屏保护

    在360F4手机中,在设置-->电池和省电-->锁屏受保护应用:选中我们自己的app,就想选中微信一样,如果不选中微信的话,锁屏30分钟后,微信也会被kill掉。不同的手机锁屏后kill掉app的时间是不同的,有的没有这一项设置,有的是几分钟,360F4手机是30分钟。见下图:


    这里写图片描述

    省电管理

    手机管家

    这类App一般都是系统自带的,都是品牌商自己的软件,为了时间省电优化,通常都会把后台运行的app杀死,而且权限还挺高。不过也有用于自己安装的,比如:360手机卫士、腾讯手机管家、猎豹清理大师等,各种app的优化设置不同,这里介绍几个常见的

    360手机卫士

    我-->设置-->清理加速-->内存加速优化名单-->把我们的app加入优化忽略名单中


    这里写图片描述

    OPPO手机管家

    待定

    代码设置

    这也有2种方法:

    1. 给serviceA在配置一个守护它的serviceB,当我们的serviceA被杀死后,我们可以serviceB再重新开启A,
    2. 注册BroadcastReceiver,锁屏时获取“电源锁”,屏幕解锁是释放“电源锁”

    增加一个守护的service

    原理:在这个serviceB中开启一个Thread,每个1分钟查找正在运行的service,如果没有serviceA,那么久开启serviceA;如果有serviceA,那么就做处理。

    public class MonitorService extends Service {
    
        protected static boolean isCheck = false;
    
        protected static boolean isRunning = false;
    
        private static final String SERVICE_NAME = "com.cqc.walelock01.WakeLockService";
    
        @Override
        public void onCreate() {
            Log.d("MonitorService2", "MonitorService onCreate");
            super.onCreate();
    
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.d("MonitorService2", "MonitorService onStartCommand");
            new Thread() {
                @Override
                public void run() {
                    while (isCheck) {
                        try {
                            Thread.sleep(5 * 60 * 1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            Log.d("MonitorService2", "thread sleep failed" );
                        }
    
                        if (!isServiceWork(getApplicationContext(), SERVICE_NAME)) {
                            Log.d("MonitorService2", "WakeLockService轨迹服务已停止,正在重启轨迹服务");
                            startService(new Intent(MonitorService.this, WakeLockService.class));
                        } else {
                            Log.d("MonitorService2", "WakeLockService轨迹服务正在运行");
                        }
                    }
                }
    
            }.start();
            return super.onStartCommand(intent, flags, startId);
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        /**
         * 判断某个服务是否正在运行的方法
         *
         * @param mContext
         * @param serviceName 是包名+服务的类名(例如:com.baidu.trace.LBSTraceService)
         * @return true代表正在运行,false代表服务没有正在运行
         */
        public boolean isServiceWork(Context mContext, String serviceName) {
            boolean isWork = false;
            ActivityManager myAM = (ActivityManager) mContext
                    .getSystemService(Context.ACTIVITY_SERVICE);
            List<RunningServiceInfo> myList = myAM.getRunningServices(80);
            if (myList.size() <= 0) {
                return false;
            }
            for (int i = 0; i < myList.size(); i++) {
                String mName = myList.get(i).service.getClassName().toString();
                if (mName.equals(serviceName)) {
                    isWork = true;
                    break;
                }
            }
            return isWork;
        }
    }
    

    WakeLock :电源锁

    注册广播,当锁屏时获取电源锁,当屏幕解锁时释放电源锁,

    public class TrackReceiver extends BroadcastReceiver {
    
        private static final String TAG = "TrackReceiver";
    
        @SuppressLint("Wakelock")
        @Override
        public void onReceive(final Context context, final Intent intent) {
            final String action = intent.getAction();
            if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                Log.d(TAG,"screen off,acquire wake lock!");
                if (null != WakeLockService.wakeLock && !(WakeLockService.wakeLock.isHeld())) {
                    WakeLockService.wakeLock.acquire();
                }
            } else if (Intent.ACTION_SCREEN_ON.equals(action)) {
                Log.d(TAG,"screen on,release wake lock!");
                if (null != WakeLockService.wakeLock && WakeLockService.wakeLock.isHeld()) {
                    WakeLockService.wakeLock.release();
                }
            }
        }
    }
    

    获取电源锁是需要权限的

    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="android.permission.DEVICE_POWER"/>
    第二个权限AS会红色提示“这是系统app需要的权限”,这是提示不是报错,添加上就可以了
    
    这里写图片描述

    BroadcastReceiver有2种注册方法:静态注册和动态注册。
    我么这里采用动态注册的方法,原因是:

    receiver应该跟随serviceA的生命周期,当serviceA被销毁后,将不再获取电源锁;service开启后,再根据屏幕的变化判断是获取还是释放电源锁

    public class WakeLockService extends Service {
        //cpu保活
        private static boolean isRegister = false;
        protected static PowerManager pm = null;
        public static PowerManager.WakeLock wakeLock = null;
        public static TrackReceiver trackReceiver = new TrackReceiver();
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
        }
    
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            //动态注册
            if (!isRegister) {
                if (null == pm) {
                    pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
                }
                if (null == wakeLock) {
                    wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "track upload");
                }
                IntentFilter filter = new IntentFilter();
                filter.addAction(Intent.ACTION_SCREEN_OFF);
                filter.addAction(Intent.ACTION_SCREEN_ON);
                registerReceiver(trackReceiver, filter);
                isRegister = true;
            }
            return super.onStartCommand(intent, flags, startId);
        }
    
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            if (isRegister) {
                try {//销毁广播
                    unregisterReceiver(trackReceiver);
                    isRegister = false;
                } catch (Exception e) {
                }
            }
        }
    }
    

    这个service保活是从百度鹰眼官方Demo中提取的。
    网址:http://lbsyun.baidu.com/index.php?title=android-yingyan/guide/tracelive

    这里写图片描述

    Demo: http://git.oschina.net/ServiceDemo/WakeLock01
    其他相关:
    Android的PowerManager和PowerManager.WakeLock用法简析
    使用WakeLock使Android应用程序保持后台唤醒

    相关文章

      网友评论

          本文标题:service保活

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