1. 程式人生 > >Android如何保證自己的服務被系統kill後又被系統重啟?

Android如何保證自己的服務被系統kill後又被系統重啟?

大家好:

微笑今天是我第一次發表文章,希望大家以後多多支援。

    我覺得現在網上Android 的各方面問題都有很多,我想以自己的方式來分享給大家,分享我所學所悟。網上Android基礎方面的東西更是遍地都是,所以我會寫一些Android基礎上深入研究的東西。希望大家一起相互交流學習。

今天第一次寫,可能寫得不好,還望各位看客老爺多多包涵,剛開始寫我可能不會寫很深入研究的功能,後面想到什麼再寫什麼,相信大家一定會滿意的。

今天的問題是:Android中如何讓自己的服務被系統kill後,又被系統主動重啟?

方法一:

重寫serviceonStartCommand方法 如下:

首先在 onStartCommand 方法中改變返回值 為 

START_STICKY

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
	// TODO Auto-generated method stub
	return START_STICKY;
}
在onDestroy方法裡面再次啟動Service
<pre name="code" class="java">	@Override
	public void onDestroy() {
		//銷燬時重新啟動Service
		Intent localIntent=new Intent();
		localIntent.setClass(this, MyService.class);
		this.startService(localIntent);
		Log.e("LOG", "onDestroy------------------->");
		super.onDestroy();
	}
還需在 AndroidManifest.xml 配置 
<pre name="code" class="java"><application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:allowClearUserData="false"
        android:process="system"
        android:killAfterRestore="false"
        android:label="@string/app_name"
        android:persistent="true"
        android:theme="@style/AppTheme" >
返回值介紹: Android開發的過程中,每次呼叫startService(Intent)的時候,都會呼叫該Service物件的onStartCommand(Intent,int,int)方法,然後在onStartCommand方法中做一些處理。然後我們注意到這個函式有一個int的返回值,這裡簡單地講講int返回值的作用。 從Android官方文件中,我們知道onStartCommand有幾種返回值 如: START_STICKY:如果service程序被kill掉,保留service的狀態為開始狀態,但不保留遞送的intent物件。隨後系統會嘗試重新建立service,由於服務狀態為開始狀態,所以建立服務後一定會呼叫onStartCommand(Intent,int,int)方法。如果在此期間沒有任何啟動命令被傳遞到service,那麼引數Intent將為null。 START_NOT_STICKY:“非粘性的”。使用這個返回值時,如果在執行完onStartCommand後,服務被異常kill掉,系統不會自動重啟該服務。 START_REDELIVER_INTENT:重傳Intent。使用這個返回值時,如果在執行完onStartCommand後,服務被異常kill掉,系統會自動重啟該服務,並將Intent的值傳入。 START_STICKY_COMPATIBILITYSTART_STICKY的相容版本,但不保證服務被kill後一定能重啟。 當然服務也存在著優先順序:         Android系統中,當某程序較長時間不活動,或系統資源比較緊時,該程序可能被系統kill掉,以此來回收一些資源。Android系統會根據程序的優先順序來選擇性地殺死一些程序,優先順序從高到低依次是: 1. 前臺程序(Foreground Process) 2. 可視程序(Visible Process) 3. 服務程序(Service Process) 4. 後臺程序(Background Process) 5. 空程序(Empty Process) 詳細介紹: 1. 前臺程序(Foreground Process)是指當前的活動程序,即那些有視窗、控制元件的,正與使用者進行互動的應用程式程序。Android會努力嘗試從其它程序回收系統資源來保持其響應。 2. 可見程序(Visible Process)是指那些可見的活動程序,但是當前它不在前臺執行,不能對使用者事件作出反映。比如一個程式A正在前臺執行,接著又啟動了另一個程式B,程式B的視窗把程式A的視窗完全或部分遮擋,那麼,程式A現在就屬於可見程序了。一般來說,只有在系統資源十分缺乏的情況下,為了保證活動程序的執行,系統才會終止它。 3. 服務程序(Service Process)是指那些沒有可見介面的程序,它們不能直接與使用者進行互動。前臺程序(通常是一個Activity)變為非活動時,會暫停執行;但服務程序可在後臺保持執行,因此如果要保持程序在轉到後臺後也能執行,就必需啟動一個Service。但是一旦前臺程序需要資源時,Service就很容易被系統給kill掉。通常,預設情況下Service被kill掉後會自動重啟,但是重啟後並不能保證恢復先前的環境;如果不需要Service自動重啟,呼叫stopSelf()函式即可。 4. 後臺程序(Background Process)是指不可見的,且沒有任何正在執行的服務的活動的程序。通常後臺程序會比較多,Android將按“最後一個被看到,第一個終止”的方式來終止它們,從而為前臺程序提供資源。 5. 對於空程序,Android為了提高系統的整體效能,經常在在應用程式的生存期結束後仍然把它們儲存在記憶體中,當該程式被再次啟動時,可以加快啟動速度。這類程序會根據需要被定期終止。 1:如果是在系統的settings中的DOWNLOADED關閉整個應用(Force stop),則這個services類中的onDestory方法沒有監聽到(services類的onDestory方法的log沒有列印日誌),如果 是在系統裡的setting中的RUNNING殺掉專案services,則onDestory方法則會監聽到(services類的onDestory 方法的log有列印日誌),所以對於此解決方案並不是一定適用, 2:或是通過別的應用,直接kill掉我的應用時,也是不會呼叫services類的 onDestory方法的 假如使用者的手機上面安裝了360或者其他的手機管理軟體,防毒軟體。使用者手動清理了我們的app後臺服務後怎麼辦?請看方法二 ... 方法二: 通過監聽系統廣播的方式來,啟動我們的app服務,比如監聽 網路狀態, 訊號變化,電量變化,手機鎖屏鍵等頻繁觸發的事件,這樣我們的app服務是不是基本上就是隨時啟動著的了?O(∩_∩)O哈哈~  是不是很流氓?看你自己需求而定,好了廢話不多說,我就以開鎖屏鍵來實現一個簡單的例子吧! 該連結裡面的博主的監聽方法是動態註冊,監聽開鎖屏事件。這樣有一個問題就是,當你app執行是正在執行時是能監聽到的,但是如果app退出,結束後,開鎖屏就監聽不到了。如果你的需求是隻在專案執行時 監聽開鎖屏事件,那麼該博主的帖子(附有原始碼)完全可以滿足你的需求。 如果你是想在app專案執行關閉,退出的狀態下監聽開鎖屏事件,那麼動態註冊方法是不能實現的。當然也有解決方法,你可以寫服務去啟動監聽廣播(前提是你的服務必須保證不被系統或者360這樣的防毒軟體,殺掉你的服務)。 其實我們在做一個程式的時候,需要時刻保持某一服務是啟動的,因此想到了通過監聽螢幕SCREEN_ON和SCREEN_OFF這兩個action。奇怪的是,這兩個action只能通過程式碼的形式註冊,才能被監聽到,使用AndroidManifest.xml 完全監聽不到。查了一下,發現這是PowerManager那邊在發這個廣播的時候,做了限制,限制只能有register到程式碼中的receiver才能接收,這裡告訴了我們監聽開鎖屏事件是不能靜態註冊廣播監聽的。
<!-- 監聽開鎖屏廣播註冊 -->
        <receiver android:name="com.isoft.screen.ScreenObserver" >
            <intent-filter android:priority="2147483647" >
                <action android:name="android.intent.action.SCREEN_ON"/>
                <action android:name="android.intent.action.SCREEN_OFF"/>
            </intent-filter>
        </receiver>

那麼我們怎麼才能保證我的服務一直是啟動狀態呢?其實還有另一個Action是可以反映出使用者正在使用手機的行為,每個使用者在使用手機的時候,首先按電源鍵將螢幕點亮,緊接著就是解鎖。解鎖動作通過 android.intent.action.USER_PRESENT 傳送出來,我們就能識別出該使用者進入了home介面,也就能啟動我們相應的服務了。該Action在AndroidManifest.xml中可以靜態註冊且監聽得到的。
<!-- 監聽home廣播註冊 -->
        <receiver android:name="com.isoft.screen.ScreenObserver" >
            <intent-filter android:priority="2147483647" >
                <action android:name="android.intent.action.USER_PRESENT"/>
            </intent-filter>
        </receiver>

如果你想永遠服務不被系統銷燬或者防毒軟體銷燬,那麼還有一個方法,把服務設定成前臺服務,這裡我就不詳細講解了,別人已經講解得很詳細了,我就不做無用功了,別人講得好的,我們就學習別人的,我在這裡只是告訴大家方法。我推薦連結你們可以看一下(都是我們 CSDN 的偉大的博主寫的!),請叫我  【雷鋒大笑把服務設定成前臺服務講解: 點選開啟連結     連結 3(講得很好)
把服務設定成前臺服務DEMO下載: 謝謝大家支援! 附上我自己的小demo :點選下載demo