service被斐郏活
在實(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)下圖:
省電管理
手機(jī)管家
這類(lèi)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)化忽略名單中
OPPO手機(jī)管家
待定
代碼設(shè)置
這也有2種方法:
- 給serviceA在配置一個(gè)守護(hù)它的serviceB守问,當(dāng)我們的serviceA被殺死后,我們可以serviceB再重新開(kāi)啟A,
- 注冊(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ù)的類(lèi)名(例如: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ò)兢孝,添加上就可以了
BroadcastReceiver有2種注冊(cè)方法:靜態(tài)注冊(cè)和動(dòng)態(tài)注冊(cè)窿凤。
我么這里采用動(dòng)態(tài)注冊(cè)的方法,原因是:
receiver應(yīng)該跟隨serviceA的生命周期跨蟹,當(dāng)serviceA被銷(xiāo)毀后雳殊,將不再獲取電源鎖;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 {//銷(xiāo)毀廣播
unregisterReceiver(trackReceiver);
isRegister = false;
} catch (Exception e) {
}
}
}
}
這個(gè)service保活是從百度鷹眼官方Demo中提取的。
網(wǎng)址:http://lbsyun.baidu.com/index.php?title=android-yingyan/guide/tracelive
Demo: http://git.oschina.net/ServiceDemo/WakeLock01
其他相關(guān):
Android的PowerManager和PowerManager.WakeLock用法簡(jiǎn)析
使用WakeLock使Android應(yīng)用程序保持后臺(tái)喚醒