android service被系統回收的解決方法

android service被系統回收的解決方法

androidservicekill 網絡

本身的app的service老是容易被系統回收,蒐羅了一下,基本上的解決思路有如下幾種: 
1.把service寫成系統服務,將不會被回收(未實踐): 
在Manifest.xml文件中設置persistent屬性爲true,則可以使該服務免受out-of-memory killer的影響。可是這種作法必定要謹慎,系統服務太多將嚴重影響系統的總體運行效率。 
2.提升service的優先級(未實踐): 
設置android:priority="1000" 
app

Xml代碼  收藏代碼異步

  1. <!-- 爲了消去加上android:priority="1000"後出現的警告信息,能夠設置android:exported屬性,指示該服務是否可以被其餘應用程序組件調用或跟它交互 -->  優化

  2.         <service android:name="com.example.helloandroid.weatherforecast.service.UpdateWidgetService" android:exported="false" >  this

  3.             <!-- 爲防止Service被系統回收,能夠經過提升優先級解決,1000是最高優先級,數字越小,優先級越低 -->  google

  4.             <intent-filter android:priority="1000"></intent-filter>  spa

  5.         </service>  線程


3.將服務寫成前臺服務foreground service(已實踐,很大程度上能解決問題,但不能保證必定不會被殺): 
重寫onStartCommand方法,使用StartForeground(int,Notification)方法來啓動service。 
注:前臺服務會在狀態欄顯示一個通知,最典型的應用就是音樂播放器,只要在播放狀態下,就算休眠也不會被殺,若是不想顯示通知,只要把參數裏的int設爲0便可。 
rest

Java代碼  收藏代碼

  1. Notification notification = new Notification(R.drawable.logo,  

  2.                 "wf update service is running",  

  3.                 System.currentTimeMillis());  

  4.         pintent=PendingIntent.getService(this0, intent, 0);  

  5.         notification.setLatestEventInfo(this"WF Update Service",  

  6.                 "wf update service is running!", pintent);  

  7.           

  8.         //讓該service前臺運行,避免手機休眠時系統自動殺掉該服務  

  9.         //若是 id 爲 0 ,那麼狀態欄的 notification 將不會顯示。  

  10.         startForeground(startId, notification);  


同時,對於經過startForeground啓動的service,onDestory方法中須要經過stopForeground(true)來取消前臺運行狀態。 

ps:若是service被殺後下次重啓出錯,多是此時重發的Intent爲null的緣故,能夠經過修改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_COMPATIBILITY:START_STICKY的兼容版本,但不保證服務被kill後必定能重啓。 

Java代碼  收藏代碼

  1. //if this service's process is killed, then it will be scheduled for a restart and the last delivered Intent re-delivered to it again   

  2. return Service.START_REDELIVER_INTENT;  


4.利用ANDROID的系統廣播檢查Service的運行狀態,若是被殺掉,就再起來(未實踐): 
利用的系統廣播是Intent.ACTION_TIME_TICK,這個廣播每分鐘發送一次,咱們能夠每分鐘檢查一次Service的運行狀態,若是已經被結束了,就從新啓動Service。 
具體的實現,能夠參考這個連接:http://mobile.51cto.com/abased-374969.htm 

補充:以上是解決service容易被回收的方法,可是再進一步深究,爲何service會被系統殺掉呢?經過分析手機的logcat日誌發現這麼一段話: 

引用


06-19 08:01:32.755 W/ActivityManager( 2081): Killing ProcessRecord{43a96570 6437:com.example.helloandroid/u0a187}: background ANR 
06-19 08:01:32.910 I/ActivityManager( 2081): Process com.example.helloandroid (pid 6437) (adj 0) has died. 

看來這個ANR(Application Not Responding)是關鍵。上網查到的解釋是: 在以下狀況下,Android會報出ANR錯誤: – 主線程 (「事件處理線程」 / 「UI線程」) 在5秒內沒有響應輸入事件 – BroadcastReceiver 沒有在10秒內完成返回 一般狀況下,下面這些作法會致使ANR 一、在主線程內進行網絡操做 二、在主線程內進行一些緩慢的磁盤操做(例如執行沒有優化過的SQL查詢) 主線程中執行過多的操做也是很差的,個人主線程裏有訪問網絡的處理,因而想辦法將網絡訪問移出主線程,一般有兩種方法:把訪問網絡放在獨立線程或者異步線程AsyncTask中。至於具體怎麼實現,google之。

相關文章
相關標籤/搜索