Android Foreground Service (前臺(tái)服務(wù))

一闯割、如何保活后臺(tái)服務(wù)

Android Services (后臺(tái)服務(wù)) 里面优炬,我們了解了Android四大組件之一的Service,知道如何使用后臺(tái)服務(wù)進(jìn)行來完成一些特定的任務(wù)怨喘。但是后臺(tái)服務(wù)在系統(tǒng)內(nèi)存不足的時(shí)候,可能會(huì)被系統(tǒng)殺死振定。那么如何讓后臺(tái)服務(wù)盡量不被殺死呢必怜?基本的解決思路主要有以下幾種:

1. 提高Service的優(yōu)先級(jí):

<!-- 為防止Service被系統(tǒng)回收,可以嘗試通過提高服務(wù)的優(yōu)先級(jí)解決后频,1000是最高優(yōu)先級(jí)梳庆,數(shù)字越小,優(yōu)先級(jí)越低 -->
android:priority="1000" 

2.把service寫成系統(tǒng)服務(wù)徘郭,將不會(huì)被回收:

在Manifest.xml文件中設(shè)置persistent屬性為true靠益,則可使該服務(wù)免受out-of-memory killer的影響。但是這種做法一定要謹(jǐn)慎残揉,系統(tǒng)服務(wù)太多將嚴(yán)重影響系統(tǒng)的整體運(yùn)行效率胧后。

3.將服務(wù)改成前臺(tái)服務(wù)foreground service:

重寫onStartCommand方法,使用StartForeground(int,Notification)方法來啟動(dòng)service抱环。

注:一般前臺(tái)服務(wù)會(huì)在狀態(tài)欄顯示一個(gè)通知壳快,最典型的應(yīng)用就是音樂播放器,只要在播放狀態(tài)下镇草,就算休眠也不會(huì)被殺眶痰,如果不想顯示通知,只要把參數(shù)里的int設(shè)為0即可梯啤。

同時(shí)竖伯,對于通過startForeground啟動(dòng)的service,onDestory方法中需要通過stopForeground(true)來取消前臺(tái)運(yùn)行狀態(tài)因宇。

這個(gè)方案也是本文目前準(zhǔn)備詳細(xì)介紹的七婴。

4.利用Android的系統(tǒng)廣播

利用ANDROID的系統(tǒng)廣播檢查Service的運(yùn)行狀態(tài),如果被殺掉察滑,就再起來打厘,系統(tǒng)廣播是Intent.ACTION_TIME_TICK,這個(gè)廣播每分鐘發(fā)送一次贺辰,我們可以每分鐘檢查一次Service的運(yùn)行狀態(tài)户盯,如果已經(jīng)被結(jié)束了,就重新啟動(dòng)Service饲化。

二莽鸭、分析為何后臺(tái)服務(wù)會(huì)被回收

當(dāng)后臺(tái)服務(wù)被回收的時(shí)候,我們查看Logcat里面的日志的時(shí)候吃靠,我們可能會(huì)看到如下的日志:

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導(dǎo)致的,如何避免ANR撩笆,主要注意以下幾點(diǎn)會(huì)導(dǎo)致ANR的發(fā)生:

  • 主線程 (“事件處理線程” / “UI線程”) 在5秒內(nèi)沒有響應(yīng)輸入事件
  • BroadcastReceiver 沒有在10秒內(nèi)完成返回
  • 在主線程內(nèi)進(jìn)行網(wǎng)絡(luò)操作
  • 在主線程內(nèi)進(jìn)行一些緩慢的磁盤操作(I/O操作或數(shù)據(jù)庫操作)

至于如何避免ANR的發(fā)生捺球,各位盡量避免上面這幾種情況出現(xiàn)缸浦,基本上就能避開大部分ANR了。

三氮兵、前臺(tái)服務(wù)

1.what

前臺(tái)服務(wù)是那些被認(rèn)為用戶知道(用戶所認(rèn)可的)且在系統(tǒng)內(nèi)存不足的時(shí)候不允許系統(tǒng)殺死的服務(wù)裂逐。前臺(tái)服務(wù)必須給狀態(tài)欄提供一個(gè)通知,它被放到正在運(yùn)行(Ongoing)標(biāo)題之下——這就意味著通知只有在這個(gè)服務(wù)被終止或從前臺(tái)主動(dòng)移除通知后才能被解除泣栈。

2.why

在一般情況下卜高,Service幾乎都是在后臺(tái)運(yùn)行,一直默默地做著辛苦的工作南片。但這種情況下掺涛,后臺(tái)運(yùn)行的Service系統(tǒng)優(yōu)先級(jí)相對較低,當(dāng)系統(tǒng)內(nèi)存不足時(shí)疼进,在后臺(tái)運(yùn)行的Service就有可能被回收薪缆。
那么,如果我們希望Service可以一直保持運(yùn)行狀態(tài)且不會(huì)在內(nèi)存不足的情況下被回收時(shí)伞广,可以選擇將需要保持運(yùn)行的Service設(shè)置為前臺(tái)服務(wù)拣帽。

3.how

本文按照做音樂播放器的思路,做一下相關(guān)的說明嚼锄,如何使用前臺(tái)服務(wù)减拭。

首先要?jiǎng)?chuàng)建一個(gè)服務(wù):

public class MusicPlayerService extends Service {private static final String TAG = MusicPlayerService.class.getSimpleName();

  @Override
  public void onCreate() { super.onCreate();
      Log.d(TAG, "onCreate()");
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG, "onStartCommand()");
  }

  @Override
  public IBinder onBind(Intent intent) {
       Log.d(TAG, "onBind()");
       // TODO: Return the communication channel to the service.
    throw new UnsupportedOperationException("Not yet implemented");
  }
}

然后創(chuàng)建Notification:

在Service的onStartCommand中添加如下代碼:

@Override public int onStartCommand(Intent intent, int flags, int startId) {
  Log.d(TAG, "onStartCommand()");
  // 在API11之后構(gòu)建Notification的方式
  Notification.Builder builder = new Notification.Builder
    (this.getApplicationContext()); //獲取一個(gè)Notification構(gòu)造器
  Intent nfIntent = new Intent(this, MainActivity.class);

  builder.setContentIntent(PendingIntent.
    getActivity(this, 0, nfIntent, 0)) // 設(shè)置PendingIntent
    .setLargeIcon(BitmapFactory.decodeResource(this.getResources(),
      R.mipmap.ic_large)) // 設(shè)置下拉列表中的圖標(biāo)(大圖標(biāo))
    .setContentTitle("下拉列表中的Title") // 設(shè)置下拉列表里的標(biāo)題
    .setSmallIcon(R.mipmap.ic_launcher) // 設(shè)置狀態(tài)欄內(nèi)的小圖標(biāo)
    .setContentText("要顯示的內(nèi)容") // 設(shè)置上下文內(nèi)容
    .setWhen(System.currentTimeMillis()); // 設(shè)置該通知發(fā)生的時(shí)間
       Notification notification = builder.build(); // 獲取構(gòu)建好的Notification
  notification.defaults = Notification.DEFAULT_SOUND; //設(shè)置為默認(rèn)的聲音
}

在完成Notification通知消息的構(gòu)建后,在Service的onStartCommand中可以使用startForeground方法來讓Android服務(wù)運(yùn)行在前臺(tái)区丑。

#參數(shù)一:唯一的通知標(biāo)識(shí)拧粪;參數(shù)二:通知消息。
startForeground(110, notification);// 開始前臺(tái)服務(wù)

如果需要停止前臺(tái)服務(wù)沧侥,可以使用stopForeground來停止正在運(yùn)行的前臺(tái)服務(wù)可霎。

@Override public void onDestroy() {
  Log.d(TAG, "onDestroy()");
  stopForeground(true);// 停止前臺(tái)服務(wù)--參數(shù):表示是否移除之前的通知
  super.onDestroy();
}

到此為止,我們基本上就學(xué)會(huì)了如何使用前臺(tái)服務(wù)了正什。

四啥纸、總結(jié)

1. 前臺(tái)服務(wù)與普通服務(wù)的區(qū)別

  • 前臺(tái)Service的系統(tǒng)優(yōu)先級(jí)更高号杏、不易被回收婴氮;
  • 前臺(tái)Service會(huì)一直有一個(gè)正在運(yùn)行的圖標(biāo)在系統(tǒng)的狀態(tài)欄顯示,下拉狀態(tài)欄后可以看到更加詳細(xì)的信息盾致,非常類似于通知的效果主经。

2. 拓展閱讀:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市庭惜,隨后出現(xiàn)的幾起案子罩驻,更是在濱河造成了極大的恐慌,老刑警劉巖护赊,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惠遏,死亡現(xiàn)場離奇詭異砾跃,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)节吮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進(jìn)店門抽高,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人透绩,你說我怎么就攤上這事翘骂。” “怎么了帚豪?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵碳竟,是天一觀的道長。 經(jīng)常有香客問我狸臣,道長莹桅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任固棚,我火速辦了婚禮统翩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘此洲。我一直安慰自己厂汗,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布呜师。 她就那樣靜靜地躺著娶桦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪汁汗。 梳的紋絲不亂的頭發(fā)上衷畦,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天,我揣著相機(jī)與錄音知牌,去河邊找鬼祈争。 笑死,一個(gè)胖子當(dāng)著我的面吹牛角寸,可吹牛的內(nèi)容都是我干的菩混。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼扁藕,長吁一口氣:“原來是場噩夢啊……” “哼沮峡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起亿柑,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤邢疙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疟游,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡呼畸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了颁虐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片役耕。...
    茶點(diǎn)故事閱讀 38,650評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖聪廉,靈堂內(nèi)的尸體忽然破棺而出瞬痘,到底是詐尸還是另有隱情,我是刑警寧澤板熊,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布框全,位于F島的核電站,受9級(jí)特大地震影響干签,放射性物質(zhì)發(fā)生泄漏津辩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一容劳、第九天 我趴在偏房一處隱蔽的房頂上張望喘沿。 院中可真熱鬧,春花似錦竭贩、人聲如沸蚜印。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窄赋。三九已至,卻和暖如春楼熄,著一層夾襖步出監(jiān)牢的瞬間忆绰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工可岂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留错敢,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓缕粹,卻偏偏與公主長得像稚茅,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子致开,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容