Android開發(fā)高級(jí)進(jìn)階——Service與Notification

眾所周知,Service是Android中實(shí)現(xiàn)程序后臺(tái)運(yùn)行的解決方案,非常適合于執(zhí)行不需要和用戶交互而且要求長期運(yùn)行的任務(wù)。Notification是顯示在手機(jī)狀態(tài)欄的通知,通過Notification和startForeground可以將Service后臺(tái)服務(wù)設(shè)置為前臺(tái)服務(wù)。

一. Service的分類


按種類分為LocalService和RemoteService

  • LocalService:當(dāng)前進(jìn)程的Service,依附在主進(jìn)程上,節(jié)約資源,通信不需要進(jìn)程間通信,但主進(jìn)程被殺掉時(shí)LocalService也會(huì)被停止。一般可以做播放操作。
  • RemoteService:遠(yuǎn)程進(jìn)程的Service,是一個(gè)獨(dú)立的進(jìn)程,當(dāng)主進(jìn)程被殺掉時(shí),其服務(wù)依然會(huì)運(yùn)行,比較靈活,但使用復(fù)雜。可以做一些系統(tǒng)常駐進(jìn)程或守護(hù)進(jìn)程(當(dāng)主進(jìn)程被殺掉時(shí),可以用守護(hù)進(jìn)程喚醒主進(jìn)程)。

按類型分為前臺(tái)Service和后臺(tái)Service

  • 前臺(tái)Service:在通知欄一直顯示的服務(wù),最大程度保證服務(wù)不被殺掉。
  • 后臺(tái)Service:默認(rèn)的服務(wù)為后臺(tái)服務(wù),看不見。

前臺(tái)Service的優(yōu)先級(jí)高于后臺(tái)Service。

啟動(dòng)方式有startService和bindService

  • startService:onCreate只會(huì)在Service第一次創(chuàng)建的時(shí)候被調(diào)用,start一次之后,下次不會(huì)再onCreate了,每次會(huì)執(zhí)行onStartCommand。
  • bindService:Service中的onBind是與外界進(jìn)行關(guān)聯(lián)的。onBind返回的IBinder都會(huì)在與其他組件連接時(shí)返回,即IBinder是一個(gè)負(fù)責(zé)溝通的橋梁。

二. Service、Thread、Process


Service是處理一些后臺(tái)任務(wù),在主線程中,并不能執(zhí)行耗時(shí)操作。而Thread是開啟一個(gè)子線程,在子線程中執(zhí)行耗時(shí)操作,這樣不會(huì)阻塞主線程。

那么Service與Thread、Process有什么關(guān)系呢?

其實(shí)它們之間并無太大關(guān)聯(lián),只是Service可以放在其他進(jìn)程中,Service是進(jìn)程中的,Thread也是進(jìn)程中的,Service中耗時(shí)操作又可以在通過Thread執(zhí)行。Service中的IBinder可以幫助我們與其他進(jìn)程進(jìn)行通信。

獲取當(dāng)前進(jìn)程:Thread.currentThread().getId();

在Service中創(chuàng)建一個(gè)子線程與Activity中創(chuàng)建一個(gè)子線程有什么區(qū)別?

當(dāng)Activity被銷毀,就無法獲取在被銷毀的Activity中創(chuàng)建的子線程實(shí)例了。例如,Activity創(chuàng)建了一個(gè)子線程在后臺(tái)運(yùn)行,執(zhí)行完之后,返回?cái)?shù)據(jù)時(shí),創(chuàng)建它的Activity已被銷毀,這是線程不安全的。再例如,Activity1創(chuàng)建了一個(gè)子線程,Activity2是無法對Activity1創(chuàng)建的子線程進(jìn)行操作。
而Service是一個(gè)服務(wù),所有的Activity都可以與該Service進(jìn)行關(guān)聯(lián),即使Activity被銷毀,但依然可以獲取Service中的IBinder的實(shí)例。
所以,用Service處理后臺(tái)任務(wù),Activity就可以放心的被finish掉了,完全不用擔(dān)心對后臺(tái)任務(wù)無法進(jìn)行控制。

三. AndroidManifest.xml中Service的一些標(biāo)簽


  • name:服務(wù)的類名。
  • label:服務(wù)名,如果不設(shè)置,默認(rèn)為類名。
  • icon:服務(wù)的圖標(biāo)。
  • permission:服務(wù)的權(quán)限。
  • process:服務(wù)的進(jìn)程名。
  • enabled:boolean類型,true表示該服務(wù)默認(rèn)被系統(tǒng)啟動(dòng)。
  • exported:表示該服務(wù)是否能夠被其他應(yīng)用程序控制或連接,是否向外通過服務(wù)。

四. Notification


  1. 創(chuàng)建通知
    可以在NotificationCompat.Builder對象中為通知指定 UI 信息和操作。要?jiǎng)?chuàng)建通知,請調(diào)用NotificationCompat.Builder.build(),它將返回包含具體規(guī)范的Notification對象。要發(fā)出通知,請通過調(diào)用NotificationManager.notify()將 [Notification對象傳遞給系統(tǒng)。

  2. 必需的通知內(nèi)容
    Notification對象必須包含以下內(nèi)容:

  • 小圖標(biāo),由setSmallIcon()設(shè)置。
  • 標(biāo)題,由setContentTitle()設(shè)置。
  • 詳細(xì)文本,由setContentText()設(shè)置。
  1. 通知操作
    盡管通知操作都是可選的,但是至少應(yīng)向通知添加一個(gè)操作。 操作允許用戶直接從通知轉(zhuǎn)到應(yīng)用中的Activity,用戶可在其中查看一個(gè)或多個(gè)事件或執(zhí)行進(jìn)一步的操作。
    一個(gè)通知可以提供多個(gè)操作。應(yīng)該始終定義一個(gè)當(dāng)用戶點(diǎn)擊通知時(shí)會(huì)觸發(fā)的操作;通常,此操作會(huì)在應(yīng)用中打開Activity。也可以向通知添加按鈕來執(zhí)行其他操作,例如,暫停鬧鈴或立即答復(fù)短信。
    在Notification內(nèi)部,操作本身由PendingIntent定義,后者包含在應(yīng)用中啟動(dòng)Activity的Intent。要將PendingIntent與手勢相關(guān)聯(lián),請調(diào)用NotificationCompat.Builde的適當(dāng)方法。例如,如果要在用戶點(diǎn)擊抽屜式通知欄中的通知文本時(shí)啟動(dòng)Activity,則可通過調(diào)用setContentIntent()來添加PendingIntent。

創(chuàng)建簡單通知

以下代碼段說明了一個(gè)指定某項(xiàng) Activity 在用戶點(diǎn)擊通知時(shí)打開的簡單通知。 請注意,該代碼將創(chuàng)建TaskStackBuilder對象并使用它來為操作創(chuàng)建PendingIntent。

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!");
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, ResultActivity.class);

// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
        stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(mId, mBuilder.build());

五. 補(bǔ)充

  1. 旋轉(zhuǎn)屏幕時(shí),Activity會(huì)被重新創(chuàng)建,bindService的連接會(huì)被斷開。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容