service保活

service保活

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

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

手动设置

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

锁屏保护

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


service保活_第1张图片
这里写图片描述

省电管理

手机管家

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

360手机卫士

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


service保活_第2张图片
这里写图片描述

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 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();
            }
        }
    }
}

获取电源锁是需要权限的



第二个权限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

service保活_第3张图片
这里写图片描述

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

你可能感兴趣的:(service保活)