Android如何降低service被殺死概率

讓app 的service常駐其實(shí)是很流氓的做法铭污,但是需求擺在那里。箭窜。毯焕。 但是要清除一點(diǎn):想百分百保活service在當(dāng)前是無法做到的磺樱,只能降低service被殺死的概率纳猫,曾經(jīng)看了多少篇網(wǎng)上大神的牛逼博客,從各個層面分析如何讓service不被殺死或者被殺死后重啟竹捉,特別是從Android系統(tǒng)底層分析芜辕,覺得特別牛逼,但是嘗試之后沒有啥用块差,以前做service鼻中活總是一個勁的鉆研android系統(tǒng)層的方式來保活service憨闰,實(shí)際上后來發(fā)現(xiàn)這是有點(diǎn)不對了状蜗,因?yàn)闀婕暗揭恍゛ndroid系統(tǒng)的兼容問題,有時候在這款手機(jī)上運(yùn)行良好鹉动,但是到另一款手機(jī)就不能正常運(yùn)行了轧坎,后來就去尋找從應(yīng)用層來降低service被殺死的概率,個人覺得從應(yīng)用層降低service被殺死的概率會比較穩(wěn)定

論Service為什么會被殺死

android對于進(jìn)程的殺死是有優(yōu)先級的:

  1. 前臺進(jìn)程泽示,也就是前臺activity

  2. 可見進(jìn)程眶根,就是一個透明的activity下面覆蓋著的那個activity就屬于可見的,但是這個透明的activity才屬于前臺

  3. 服務(wù)進(jìn)程边琉,也就是service

  4. 后臺進(jìn)程,一般情況下app按下home鍵后就變成后臺進(jìn)城了

  5. 空進(jìn)程 android系統(tǒng)給這些進(jìn)程設(shè)置了oom_adj值记劝,oom_adj值越小表示進(jìn)程的優(yōu)先級越高:


名稱

oom_adj

解釋

FOREGROUD_APP
0

前臺進(jìn)程

VISIBLE_APP
1

可見進(jìn)程

SECONDARY_SERVER
2

服務(wù)進(jìn)程

HIDDEN_APP
7

后臺進(jìn)程

EMPTY_APP
15

空進(jìn)程

如上的oom_adj值可能會根據(jù)不同手機(jī)系統(tǒng)有所不同变姨,但是只要是oom_adj越小,進(jìn)程優(yōu)先級越高厌丑,進(jìn)程越不容易被殺死定欧,當(dāng)android系統(tǒng)的內(nèi)存緊張的時候就會根據(jù)oom_adj來回收進(jìn)程,因此app在按下home鍵后被回收是正常的怒竿,因?yàn)閍pp按下home鍵盤后就編程后臺進(jìn)程了砍鸠,而后臺進(jìn)程的優(yōu)先級比服務(wù)進(jìn)程還要低,我們項(xiàng)目的app在按下home鍵盤被系統(tǒng)回收的主要原因有以下幾種:

  1. 我們的APP進(jìn)程啟動后占用內(nèi)存太大了耕驰,基本是打開APP就爷辱,然后到應(yīng)用程序管理里面一看,有60到70MB,現(xiàn)在已經(jīng)飆升到80MB

  2. 有些android深度定制系統(tǒng)的殺死策略太嚴(yán)格饭弓,進(jìn)程清理的太徹底双饥,導(dǎo)致我們APP的service很容易被殺殺殺,基本是手機(jī)一鎖屏弟断,過幾分鐘之后立刻就被殺死了

  3. 我們app的進(jìn)程優(yōu)先級太低咏花,按下home鍵后沒做任何處理,占的內(nèi)存又很高阀趴,所以被回收的概率也很高 綜上app進(jìn)程被殺死的根本原因:系統(tǒng)內(nèi)存出現(xiàn)不足時昏翰,會被Android的low memory killer殺掉
    針對以上問題,

幾種有效的service绷跫保活方案

最近一直在做公司的推送android端sdk棚菊,我們是把tcp連接寫在了java層,然后開一個service來維護(hù)這個tcp長連接排霉,那么問題來了窍株,要讓提升消息的可達(dá)率就必須保證tcp長連接一直存在,這里涉及到兩點(diǎn)惫ツ活球订,一種是service保活瑰钮,一種是tcp長連接泵疤玻活。

service崩饲矗活

比較古老的做法有兩種:

  1. 一種是用c在底層fork一個進(jìn)程出來定時掃描开睡,采用am命令啟動service,這種方式挺耗電的苟耻,而且有android系統(tǒng)的兼容問題篇恒,有些android系統(tǒng)是改過的,所以會導(dǎo)致c程序運(yùn)行失效凶杖,例如我遇到過的華為手機(jī)很多機(jī)型就不兼容胁艰,而且還有很嚴(yán)重的耗電問題

  2. 一種是fork一個進(jìn)程出來,然后把fork出來的進(jìn)程和app主進(jìn)程建立一條本地長連接來監(jiān)聽兩個進(jìn)程之間的狀態(tài)智蝠,一旦其中一個進(jìn)程斷掉之后另一個進(jìn)程就能檢測到tcp連接斷掉了腾么,然后采用am命令拉起service,這種可能沒有第一種耗電杈湾,但是依然存在這android系統(tǒng)兼容性問題

  3. 上述做法在android系統(tǒng)是5.0以下的手機(jī)運(yùn)行良好解虱,因?yàn)榫退闶鞘謾C(jī)一鍵清理的時候也只是清理app主進(jìn)程,而不會清理fork出來的進(jìn)程漆撞,所以service會被成功拉起殴泰;而在android5.0以上的手機(jī)中于宙,一旦系統(tǒng)一鍵清理,或者系統(tǒng)后臺自動清理艰匙,那么會殺死跟app進(jìn)程有關(guān)的進(jìn)程組限煞,也包括fork出來的進(jìn)程,所以android5.0以上的手機(jī)這個fork進(jìn)程就貌似是一個雞肋员凝,增加了耗電署驻,增加了內(nèi)存消耗,甚至增加了service會被系統(tǒng)清理的概率健霹,而且舊的android系統(tǒng)在系統(tǒng)清理的時候據(jù)說是只會清理java進(jìn)程旺上,不會清理c進(jìn)程,但是新的android系統(tǒng)全名提升了安全性糖埋,會徹底清理app相關(guān)的所有進(jìn)程

  4. 現(xiàn)在守護(hù)進(jìn)程已經(jīng)漸漸無效了宣吱,所以一些專業(yè)做推送服務(wù)的公司已經(jīng)把守護(hù)進(jìn)程這個保活手段早早的去掉了瞳别,人家用的是更加高端有效的做法:TCP長連接多路復(fù)用征候,后面在介紹


在應(yīng)用層,我嘗試過的祟敛,了解到的有效的service卑贪樱活手段有以下幾種

  1. 在onDestroy方法里面重啟service,或者發(fā)個廣播出來觸發(fā)啟動service馆铁,這個要求service在被殺死的時候如果有調(diào)用onDestroy()方法跑揉,那么service就能被重啟,在魅族5.0系統(tǒng)上埠巨,我進(jìn)入到應(yīng)用管理历谍,找到正在運(yùn)行的應(yīng)用,點(diǎn)擊停止辣垒,這時候service是會跑onDestroy()方法的望侈,我親自測試過

  2. onStartCommand中的flag設(shè)置成START_STICKY,或者直接return START_STICKY勋桶,這個有些舊版的手機(jī)在手機(jī)一鍵清理后service被殺死后會重啟起來脱衙,但是在一些國產(chǎn)定制機(jī),例如小米哥遮,華為,魅族等手機(jī)就無效了陵究,在android源碼中注釋如下:

/** * Constant to return from {@link #onStartCommand}: if this service's * process is killed while it is started 
(after returning from * {@link #onStartCommand}), then leave it in the started state but * don't retain this 
delivered intent. Later the system will try to * re-create the service. Because it is in the started state, it will * 
guarantee to call {@link #onStartCommand} after creating the new * service instance; if there are not any 
pending start commands to be * delivered to the service, it will be called with a null intent * object, so you must 
take care to check for this. * * <p>This mode makes sense for things that will be explicitly started * and 
stopped to run for arbitrary periods of time, such as a service * performing background music playback. */ 
public static final int START_STICKY = 1;

說的是如果service在已經(jīng)被啟動的時候被停止眠饮,那么系統(tǒng)將保持service的啟動狀態(tài),但是不會把原先的intent傳遞進(jìn)來铜邮,然后系統(tǒng)會嘗試這重新創(chuàng)建這個service仪召,因?yàn)榇藭rservice是在啟動狀態(tài)寨蹋,所以它一定會在被創(chuàng)建后調(diào)用onStartCommand()方法,但是由于intent沒有被保存下載扔茅,所以里面的參數(shù)intent有可能為null已旧,所以要做下判斷,這個模式可以保證service被殺死后重新啟動起來召娜,而且避免在任意時間被停止运褪,就如后臺音樂播放;但是有一點(diǎn)要生命:這個僅僅是針對android原生系統(tǒng)玖瘸,對于定制的android系統(tǒng)如果有對這方面做過優(yōu)化秸讹,那這個也將無效,而且如果是應(yīng)用進(jìn)程被直接殺死雅倒,這個方法也無效

  1. 把進(jìn)程做拆分璃诀,分成app進(jìn)程和push進(jìn)程,其實(shí)就是把push進(jìn)程做到最小蔑匣,push進(jìn)程盡量不做業(yè)務(wù)邏輯處理劣欢,只做數(shù)據(jù)轉(zhuǎn)發(fā)和接收,這樣push進(jìn)程占用的內(nèi)存就變小了裁良,被回收的幾率自然也下降

  2. 提升app進(jìn)程凿将,push進(jìn)程的優(yōu)先級;一般app進(jìn)程里面會有一個常駐的service趴久,push進(jìn)程也會有一個維護(hù)長連接的service丸相,把這兩個service都設(shè)置成前臺進(jìn)程,采用startForeground(id, new Notification())彼棍,但是在sdk version > 18的時候通知欄會默認(rèn)顯示一個應(yīng)用通知灭忠,這個是非常不友好的,有些用戶就會反饋說通知欄有哥這個座硕,表示不爽等等弛作。。华匾。通過一些渠道了解到映琳,利用android系統(tǒng)的一個bug可以解決上述問題:在Service里面建一個InnerService,這個InnerService必須是static類型的蜘拉,否則無法啟動這個內(nèi)部service萨西,然后啟動InnerService,同時把Service和InnerService都設(shè)置成前臺service旭旭,并綁定同一個id谎脯,然后再關(guān)閉掉InnerService,這時候通知欄的顯示就沒了持寄,記住只是stop InnerService而不是stopForeground()源梭,此時service依然是前臺進(jìn)程娱俺,親測有效,下面來展示以下測試的過程和結(jié)果: 外層service的部分代碼

public static class InnerService extends Service { 

@Override 
public void onCreate() {
     super.onCreate(); 
    startForeground(notificationId, new Notification()); 
    SyncLogUtil.i("inner service onCreate..."); 
    stopSelf(); 
} 

@Override
 public int onStartCommand(Intent intent, int flags, int startId) { 
    SyncLogUtil.i("inner service onStartCommand..."); 
    return START_NOT_STICKY; 
} 

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

@Override 
public void onDestroy() { 
    super.onDestroy(); 
    SyncLogUtil.i("inner service destroy!"); } 
} 

@Override 
public void onCreate() { 
    super.onCreate(); 
    SyncLogUtil.init(getApplicationContext()); 
    startForeground(notificationId, new Notification()); startInnerService(); 
}

 private void startInnerService() { 
    Intent intent = new Intent(this, InnerService.class); 
    startService(intent); 
}

進(jìn)入adb命令行: 未設(shè)置前臺service的app進(jìn)程:
shell@cancro:/ $ ps | grep com.xtc.watchps | grep com.xtc.watchu0_a517 11829 245 1023556 131048 ffffffff 00000000 S com.xtc.watchu0_a517 11919 1 948 108 ffffffff 00000000 S /data/data/com.xtc.watch/app_bin/daemonu0_a517 12092 245 890632 46984 ffffffff 00000000 S com.xtc.watch:push

app界面在前臺

shell@cancro:/ $ cat proc/11829/oom_adjcat proc/11829/oom_adj0

app界面在后臺(按下home鍵)

shell@cancro:/ $ cat proc/11829/oom_adjcat proc/11829/oom_adj7

app界面在后臺(按返回鍵)

shell@cancro:/ $ cat proc/11829/oom_adjcat proc/11829/oom_adj7

設(shè)置前臺service的app進(jìn)程:

shell@cancro:/ $ ps | grep com.xtc.watchps | grep com.xtc.watchu0_a518 27381 245 1015104 130352 ffffffff 00000000 R com.xtc.watchu0_a518 27481 245 890620 46544 ffffffff 00000000 S com.xtc.watch:push

app界面在前臺

shell@cancro:/ $ cat proc/27381/oom_adjcat proc/27381/oom_adj0

app界面在后臺(按下home鍵)

shell@cancro:/ $ cat proc/27381/oom_adjcat proc/27381/oom_adj2

app界面在后臺(按返回鍵)

shell@cancro:/ $ cat proc/27381/oom_adjcat proc/27381/oom_adj2

通過以上兩種對比可知废麻,app進(jìn)程設(shè)置了前臺service的app進(jìn)程在退到后臺后依然保持oom_adj = 2的進(jìn)程優(yōu)先級荠卷,相當(dāng)于app退到后臺后仍然是可視進(jìn)程,而沒有設(shè)置前臺service的app進(jìn)程的oom_adj = 7編程了后臺進(jìn)程
設(shè)置前臺service后app的push進(jìn)程
shell@cancro:/ $ ps | grep sync.pushps | grep sync.pushu0_a517 8738 245 894808 46452 ffffffff 00000000 S sync.push

app界面在前臺

shell@cancro:/ $ cat proc/8738/oom_adjcat proc/8738/oom_adj1

app界面在后臺(按下home鍵)

shell@cancro:/ $ cat proc/8738/oom_adjcat proc/8738/oom_adj2

app界面在后臺(按返回鍵)

shell@cancro:/ $ cat proc/8738/oom_adjcat proc/8738/oom_adj2


對比微信:

微信的pushshell@cancro:/ $ ps | grep com.tencent.mmps | grep com.tencent.mmu0_a337 12143 245 915440 61144 ffffffff 00000000 S com.tencent.mm:pushu0_a337 17492 245 1191424 96248 ffffffff 00000000 S com.tencent.mmapp

界面在前臺

shell@cancro:/ $ cat proc/12143/oom_adjcat proc/12143/oom_adj1app

界面在后臺(按下home鍵)

shell@cancro:/ $ cat proc/12143/oom_adjcat proc/12143/oom_adj2app

界面在后臺(按返回鍵)

shell@cancro:/ $ cat proc/12143/oom_adjcat proc/12143/oom_adj2微信appshell@cancro:/ $ ps | grep com.tencent.mmps | grep com.tencent.mmu0_a337 12143 245 915440 61144 ffffffff 00000000 S com.tencent.mm:pushu0_a337 17492 245 1191424 96436 ffffffff 00000000 S com.tencent.mmapp

界面在前臺

shell@cancro:/ $ cat proc/17492/oom_adjcat proc/17492/oom_adj0app

界面在后臺(按下home鍵)

shell@cancro:/ $ cat proc/17492/oom_adjcat proc/17492/oom_adj2app

界面在后臺(按返回鍵)

shell@cancro:/ $ cat proc/17492/oom_adjcat proc/17492/oom_adj2

可以看到我們app的進(jìn)程優(yōu)先級已經(jīng)和微信一樣了烛愧,進(jìn)程優(yōu)先級提升了油宜,其實(shí)已經(jīng)在很大程度上降低了app進(jìn)程或者push進(jìn)程被殺死的概率了

  1. 守護(hù)Service,開一個Service單獨(dú)運(yùn)行在獨(dú)立的進(jìn)程中屑彻,在守護(hù)service里面定時去start app進(jìn)程的service验庙,而app進(jìn)程里面的service也定時去start守護(hù)service;或者在這兩個service之間維護(hù)一條tcp連接也可以做到實(shí)時檢測

  2. 采用bind service加上start service社牲,因?yàn)閎ing service之后即使stop service那service也還是存在粪薛,不會調(diào)用onDestroy,只有等service被解綁之后才用調(diào)用onDestroy搏恤,有時候你到應(yīng)用程序里面去停止了進(jìn)程的service违寿,列表里面看運(yùn)行中的程序是找不到service了,但是實(shí)際上service還是在運(yùn)行的熟空,過一會兒就又刷出來了

  3. 捕獲第三方推送的廣播接收藤巢,在app程序中添加一個靜態(tài)廣播專門用來接收第三方的廣播,收到廣播后就喚醒Service息罗,例如捕獲小米推送掂咒,個推,但是有些第三方的廣播是有權(quán)限限制的迈喉,因此不是所有的第三方廣播都能被收到

  4. 監(jiān)聽系統(tǒng)靜態(tài)廣播绍刮,開機(jī)自啟廣播,網(wǎng)絡(luò)變換廣播挨摸,USB接入和拔出的廣播孩革,系統(tǒng)屏幕解鎖廣播,這幾個廣播都是靜態(tài)注冊的廣播得运;但是這種方式也是不可靠的膝蜈,因?yàn)橛行┦謾C(jī)在程序停止運(yùn)行之后連靜態(tài)廣播都不能收到了。熔掺。饱搏。增加廣播監(jiān)聽只是在一定程度上降低service被殺后重新拉起的概率,但是系統(tǒng)的靜態(tài)廣播在app被殺死后是無法收到的

  5. 監(jiān)聽第三方的靜態(tài)自定義廣播置逻,靜態(tài)自定義廣播是有可能可以被接收的推沸,只要發(fā)送方按照一定的方式發(fā)送就行,具體可以參考:如何在app被殺死的情況下仍然可接收靜態(tài)自定義廣播诽偷,這邊有個前提就是第三方推送發(fā)送廣播的時候必須要按照指定方式發(fā)送才可行坤学,優(yōu)點(diǎn)是無需接入第三方推送,只是監(jiān)聽他們的廣播即可报慕,很輕量級

  6. 接入第三方推送服務(wù)深浮,但是我們不用他們的推送,我們還是用我們自己的推送眠冈,不過我們可以捕捉到他們的一些廣播,service啟動的action等來讓它們來觸發(fā)拉起我們的程序布卡,比如說集成友盟推送雇盖,當(dāng)啟動uc的時候可能會發(fā)一些廣播,通過action啟動一些service贸街,我們就專門監(jiān)聽這種廣播狸相,監(jiān)聽這些action就能成功的拉起我們的服務(wù),這種辦法是通過第三方推送來觸發(fā)我們的推送服務(wù)脓鹃,人家是專門做推送的瘸右,更專業(yè),那我們就直接用唄尊浓,達(dá)到不使用他們的推送栋齿,但是們的app也加入了互相喚醒的app 的行列中去了

  7. 市面上的推送服務(wù)現(xiàn)在大多使用長連接多路復(fù)用來保證app互相喚醒,就是一臺設(shè)備商有多個app集成了一種推送瓦堵,那么只會有一個宿主app會保持跟服務(wù)器之間的長連接,其他app都是共享這條長連接澜驮,宿主app就負(fù)責(zé)路由各個app的推送消息惋鸥,當(dāng)有一個app存活悍缠,其他app都被殺死耐量,這是后有消息過來,那么這個活著的app就會把死掉的app喚醒趴拧,而app之間的互相喚醒是采用action來start service的方式喚醒的山叮,我了解到友盟推送和個推都是這么做的;但是長連接多路復(fù)用的蹦杂郑活效果是建立在用戶量上面的锐借,用戶量大了挂谍,集成推送的app多了口叙,喚醒幾率就越大嗅战,喚醒效果就越好,例如一些高頻使用的app疟呐,uc东且,支付寶等,用戶可能頻繁的點(diǎn)開這些app鲁冯,那么就會經(jīng)常喚醒其他app,長連接多路復(fù)用因?yàn)樽龅搅诉B接共享所以更加省電薯演,省內(nèi)存秧了;但是的但是,道高一尺衡创,魔高一丈,嘴型android 6.0系統(tǒng)已經(jīng)禁止app互相喚醒了璃氢。。。而且去掉了網(wǎng)絡(luò)切換靜態(tài)廣播

  8. 其實(shí)最最根本的解決方案還是把a(bǔ)pp直接加入手機(jī)白名單~隘竭,絕對百分百不會被殺死,親測有效尊剔,有些人認(rèn)為為啥微信消息接收那么即時菱皆,微信不會被手機(jī)清理,因?yàn)槲⑿乓呀?jīng)牛逼到手機(jī)廠商自動把微信和QQ加入了手機(jī)白名單京痢,小米系統(tǒng)更是直接把微信app的相關(guān)進(jìn)程設(shè)置成守護(hù)進(jìn)程: 小米4c手機(jī)進(jìn)入adb命令行: 輸入dumpsys activity
    這里寫圖片描述

    app的push進(jìn)程設(shè)置前臺service后sync.push的進(jìn)程優(yōu)先級是vis篷店,可視進(jìn)程 而微信app的push進(jìn)程com.tencent.mm:push的進(jìn)程優(yōu)先級的prcp,protect process保護(hù)進(jìn)程方淤,可能是小米手機(jī)自定義的進(jìn)程優(yōu)先級別


下面幾種是不知道有沒有效果的service碧阊辏活手段:

  1. 配置文件里面加入android:persistent=”true”提升進(jìn)程優(yōu)先級,但是這個貌似只有對系統(tǒng)應(yīng)用才有效讳苦,具體原理不說了吩谦,自己百度

  2. 設(shè)置service的action優(yōu)先級:

<service android:name="com.xtc.sync.connection.ConnectionService" android:process="sync.push" 
android:enabled="true" android:exported="false" android:persistent="true"> <intent-filter 
android:priority="0x7fffffff"> <action android:name="com.xtc.sync.connection_service" /> </intent-filter> 
</service>

這種效果我感覺微乎其微,即使不設(shè)置也沒啥影響

TCP長連接贝活:

心跳包保持長連接暢通,定時發(fā)心跳包是為了避免NAT草描,把發(fā)送心跳包的代碼寫到維護(hù)長連接的Service里面览绿,每次發(fā)心跳包就start service穗慕,因?yàn)樾奶怯敏[鐘實(shí)現(xiàn)的逛绵,有可能service死了,但是系統(tǒng)鬧鐘還是在正常執(zhí)行的术浪,這時候就能把維護(hù)長連接的service拉起,然后只要心跳包一超時就立馬把連接斷開重連硕蛹,這是為了避免無效連接硕并,關(guān)于無效連接請看TCP長連接的一些坑冗余心跳包,手機(jī)鎖屏解鎖倔毙,網(wǎng)絡(luò)切換,USB接入贵试,拔出凯正,app帳戶登錄都發(fā)一個心跳包,長連接請求超時也補(bǔ)發(fā)一個心跳包斷線重連策略桑滩,采用時間間隔遞增,第一次斷開馬上連上运准,連接失敗隔2s再重連缭受,重連失敗再隔4s再重連米者,以此類推宇智,至于時間間隔可以自己指定比較適用的算法計(jì)算出來胰丁,這時候也會遇到要是網(wǎng)絡(luò)閃斷的情況會導(dǎo)致連接連傷后又馬上斷開,然后馬上重連成功后連接再次斷開机蔗,這樣也會導(dǎo)致短時間內(nèi)重連多次甘萧,這時候可以對重連也做連接間隔的遞增策略扬卷,如果檢測到上次連接成功的時間在1s之內(nèi)那么就采用時間間隔遞增重連邀泉,如果上次重連在比較久之前了钝鸽,那么就不采用時間間隔遞增重連,直接正常重連 心跳包周期策略因谎,當(dāng)前我們的app只對wifi網(wǎng)絡(luò)和數(shù)據(jù)網(wǎng)絡(luò)指定了不同的心跳包财岔,沒有很詳細(xì)的心跳包策略河爹,但其實(shí)后期可以指定詳細(xì)的心跳包策略來進(jìn)一步提升tcp連接的穩(wěn)定性 在手機(jī)休眠的時候采用系統(tǒng)鬧鐘可以短暫喚醒cpu執(zhí)行任務(wù)咸这,例如利用系統(tǒng)鬧鐘來執(zhí)行周期心跳媳维,在網(wǎng)絡(luò)數(shù)據(jù)返回的時候侄刽,也會喚醒cpu醋安,所以不需要wakelock茬故,因?yàn)閺钠渌懒私獾剑?/p>

a. Alarm喚醒后磺芭,有足夠的cpu時間來發(fā)包钾腺,所以不用wakelock
b. 網(wǎng)絡(luò)回包可喚醒機(jī)器(但是在api level >= 23就關(guān)閉了所有網(wǎng)絡(luò))姻报,而且小米4c手機(jī)鎖屏后過一會兒也會自動禁止網(wǎng)絡(luò)吴旋,導(dǎo)致所有連接全部失效荣瑟,小米4c手機(jī)的這種情況是我親測的笆焰,確實(shí)有這種問題跨進(jìn)程通信在我們的sdk里面是采用aidl和廣播實(shí)現(xiàn),但是aidl有時候會有問題不皆,在service被殺死的時候會爆出DeadObjectException熊楼,就是表示service已經(jīng)被殺死了粟焊,但是可能程序依然在執(zhí)行aidl的方法项棠,而且aidl代碼冗余香追,廣播的話傳輸?shù)臄?shù)據(jù)大小有限制透典,可以考慮采用Socket和ServerSocket來實(shí)現(xiàn)進(jìn)程間的通信税弃,采用TCP連接實(shí)現(xiàn)進(jìn)程間的通信可以實(shí)現(xiàn)兩個進(jìn)城之間互相監(jiān)聽,只要有一個進(jìn)程死了西壮,另一個進(jìn)程馬上就能收到反饋,這時候可以做相關(guān)操作抡草,例如再把死掉的進(jìn)程拉起來等

針對不同定制系統(tǒng)的問題:

  1. 小米MIUI和魅族flyme是兩個比較深android定制系統(tǒng),超級坑超級坑签杈,系統(tǒng)清理策略太特么嚴(yán)格了铣除,一清全死尚粘,怎么起都起不來秉继,秒殺一切推送,針對這種機(jī)型我們只能說月褥,可以的話默默的加入白名單吧,親决左,要不你就去跟手機(jī)廠商談合作,要不你就用他們家的推送,例如MiPush

  2. 三星手機(jī)倒是還好码荔,基本按照以上的做法在大部分5.0一下的系統(tǒng)都可以在很大程度上保持service常駐,因?yàn)槿堑腶ndroid系統(tǒng)是比較純凈的

  3. 華為的手機(jī)系統(tǒng)也是定制的,不過也不知道為啥堂鲤,我們的c守護(hù)進(jìn)程在其他手機(jī)上跑得好好的,在華為手機(jī)上跑超級耗電,而且無法start service,因?yàn)檫@個c程序是網(wǎng)上大牛寫的戒良,不是我寫的,我也找不到原因所在,甚至于在華為某些機(jī)型上面會導(dǎo)致超級耗電韵洋,要不就是導(dǎo)致手機(jī)超級卡頓,要重啟才能使用副编,所以華為的定制機(jī)我們是把守護(hù)進(jìn)城去掉了,所以我們的service變得非常脆弱

  4. 市面上的主流手機(jī)就是小米队腐,三星柴淘,華為为严,魅族荸型,vivo辕狰,oppo了,但是當(dāng)我們專門針對這些進(jìn)行做適配的時候,版本正式發(fā)布了滞诺,你會發(fā)現(xiàn)反饋問題的用戶往往都不是使用這些手機(jī)。。。都是使用什么聯(lián)想厨剪,htc等等好坑的手機(jī)祷膳,有廣播發(fā)送需要一兩分鐘才能收到

  5. 根據(jù)手機(jī)渠道來分版本發(fā)布陶衅,小米版,魅族版等等


經(jīng)過測試采用上述方式后直晨,只要不使用手機(jī)自身的一鍵清除搀军,按下home鍵后service常駐情況后臺的機(jī)型:

  1. 小米4C——4.4Android系統(tǒng)——service可以常駐(但是守護(hù)進(jìn)程無效,因?yàn)樾∶椎囊绘I清理太徹底)

  2. 魅族MX5——5.0Android系統(tǒng)——service在手機(jī)鎖屏后幾分鐘就被殺死并且無法重啟(守護(hù)進(jìn)程無效勇皇,魅族一鍵清理更徹底)

  3. 華為榮耀6罩句,6plus——5.0Android系統(tǒng)——service在手機(jī)鎖屏后馬上就被殺死并無法重啟(守護(hù)進(jìn)程無效,守護(hù)進(jìn)程導(dǎo)致嚴(yán)重耗電敛摘,守護(hù)進(jìn)程無法正常運(yùn)行)

  4. 華為很舊的機(jī)型—–4.4Android系統(tǒng)——service常駐后臺门烂,就算被殺死或者手機(jī)一鍵清理也會被守護(hù)進(jìn)程拉起(守護(hù)進(jìn)程有效,守護(hù)進(jìn)程基本不會被殺死)

  5. 華為meta7——4.4Android系統(tǒng)——service常駐后臺(未知守護(hù)進(jìn)程是否有效,待測)

  6. 三星部分機(jī)型service可以常駐屯远,但是部分機(jī)型service無法常駐并且守護(hù)進(jìn)程無效蔓姚,具體待測

  7. vivo和oppo的手機(jī)上service基本無法常駐,死的一干二凈明明白白慨丐,絲毫沒有任何掙扎的痕跡

  8. android5.0以上系統(tǒng)守護(hù)進(jìn)程據(jù)說是無效赂乐,但是我沒有親測,因?yàn)?.0以下的android系統(tǒng)只是殺死App主進(jìn)程咖气,但是5.0以上的android系統(tǒng)是殺死跟App有關(guān)的所有進(jìn)程組挨措,所以game over。崩溪。浅役。

  9. 但是最最特么坑爹的是居然能看到確實(shí)有些app可以在各種各樣的機(jī)型上保持service常駐。伶唯。觉既。我也是醉了,雖然有些是跟廠商合作乳幸,但是我覺的應(yīng)該還是有其他辦法能再次提升service常駐的概率瞪讼,至少保持按下home鍵后手機(jī)鎖屏service不被殺死吧,看到這里要是有大神知道的是什么方式的請指導(dǎo)指導(dǎo)粹断,分享分享符欠,給小弟一個方向,多謝


不同的andorid系統(tǒng)版本:

  1. android5.0開始系統(tǒng)做的越來越安全了瓶埋,5.0以下start service可以隱式啟動希柿,就是不設(shè)置intent的package,但是5.0開始就必須要設(shè)置了

  2. 最近剛出的android N已經(jīng)把靜態(tài)廣播網(wǎng)絡(luò)變換廣播去掉了养筒。曾撤。。這個對我們來說實(shí)在是巨大的打擊晕粪,編程了只能動態(tài)注冊挤悉。。巫湘。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末装悲,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子剩膘,更是在濱河造成了極大的恐慌衅斩,老刑警劉巖盆顾,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怠褐,死亡現(xiàn)場離奇詭異,居然都是意外死亡您宪,警方通過查閱死者的電腦和手機(jī)奈懒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門奠涌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人磷杏,你說我怎么就攤上這事溜畅。” “怎么了极祸?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵慈格,是天一觀的道長。 經(jīng)常有香客問我遥金,道長浴捆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任稿械,我火速辦了婚禮选泻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘美莫。我一直安慰自己页眯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布厢呵。 她就那樣靜靜地躺著窝撵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪襟铭。 梳的紋絲不亂的頭發(fā)上忿族,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機(jī)與錄音蝌矛,去河邊找鬼道批。 笑死,一個胖子當(dāng)著我的面吹牛入撒,可吹牛的內(nèi)容都是我干的隆豹。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼茅逮,長吁一口氣:“原來是場噩夢啊……” “哼璃赡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起献雅,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤碉考,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后挺身,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體侯谁,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了墙贱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片热芹。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖惨撇,靈堂內(nèi)的尸體忽然破棺而出伊脓,到底是詐尸還是另有隱情,我是刑警寧澤魁衙,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布报腔,位于F島的核電站,受9級特大地震影響剖淀,放射性物質(zhì)發(fā)生泄漏榄笙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一祷蝌、第九天 我趴在偏房一處隱蔽的房頂上張望茅撞。 院中可真熱鬧,春花似錦巨朦、人聲如沸米丘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拄查。三九已至,卻和暖如春棚蓄,著一層夾襖步出監(jiān)牢的瞬間堕扶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工梭依, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留稍算,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓役拴,卻偏偏與公主長得像糊探,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子河闰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容