service保活

service?;?/h1>

在實(shí)際開(kāi)發(fā)中,我們會(huì)遇到一些要求后臺(tái)運(yùn)行的service,但是現(xiàn)在Android手機(jī)型號(hào)太多,而且國(guó)內(nèi)的系統(tǒng)都是各大廠商定制過(guò)得,加入了自己的一些優(yōu)化設(shè)置(比如省電方面的)。造成的的問(wèn)題是:當(dāng)service在后臺(tái)運(yùn)行一段時(shí)間后,如果是比較耗電,會(huì)被系統(tǒng)kill,service里的邏輯操作也就停止了,對(duì)我們的業(yè)務(wù)造成困擾。那么該如何處理呢?

主要有2種方法:手動(dòng)設(shè)置和代碼設(shè)置混合使用

手動(dòng)設(shè)置

在手機(jī)設(shè)置界面中,有鎖屏保護(hù)和省電管理或者手機(jī)管家中的內(nèi)存優(yōu)化都要進(jìn)行處理。

鎖屏保護(hù)

在360F4手機(jī)中,在設(shè)置-->電池和省電-->鎖屏受保護(hù)應(yīng)用:選中我們自己的app,就想選中微信一樣,如果不選中微信的話,鎖屏30分鐘后,微信也會(huì)被kill掉。不同的手機(jī)鎖屏后kill掉app的時(shí)間是不同的,有的沒(méi)有這一項(xiàng)設(shè)置,有的是幾分鐘,360F4手機(jī)是30分鐘。見(jiàn)下圖:


這里寫(xiě)圖片描述

省電管理

手機(jī)管家

這類App一般都是系統(tǒng)自帶的,都是品牌商自己的軟件,為了時(shí)間省電優(yōu)化,通常都會(huì)把后臺(tái)運(yùn)行的app殺死,而且權(quán)限還挺高。不過(guò)也有用于自己安裝的,比如:360手機(jī)衛(wèi)士、騰訊手機(jī)管家、獵豹清理大師等,各種app的優(yōu)化設(shè)置不同,這里介紹幾個(gè)常見(jiàn)的

360手機(jī)衛(wèi)士

我-->設(shè)置-->清理加速-->內(nèi)存加速優(yōu)化名單-->把我們的app加入優(yōu)化忽略名單中


這里寫(xiě)圖片描述

OPPO手機(jī)管家

待定

代碼設(shè)置

這也有2種方法:

  1. 給serviceA在配置一個(gè)守護(hù)它的serviceB,當(dāng)我們的serviceA被殺死后,我們可以serviceB再重新開(kāi)啟A,
  2. 注冊(cè)BroadcastReceiver,鎖屏?xí)r獲取“電源鎖”,屏幕解鎖是釋放“電源鎖”

增加一個(gè)守護(hù)的service

原理:在這個(gè)serviceB中開(kāi)啟一個(gè)Thread,每個(gè)1分鐘查找正在運(yùn)行的service,如果沒(méi)有serviceA,那么久開(kāi)啟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軌跡服務(wù)已停止,正在重啟軌跡服務(wù)");
                        startService(new Intent(MonitorService.this, WakeLockService.class));
                    } else {
                        Log.d("MonitorService2", "WakeLockService軌跡服務(wù)正在運(yùn)行");
                    }
                }
            }

        }.start();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    /**
     * 判斷某個(gè)服務(wù)是否正在運(yùn)行的方法
     *
     * @param mContext
     * @param serviceName 是包名+服務(wù)的類名(例如:com.baidu.trace.LBSTraceService)
     * @return true代表正在運(yùn)行,false代表服務(wù)沒(méi)有正在運(yùn)行
     */
    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 :電源鎖

注冊(cè)廣播,當(dāng)鎖屏?xí)r獲取電源鎖,當(dāng)屏幕解鎖時(shí)釋放電源鎖,

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

獲取電源鎖是需要權(quán)限的

<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.DEVICE_POWER"/>
第二個(gè)權(quán)限AS會(huì)紅色提示“這是系統(tǒng)app需要的權(quán)限”,這是提示不是報(bào)錯(cuò),添加上就可以了
這里寫(xiě)圖片描述

BroadcastReceiver有2種注冊(cè)方法:靜態(tài)注冊(cè)和動(dòng)態(tài)注冊(cè)。
我么這里采用動(dòng)態(tài)注冊(cè)的方法,原因是:

receiver應(yīng)該跟隨serviceA的生命周期,當(dāng)serviceA被銷毀后,將不再獲取電源鎖;service開(kāi)啟后,再根據(jù)屏幕的變化判斷是獲取還是釋放電源鎖

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) {
        //動(dòng)態(tài)注冊(cè)
        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) {
            }
        }
    }
}

這個(gè)service?;钍菑陌俣鳃椦酃俜紻emo中提取的。
網(wǎng)址:http://lbsyun.baidu.com/index.php?title=android-yingyan/guide/tracelive

這里寫(xiě)圖片描述

Demo: http://git.oschina.net/ServiceDemo/WakeLock01
其他相關(guān):
Android的PowerManager和PowerManager.WakeLock用法簡(jiǎn)析
使用WakeLock使Android應(yīng)用程序保持后臺(tái)喚醒

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容