Android開發(fā)如何監(jiān)聽讓service服務(wù)不被殺死_第1頁
Android開發(fā)如何監(jiān)聽讓service服務(wù)不被殺死_第2頁
Android開發(fā)如何監(jiān)聽讓service服務(wù)不被殺死_第3頁
Android開發(fā)如何監(jiān)聽讓service服務(wù)不被殺死_第4頁
Android開發(fā)如何監(jiān)聽讓service服務(wù)不被殺死_第5頁
已閱讀5頁,還剩4頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、項(xiàng)目要實(shí)現(xiàn)這樣一個(gè)效果:運(yùn)行后,要有一個(gè)service始終保持在后臺(tái)運(yùn)行,不管用戶作出什么操作,都要保證service不被kill,這可真是一個(gè)難題。參考了現(xiàn)今各種定制版的系統(tǒng)和安全廠商牛虻軟件,如何能保證自己的Service不被殺死呢? 其實(shí)除了常規(guī)的手段,我們可以參考一下微信和360,設(shè)置-程序-正在運(yùn)行,可以看到微信是同時(shí)開啟了兩個(gè)進(jìn)程和服務(wù): 我猜想它應(yīng)該是相互監(jiān)聽,如果有一方被kill掉,另一個(gè)捕獲到立即啟動(dòng),以達(dá)到service永遠(yuǎn)都在運(yùn)行的狀態(tài),貌似360也是這個(gè)原理,具體是不是這個(gè)樣子,還有待參考,目前我還沒有參透它們是如何實(shí)現(xiàn)的,先簡單說一下我自己的防控措施吧。 一、Serv

2、ice簡介 Service是在一段不定的時(shí)間運(yùn)行在后臺(tái),不和用戶交互應(yīng)用組件。每個(gè)Service必須在manifest中 通過來聲明??梢酝ㄟ^contect.startservice和contect.bindserverice來啟動(dòng)。和其他的應(yīng)用組件一樣,運(yùn)行在進(jìn)程的主線程中。這就是說如果service需要很多耗時(shí)或者阻塞的操作,需要在其子線程中實(shí)現(xiàn)(或者用系統(tǒng)提供的IntentService,它繼承了Service,它處理數(shù)據(jù)是用自身新開的線程)。 本地服務(wù) Local Service 用于應(yīng)用程序內(nèi)部。 它可以啟動(dòng)并運(yùn)行,直至有人停止了它或它自己停止。在這種方式下,它以調(diào)用Context.

3、startService()啟動(dòng),而以調(diào)用Context.stopService()結(jié)束。它可以調(diào)用Service.stopSelf() 或 Service.stopSelfResult()來自己停止。不論調(diào)用了多少次startService()方法,你只需要調(diào)用一次stopService()來停止服務(wù)。 用于實(shí)現(xiàn)應(yīng)用程序自己的一些耗時(shí)任務(wù),比如查詢升級(jí)信息,并不占用應(yīng)用程序比如Activity所屬線程,而是單開線程后臺(tái)執(zhí)行,這樣用戶體驗(yàn)比較好。 遠(yuǎn)程服務(wù) Remote Service 用于android系統(tǒng)內(nèi)部的應(yīng)用程序之間。 它可以通過自己定義并暴露出來的接口進(jìn)行程序操作??蛻舳私⒁粋€(gè)到

4、服務(wù)對(duì)象的連接,并通過那個(gè)連接來調(diào)用服務(wù)。連接以調(diào)用Context.bindService()方法建立,以調(diào)用 Context.unbindService()關(guān)閉。多個(gè)客戶端可以綁定至同一個(gè)服務(wù)。如果服務(wù)此時(shí)還沒有加載,bindService()會(huì)先加載它。 可被其他應(yīng)用程序復(fù)用,比如天氣預(yù)報(bào)服務(wù),其他應(yīng)用程序不需要再寫這樣的服務(wù),調(diào)用已有的即可。 1,Service的生命周期 2,Service運(yùn)行方式 以startService()啟動(dòng)service,系統(tǒng)將通過傳入的Intent在底層搜索相關(guān)符合Intent里面信息的service。如果服務(wù)沒有啟動(dòng)則先運(yùn)行onCreate,然后運(yùn)行onS

5、tartCommand (可在里面處理啟動(dòng)時(shí)傳過來的Intent和其他參數(shù)),直到明顯調(diào)用stopService或者stopSelf才將停止Service。無論運(yùn)行startService多少次,只要調(diào)用一次stopService或者stopSelf,Service都會(huì)停止。使用stopSelf(int)方法可以保證在處理好intent后再停止。onStartCommand ,在2.0后被引入用于service的啟動(dòng)函數(shù),2.0之前為public void onStart(Intent intent, int startId) 。 使用bindService()方法啟用服務(wù),調(diào)用者與服務(wù)綁定在

6、了一起,調(diào)用者一旦退出,服務(wù)也就終止。 onBind()只有采用Context.bindService()方法啟動(dòng)服務(wù)時(shí)才會(huì)回調(diào)該方法。該方法在調(diào)用者與服務(wù)綁定時(shí)被調(diào)用,當(dāng)調(diào)用者與服務(wù)已經(jīng)綁定,多次調(diào)用Context.bindService()方法并不會(huì)導(dǎo)致該方法被多次調(diào)用。 采用Context.bindService()方法啟動(dòng)服務(wù)時(shí)只能調(diào)用onUnbind()方法解除調(diào)用者與服務(wù)解除,服務(wù)結(jié)束時(shí)會(huì)調(diào)用onDestroy()方法。 3,擁有service的進(jìn)程具有較高的優(yōu)先級(jí) 官方文檔告訴我們,Android系統(tǒng)會(huì)盡量保持擁有service的進(jìn)程運(yùn)行,只要在該service已經(jīng)被啟動(dòng)(sta

7、rt)或者客戶端連接(bindService)到它。當(dāng)內(nèi)存不足時(shí),需要保持,擁有service的進(jìn)程具有較高的優(yōu)先級(jí)。 1 如果service正在調(diào)用onCreate,onStartCommand或者onDestory方法,那么用于當(dāng)前service的進(jìn)程則變?yōu)榍芭_(tái)進(jìn)程以避免被killed。2 如果當(dāng)前service已經(jīng)被啟動(dòng)(start),擁有它的進(jìn)程則比那些用戶可見的進(jìn)程優(yōu)先級(jí)低一些,但是比那些不可見的進(jìn)程更重要,這就意味著service一般不會(huì)被killed.3 如果客戶端已經(jīng)連接到service (bindService),那么擁有Service的進(jìn)程則擁有最高的優(yōu)先級(jí),可以認(rèn)為ser

8、vice是可見的。4 如果service可以使用startForeground(int, Notification)方法來將service設(shè)置為前臺(tái)狀態(tài),那么系統(tǒng)就認(rèn)為是對(duì)用戶可見的,并不會(huì)在內(nèi)存不足時(shí)killed。如果有其他的應(yīng)用組件作為Service,Activity等運(yùn)行在相同的進(jìn)程中,那么將會(huì)增加該進(jìn)程的重要性。 二、保證service不死 onStartCommand方法,返回START_STICKY。 1、START_STICKY 在運(yùn)行onStartCommand后service進(jìn)程被kill后,那將保留在開始狀態(tài),但是不保留那些傳入的intent。不久后service就會(huì)再次嘗

9、試重新創(chuàng)建,因?yàn)楸A粼陂_始狀態(tài),在創(chuàng)建 service后將保證調(diào)用onstartCommand。如果沒有傳遞任何開始命令給service,那將獲取到null的intent。2、START_NOT_STICKY 在運(yùn)行onStartCommand后service進(jìn)程被kill后,并且沒有新的intent傳遞給它。Service將移出開始狀態(tài),并且直到新的明顯的方法(startService)調(diào)用才重新創(chuàng)建。因?yàn)槿绻麤]有傳遞任何未決定的intent那么service是不會(huì)啟動(dòng),也就是期間onstartCommand不會(huì)接收到任何null的intent。3、START_REDELIVER_INTEN

10、T 在運(yùn)行onStartCommand后service進(jìn)程被kill后,系統(tǒng)將會(huì)再次啟動(dòng)service,并傳入最后一個(gè)intent給onstartCommand。直到調(diào)用stopSelf(int)才停止傳遞intent。如果在被kill后還有未處理好的intent,那被kill后服務(wù)還是會(huì)自動(dòng)啟動(dòng)。因此onstartCommand不會(huì)接收到任何null的intent。 Override public int onStartCommand(Intent intent, int flags, int startId) flags = START_STICKY; return super.onSta

11、rtCommand(intent, flags, startId); 【結(jié)論】 手動(dòng)返回START_STICKY,親測當(dāng)service因內(nèi)存不足被kill,當(dāng)內(nèi)存又有的時(shí)候,service又被重新創(chuàng)建,比較不錯(cuò)。 提升service進(jìn)程優(yōu)先級(jí) 在AndroidManifest.xml文件中對(duì)于intent-filter可以通過android:priority = 1000這個(gè)屬性設(shè)置最高優(yōu)先級(jí),1000是最高值,如果數(shù)字越小則優(yōu)先級(jí)越低,同時(shí)實(shí)用于廣播 提升service優(yōu)先級(jí) Android中的進(jìn)程是托管的,當(dāng)系統(tǒng)進(jìn)程空間緊張的時(shí)候,會(huì)依照優(yōu)先級(jí)自動(dòng)進(jìn)行進(jìn)程的回收。Android將進(jìn)程分為6

12、個(gè)等級(jí),它們按優(yōu)先級(jí)順序由高到低依次是: 1.前臺(tái)進(jìn)程( FOREGROUND_APP) 2.可視進(jìn)程(VISIBLE_APP ) 3. 次要服務(wù)進(jìn)程(SECONDARY_SERVER ) 4.后臺(tái)進(jìn)程 (HIDDEN_APP) 5.內(nèi)容供應(yīng)節(jié)點(diǎn)(CONTENT_PROVIDER) 6.空進(jìn)程(EMPTY_APP) 當(dāng)service運(yùn)行在低內(nèi)存的環(huán)境時(shí),將會(huì)kill掉一些存在的進(jìn)程。因此進(jìn)程的優(yōu)先級(jí)將會(huì)很重要,可以使用startForeground API將service放到前臺(tái)狀態(tài)。這樣在低內(nèi)存時(shí)被kill的幾率更低,但是如果在極度極度低內(nèi)存的壓力下,該service還是會(huì)被kill掉。 在

13、onStartCommand方法內(nèi) Notification notification = new Notification(R.drawable.ic_launcher, getString(R.string.app_name), System.currentTimeMillis(); PendingIntent pendingintent = PendingIntent.getActivity(this, 0, new Intent(this, AppMain.class), 0); notification.setLatestEventInfo(this, uploadservice,

14、請(qǐng)保持程序在后臺(tái)運(yùn)行, pendingintent); startForeground(0x111, notification); 注意在onDestroy里還需要stopForeground(true); 在onDestroy方法里重啟service service +broadcast 方式,就是當(dāng)service走ondestory的時(shí)候,發(fā)送一個(gè)自定義的廣播,當(dāng)收到廣播的時(shí)候,重新啟動(dòng)service; /這個(gè)就是自定義的action 在onDestroy時(shí): Override public void onDestroy() stopForeground(true); Intent int

15、ent = new Intent(com.dbjtech.waiqin.destroy); sendBroadcast(intent); super.onDestroy(); 在BootReceiver里 public class BootReceiver extends BroadcastReceiver Override public void onReceive(Context context, Intent intent) if (intent.getAction().equals(com.dbjtech.waiqin.destroy) /TODO /在這里寫重新啟動(dòng)service的相

16、關(guān)操作 startUploadService(context); 【結(jié)論】當(dāng)然,你也可以在onDestroy里直接startService(),我通過使用broadcast,可以做更多的處理判斷操作。 一個(gè)不被殺死的進(jìn)程 看Android的文檔知道,當(dāng)進(jìn)程長期不活動(dòng),或系統(tǒng)需要資源時(shí),會(huì)自動(dòng)清理門戶,殺死一些Service,和不可見的Activity等所在的進(jìn)程。但是如果某個(gè)進(jìn)程不想被殺死(如數(shù)據(jù)緩存進(jìn)程,或狀態(tài)監(jiān)控進(jìn)程,或遠(yuǎn)程服務(wù)進(jìn)程),可以這么做: application android:name=com.test.Application android:allowBackup=true

17、android:icon=drawable/ic_launcher android:label=string/app_name android:persistent=true android:theme=style/AppTheme 【結(jié)論】據(jù)說這個(gè)屬性不能亂設(shè)置,不過設(shè)置后,的確發(fā)現(xiàn)優(yōu)先級(jí)提高不少,或許是相當(dāng)于系統(tǒng)級(jí)的進(jìn)程。 系統(tǒng)各種廣播監(jiān)聽 通過系統(tǒng)的廣播,監(jiān)聽并捕獲到,然后判斷是否需要重新啟動(dòng)service。 Override public void onReceive(Context context, Intent intent) if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAct

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論