1. 程式人生 > >Android Service 不被殺掉方法(broadcast+system/app)

Android Service 不被殺掉方法(broadcast+system/app)

Service簡介

service是在一段不定的時間執行在後臺,不和使用者互動應用元件。每個Service必須在manifest中 通過<service>來宣告。可以通過contect.startservice和contect.bindserverice來啟動。和其他的應用元件一樣,執行在程序的主執行緒中。這就是說如果service需要很多耗時或者阻塞的操作,需要在其子執行緒中實現(或者用系統提供的IntentService,它繼承了Service,它處理資料是用自身新開的執行緒)。【當然你也可以在新的執行緒中startService,這樣Service就不是在MainThread了


本地服務 Local Service 用於應用程式內部

它可以啟動並執行,直至有人停止了它或它自己停止。在這種方式下,它以呼叫Context.startService()啟動,而以呼叫Context.stopService()結束。它可以呼叫Service.stopSelf() 或 Service.stopSelfResult()來自己停止。不論呼叫了多少次startService()方法,你只需要呼叫一次stopService()來停止服務。

【用於實現應用程式自己的一些耗時任務,比如查詢升級資訊,並不佔用應用程式比如Activity所屬執行緒,而是單開執行緒後臺執行,這樣使用者體驗比較好】

遠端服務 Remote Service 用於android系統內部的應用程式之間

它可以通過自己定義並暴露出來的介面進行程式操作。客戶端建立一個到服務物件的連線,並通過那個連線來呼叫服務。連線以呼叫Context.bindService()方法建立,以呼叫 Context.unbindService()關閉。多個客戶端可以繫結至同一個服務。如果服務此時還沒有載入,bindService()會先載入它。

【可被其他應用程式複用,比如天氣預報服務,其他應用程式不需要再寫這樣的服務,呼叫已有的即可】

1,Service的生命週期


2,Service執行方式

以startService()啟動服務,系統將通過傳入的Intent在底層搜尋相關符合Intent裡面資訊的service。如果服務沒有啟動則先執行onCreate,然後執行onStartCommand (可在裡面處理啟動時傳過來的Intent和其他引數),直到明顯呼叫stopService或者stopSelf才將停止Service。無論執行startService多少次,只要呼叫一次stopService或者stopSelf,Service都會停止。使用stopSelf(int)方法可以保證在處理好intent後再停止。onStartCommand ,在2.0後被引入用於service的啟動函式,2.0之前為public void onStart(Intent intent, int startId) 。

以bindService()方法啟用服務,呼叫者與服務繫結在了一起,呼叫者一旦退出,服務也就終止。onBind()只有採用Context.bindService()方法啟動服務時才會回撥該方法。該方法在呼叫者與服務繫結時被呼叫,當呼叫者與服務已經繫結,多次呼叫Context.bindService()方法並不會導致該方法被多次呼叫。採用Context.bindService()方法啟動服務時只能呼叫onUnbind()方法解除呼叫者與服務解除,服務結束時會呼叫onDestroy()方法。

3,擁有service的程序具有較高的優先順序

官方文件告訴我們,Android系統會盡量保持擁有service的程序執行,只要在該service已經被啟動(start)或者客戶端連線(bindService)到它。當記憶體不足時,需要保持,擁有service的程序具有較高的優先順序。

1. 如果service正在呼叫onCreate,onStartCommand或者onDestory方法,那麼用於當前service的程序則變為前臺程序以避免被killed。
2. 如果當前service已經被啟動(start),擁有它的程序則比那些使用者可見的程序優先順序低一些,但是比那些不可見的程序更重要,這就意味著service一般不會被killed.
3. 如果客戶端已經連線到service (bindService),那麼擁有Service的程序則擁有最高的優先順序,可以認為service是可見的。
4. 如果service可以使用startForeground(int, Notification)方法來將service設定為前臺狀態,那麼系統就認為是對使用者可見的,並不會在記憶體不足時killed。
5. 如果有其他的應用元件作為Service,Activity等執行在相同的程序中,那麼將會增加該程序的重要性。

保證service不被殺掉

onStartCommand方法,返回START_STICKY

StartCommond幾個常量引數簡介:

1、START_STICKY

在執行onStartCommand後service程序被kill後,那將保留在開始狀態,但是不保留那些傳入的intent。不久後service就會再次嘗試重新建立,因為保留在開始狀態,在建立     service後將保證呼叫onstartCommand。如果沒有傳遞任何開始命令給service,那將獲取到null的intent。

2、START_NOT_STICKY

在執行onStartCommand後service程序被kill後,並且沒有新的intent傳遞給它。Service將移出開始狀態,並且直到新的明顯的方法(startService)呼叫才重新建立。因為如果沒有傳遞任何未決定的intent那麼service是不會啟動,也就是期間onstartCommand不會接收到任何null的intent。

3、START_REDELIVER_INTENT

在執行onStartCommand後service程序被kill後,系統將會再次啟動service,並傳入最後一個intent給onstartCommand。直到呼叫stopSelf(int)才停止傳遞intent。如果在被kill後還有未處理好的intent,那被kill後服務還是會自動啟動。因此onstartCommand不會接收到任何null的intent。

  1. @Override
  2. publicint onStartCommand(Intent intent, int flags, int startId) {  
  3.     flags = START_STICKY;  
  4.     returnsuper.onStartCommand(intent, flags, startId);  
  5. }  

【結論】 手動返回START_STICKY,親測當service因記憶體不足被kill,當記憶體又有的時候,service又被重新建立,比較不錯,但是不能保證任何情況下都被重建,比如程序被幹掉了....

提升service優先順序

在AndroidManifest.xml檔案中對於intent-filter可以通過android:priority = "1000"這個屬性設定最高優先順序,1000是最高值,如果數字越小則優先順序越低,同時適用於廣播。

  1. <service  
  2.     android:name="com.dbjtech.acbxt.waiqin.UploadService"
  3.     android:enabled="true" >  
  4.     <intent-filter android:priority="1000" >  
  5.         <action android:name="com.dbjtech.myservice" />  
  6.     </intent-filter>  
  7. </service>  

【結論】目前看來,priority這個屬性貌似只適用於broadcast,對於Service來說可能無效

提升service程序優先順序

Android中的程序是託管的,當系統程序空間緊張的時候,會依照優先順序自動進行程序的回收。Android將程序分為6個等級,它們按優先順序順序由高到低依次是:

   1.前臺程序( FOREGROUND_APP)
   2.可視程序(VISIBLE_APP )
   3. 次要服務程序(SECONDARY_SERVER )
   4.後臺程序 (HIDDEN_APP)
   5.內容供應節點(CONTENT_PROVIDER)
   6.空程序(EMPTY_APP)

當service執行在低記憶體的環境時,將會kill掉一些存在的程序。因此程序的優先順序將會很重要,可以使用startForeground 將service放到前臺狀態。這樣在低記憶體時被kill的機率會低一些。

在onStartCommand方法內新增如下程式碼:

  1.  Notification notification = new Notification(R.drawable.ic_launcher,  
  2.  getString(R.string.app_name), System.currentTimeMillis());  
  3.  PendingIntent pendingintent = PendingIntent.getActivity(this0,  
  4.  new Intent(this, AppMain.class), 0);  
  5.  notification.setLatestEventInfo(this"uploadservice""請保持程式在後臺執行",  
  6.  pendingintent);  
  7. <span style="color:#ff0000;"> startForeground(0x111, notification);</span>  

注意在onDestroy裡還需要stopForeground(true),執行時在下拉列表會看到自己的APP在:


【結論】如果在極度極度低記憶體的壓力下,該service還是會被kill掉,並且不一定會restart

onDestroy方法裡重啟service

service +broadcast  方式,就是當service走ondestory的時候,傳送一個自定義的廣播,當收到廣播的時候,重新啟動service;

  1. <receiver android:name="com.dbjtech.acbxt.waiqin.BootReceiver" >  
  2.     <intent-filter>  
  3.         <action android:name="android.intent.action.BOOT_COMPLETED" />  
  4.         <action android:name="android.intent.action.USER_PRESENT" />  
  5.         <action android:name="com.dbjtech.waiqin.destroy" />//這個就是自定義的action
  6.     </intent-filter>  
  7. </receiver>  
在onDestroy時:
  1. @Override
  2. publicvoid onDestroy() {  
  3.     stopForeground(true);  
  4.     Intent intent = new Intent("com.dbjtech.waiqin.destroy");  
  5.     sendBroadcast(intent);  
  6.     super.onDestroy();  
  7. }  
在BootReceiver裡
  1. publicclass BootReceiver extends BroadcastReceiver {  
  2.     @Override
  3.     publicvoid onReceive(Context context, Intent intent) {  
  4.         if (intent.getAction().equals("com.dbjtech.waiqin.destroy")) {  
  5.             //TODO
  6.             //在這裡寫重新啟動service的相關操作
  7.                 startUploadService(context);  
  8.         }  
  9.     }  
  10. }  

也可以直接在onDestroy()裡startService

  1. @Override
  2. publicvoid onDestroy() {  
  3.      Intent sevice = new Intent(this, MainService.class);  
  4.      this.startService(sevice);  
  5.     super.onDestroy();  
  6. }  

【結論】當使用類似口口管家等第三方應用或是在setting裡-應用-強制停止時,APP程序可能就直接被幹掉了,onDestroy方法都進不來,所以還是無法保證~.~


Application加上Persistent屬性

看Android的文件知道,當程序長期不活動,或系統需要資源時,會自動清理門戶,殺死一些Service,和不可見的Activity等所在的程序。但是如果某個程序不想被殺死(如資料快取程序,或狀態監控程序,或遠端服務程序),可以這麼做:

  1. <application  
  2.     android:name="com.test.Application"
  3.     android:allowBackup="true"
  4.     android:icon="@drawable/ic_launcher"
  5.     android:label="@string/app_name"
  6.    <span style="color:#ff0000;"> android:persistent="true"</span>  
  7.     android:theme="@style/AppTheme" >  
  8. </application>  

【結論】據說這個屬性不能亂設定,不過設定後,的確發現優先順序提高不少,或許是相當於系統級的程序,但是還是無法保證存活

監聽系統廣播判斷Service狀態

通過系統的一些廣播,比如:手機重啟、介面喚醒、應用狀態改變等等監聽並捕獲到,然後判斷我們的Service是否還存活,別忘記加許可權啊。

  1. <receiver android:name="com.dbjtech.acbxt.waiqin.BootReceiver" >  
  2.     <intent-filter>  
  3.         <action android:name="android.intent.action.BOOT_COMPLETED" />  
  4.         <action android:name="android.intent.action.USER_PRESENT" />  
  5.         <action android:name="android.intent.action.PACKAGE_RESTARTED" />  
  6.         <action android:name="com.dbjtech.waiqin.destroy" />  
  7.     </intent-filter>  
  8. </receiver>  
BroadcastReceiver中:
  1. @Override
  2. publicvoid onReceive(Context context, Intent intent) {  
  3.     if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {  
  4.         System.out.println("手機開機了....");  
  5.         startUploadService(context);  
  6.     }  
  7.     if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {  
  8.             startUploadService(context);  
  9.     }  
  10. }  

【結論】這也能算是一種措施,不過感覺監聽多了會導致Service很混亂,帶來諸多不便

將APK安裝到/system/app,變身系統級應用 這個辦法不推薦使用,因為如果你的APP如果是給使用者使用的,那就不合適了,我是為了給測試的妹子來用,這個APP的目的也是很簡單,開啟後開啟Service並且能保證一直在後臺駐留,開機自啟動。但是昨天發現如果她的HuaWei手機長時間關閉, 再重新開啟時,我們應用的Service不會自啟動,貌似廣播收不到了~一怒之下,打算搞成系統應用。 前提: ROOT過的手機 1,把程式碼編寫好後,打包匯出apk,copy到手機SD卡根目錄下。 2,手機連線eclipse,cmd: adb shell 3,切換root模式,輸入:su     (如果root過就不會有錯誤) 4,設定System為讀寫許可權:mount –o remount rw /system (System預設為只讀,無法寫入,這一步很關鍵)
5,cd到sd卡跟目錄下,確認是否有我們拷貝到sd卡根目錄下的apk(一般都是 storage/sdcard0) [email protected]:/ # cd storage/sdcard0
6,最關鍵的一步,我們要把apk拷貝到 /System/app中:
發現copy命令無效~那麼我們就用push把:
如果有錯誤:device not found,那麼手機下載一個Root Explorer把,找到apk,copy到System/app下,通過這個APP要更容易一些。 7,system/app 確定擁有我們的APK後,重啟手機把:
設定-應用程式管理,檢視一下: 可以看到我們的APP已經無法解除安裝了,只能停用
這個時候,就算強制停止,或是關閉Service,重啟手機後照樣可以起來Service~!
系統級的APP,這樣一些第三方的管家軟體,就無法殺掉我們,除非自己把APP停用掉,或是強制停止(但是我的APP可以開機自啟動)。 【結論】這種方式適合除錯來用,並不算是一種解決辦法,大家可以嘗試在正在執行的介面:強制關閉搜狐視訊的兩個程序,重啟手機,發現他又可以自啟動,但是如果換成我們的APP,強制停止,程序掛了,再重啟手機,無法自啟動了~ 大家一起研究,怎麼樣才能像上圖搜狐視訊一樣,開啟兩個程序,相互監聽,做到最大程度的存活,如果這個能實現了,那就和微信、360等一樣的效果了。

相關推薦

Android Service 殺掉方法broadcast+system/app

Service簡介 service是在一段不定的時間執行在後臺,不和使用者互動應用元件。每個Service必須在manifest中 通過<service>來宣告。可以通過contect.startservice和contect.bindserverice來啟動。

[轉] Android開發之如何保證Service殺掉broadcast+system/app

轉發:原文連結http://blog.csdn.net/mad1989/article/details/22492519 序言 最近專案要實現這樣一個效果:執行後,要有一個service始終保持在後臺執行,不管使用者作出什麼操作,都要保證service不被kill,這可真是一個難題。參考了現今各種定製版的系

Android開發之如何保證Service殺掉broadcast+system/app

序言 最近專案要實現這樣一個效果:執行後,要有一個service始終保持在後臺執行,不管使用者作出什麼操作,都要保證service不被kill,這可真是一個難題。參考了現今各種定製版的系統和安全廠商牛虻軟體,如何能保證自己的Service不被殺死呢?

android servicekill的方法

private ActivityManager activityManager; activityManager = (ActivityManager) mcontext.getSystemService(Context.ACTIVITY_SERVICE); IntentFilter

Android保證service殺掉-增強版: 程序保活(根據使用者需求慎用)

作者:騰訊——張興華 目前市面上的應用,貌似除了微信和手Q都會比較擔心被使用者或者系統(廠商)殺死問題。本文對 Android 程序拉活進行一個總結。 Android 程序拉活包括兩個層面: A. 提供程序優先順序,降低程序被殺死的概率 B. 在程序被殺死後,進行

Android應用殺死killer方法

方法:對於一個service,可以首先把它設為在前臺執行: 複製程式碼 程式碼如下: public void MyService.onCreate() {         super.onCreate();         Notification notification = new Notificat

android 小米手機彈出框自定義dialog位置居中解決方法

在建立dialog或者構造方法出加入如下程式碼就可以解決問題、 Window window = dialog.getWindow(); if (dialog != null &a

Android 開發之Service 探索如何保證Service殺死或kill之後自動重啟

前言: 在我司專案1.0版本的時候訊息是使用的環信、用了之後發現各種bug,各種機型不支援導致app崩潰,於是在2.0版本果斷去掉環信,使用了公眾號用的那套訊息系統(老大自己寫的)並做了擴充套件升級。

Android AIDL bindService後能呼叫onServiceConnected方法一種情況

"font-size:18px;">import android.app.Activity;   import android.content.ComponentName;   import android.content.Intent;   import android.content.Servic

XAMPP--解決apache因埠佔用啟動了的一種方法不用改埠

在執行apache時,XAMPP提示apache的80埠被佔用一、可以先用netstart命令進行檢視80埠被哪個程序進行佔用win+r 執行cmd輸入netstat -ano二、此時可現在服務中找到Apache服務將其停止三、在停止服務後啟動Apache服務後再啟動apac

andorid如何保證service殺死精簡版

Android 程序不死從3個層面入手:        A.提供程序優先順序,降低程序被殺死的概率          方法一:監控手機鎖屏解鎖事件,在螢幕鎖屏時啟動1個畫素的 Activity,在使

try catch 小結 , node的回調callback裏能捕獲異常 , v8優化現在能了

容易 sin ejs called ack tro 崩潰 span 檢查 《深入淺出Nodejs》時,在第四章 - 異步編程中作者樸靈曾提到,異步編程的難點之一是異常處理,書中描述"嘗試對異步方法進行try/catch操作只能捕獲當次事件循環內的異常,對call back執

Android傳遞中文參數方法之一

volley and param method mit resp star cat ner 最近在做app,用的volley傳參,有一個地方傳中文參數不行(貌似是get方式),我又試了下post方式,成功了,記錄下,以後有用! RequestQueue requ

保證ServiceKill的解決方案

req som .html ppp 真機測試 其中 清理工具 reat 清理 1、Service設置成START_STICKY(onStartCommand方法中),kill 後會被重啟(等待5秒左右),重傳Intent,保持與重啟前一樣 2、通過 startForegro

如今的iOS開發者優勝劣汰,如何提升讓自己淘汰?附資料

角度 高效 二進制 新的 編輯器 選擇 形勢 前端工程 作者 序言: 如果從 13 年移動客戶端大火開始算起,至今已經有五個年頭了。現在移動端的形勢也不需要太多的廢話來描述,一句話總結就是:“浪潮退去,誰在裸泳一看就清楚。”我希望借助這篇文章來聊聊在我心目中,移動互聯網下一

已有的exe,始終帶引數執行,需要每次輸入命令列的方法create sfx archive

原始需求:由於讓其他人操作時,可能由於看錯或者是手動輸入錯誤,導致命令列引數並不是符合預期的值,結果不能得到想要的結果 工具:winrar 英文中文都可以(不能使用快壓,快壓沒有這個功能)--自行下載(我的資源裡也可以找到) 操作方法: 開啟rar, 選擇要進行自解壓格式的exe檔案,然

教你怎麼檢視微信聊天記錄發現?方法絕了

微信聊天記錄怎麼查?已經刪除的微信聊天記錄檢視方法。手機如何查詢微信聊天記錄?我相信大多數小夥伴都改過對如何查詢刪除微信聊天記錄恢復感興趣,因為我們在使用微信的時候,偶爾會遇到誤刪微信聊天記錄的情況,因此有時候我們對刪除的微信聊天記錄進行查詢而是非常有必要的,那麼手機如何查詢

android 判斷手機是否是國內的手機的方法getSimCountryIso和getSimOperator

有一個需求:如果手機插入了sim卡,要判斷該手機是否是大陸使用者? 方法一: /**      * 判斷國家是否是國內使用者      *       * @return      */     public static boolean isCN(Context cont

Scrapy爬蟲執行中yield請求未丟擲或丟擲未執行解決方法親測有效

當我們在執行scrapy除錯的時候可能會遇到yield請求未正確丟擲的情況。 1、檢視scrapy執行日誌 日誌中的這一項表示,我們的請求被過濾掉了20條。 解決方法: 1、將我們的請求ip地址域名(如:blog.csdn.net)新增到spider爬蟲檔案的allowed_d

Android GPS室內定位問題的解決方法location為null

為什麼室內沒有location呢?        因為我們開發的時候幾乎肯定都是在室內的,這個時候衛星你是搜尋不到的,所以必然是定位不了的,所以系統如何將位置資訊通知給你的程式。所以要從根本上解決這個問題,就要解決位置資訊獲取問題。         那麼我來告訴大家,只