保證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。
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- flags = START_STICKY;
- return super.onStartCommand(intent, flags, startId);
- }
【結論】 手動返回START_STICKY,親測當service因內存不足被kill,當內存又有的時候,service又被重新創建,比較不錯,但是不能保證任何情況下都被重建,比如進程被幹掉了....
提升service優先級
在AndroidManifest.xml文件中對於intent-filter可以通過android:priority = "1000"這個屬性設置最高優先級,1000是最高值,如果數字越小則優先級越低,同時適用於廣播。
- <service
- android:name="com.dbjtech.acbxt.waiqin.UploadService"
- android:enabled="true" >
- <intent-filter android:priority="1000" >
- <action android:name="com.dbjtech.myservice" />
- </intent-filter>
- </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方法內添加如下代碼:
- 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", "請保持程序在後臺運行",
- pendingintent);
- <span style="color:#ff0000;"> startForeground(0x111, notification);</span>
注意在onDestroy裏還需要stopForeground(true),運行時在下拉列表會看到自己的APP在:
【結論】如果在極度極度低內存的壓力下,該service還是會被kill掉,並且不一定會restart
onDestroy方法裏重啓service
service +broadcast 方式,就是當service走ondestory的時候,發送一個自定義的廣播,當收到廣播的時候,重新啓動service;
- <receiver android:name="com.dbjtech.acbxt.waiqin.BootReceiver" >
- <intent-filter>
- <action android:name="android.intent.action.BOOT_COMPLETED" />
- <action android:name="android.intent.action.USER_PRESENT" />
- <action android:name="com.dbjtech.waiqin.destroy" />//這個就是自定義的action
- </intent-filter>
- </receiver>
- @Override
- public void onDestroy() {
- stopForeground(true);
- Intent intent = new Intent("com.dbjtech.waiqin.destroy");
- sendBroadcast(intent);
- super.onDestroy();
- }
- public class BootReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals("com.dbjtech.waiqin.destroy")) {
- //TODO
- //在這裏寫重新啓動service的相關操作
- startUploadService(context);
- }
- }
- }
也可以直接在onDestroy()裏startService
- @Override
- public void onDestroy() {
- Intent sevice = new Intent(this, MainService.class);
- this.startService(sevice);
- super.onDestroy();
- }
【結論】當使用類似口口管家等第三方應用或是在setting裏-應用-強制停止時,APP進程可能就直接被幹掉了,onDestroy方法都進不來,所以還是無法保證~.~
Application加上Persistent屬性
看Android的文檔知道,當進程長期不活動,或系統需要資源時,會自動清理門戶,殺死一些Service,和不可見的Activity等所在的進程。但是如果某個進程不想被殺死(如數據緩存進程,或狀態監控進程,或遠程服務進程),可以這麼做:
- <application
- android:name="com.test.Application"
- android:allowBackup="true"
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- <span style="color:#ff0000;"> android:persistent="true"</span>
- android:theme="@style/AppTheme" >
- </application>
【結論】據說這個屬性不能亂設置,不過設置後,的確發現優先級提高不少,或許是相當於系統級的進程,但是還是無法保證存活
監聽系統廣播判斷Service狀態
通過系統的一些廣播,比如:手機重啓、界面喚醒、應用狀態改變等等監聽並捕獲到,然後判斷我們的Service是否還存活,別忘記加權限啊。
- <receiver android:name="com.dbjtech.acbxt.waiqin.BootReceiver" >
- <intent-filter>
- <action android:name="android.intent.action.BOOT_COMPLETED" />
- <action android:name="android.intent.action.USER_PRESENT" />
- <action android:name="android.intent.action.PACKAGE_RESTARTED" />
- <action android:name="com.dbjtech.waiqin.destroy" />
- </intent-filter>
- </receiver>
- @Override
- public void onReceive(Context context, Intent intent) {
- if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
- System.out.println("手機開機了....");
- startUploadService(context);
- }
- if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
- startUploadService(context);
- }
- }
【結論】這也能算是一種措施,不過感覺監聽多了會導致Service很混亂,帶來諸多不便