iT邦幫忙

2025 iThome 鐵人賽

DAY 12
0

NotificationManagerService

intro

在 Android 系統中,通知 (Notification) 是應用程式與使用者溝通最重要的方式之一。
它提供了一種非侵入性的互動方式,可以讓應用程式在不打斷使用者操作的前提下,及時地傳遞訊息。
而背後的關鍵角色,就是 NotificationManagerService (NMS)。
NMS 的角色可以簡單理解為:

  • 應用程式層 → 呼叫 NotificationManager 發送通知
  • 系統服務層 → NotificationManagerService 接收、管理、排序與分發通知
  • UI 呈現層 → 狀態列 (StatusBar)、通知欄 (Notification Shade) 負責渲染

通知系統整體架構

Android 的通知系統由三個主要部分組成:

  1. 應用程式 (App Layer)
  • 開發者透過 NotificationManager API 發送通知
  • 使用 NotificationChannel 來設定通知層級、聲音、震動等行為
  1. 系統服務 (System Server)
  • NotificationManagerService (NMS)
    • 負責接收與管理所有 App 的通知
    • 處理通知的新增、更新、移除、排序
    • 檢查權限與通知通道設定
  1. 系統 UI (SystemUI Process)
  • StatusBarManagerService (SBMS) 與 SystemUI 協作
  • 負責顯示通知在狀態列、下拉通知欄
  • 使用 StatusBar 介面與 NMS 交互
[App]
   │   (NotificationManager)
   ▼
[Binder IPC]
   │
   ▼
[System Server]
   └─ NotificationManagerService
         │
         ├─ 檢查權限、通道、排序
         │
         └─ StatusBarManagerService
                │
                ▼
          [SystemUI Process]
                │
                ▼
         狀態列 (StatusBar) / 通知欄 (Shade)

NotificationManagerService 的啟動與註冊

在 SystemServer 啟動流程中,會建立 NotificationManagerService:

NotificationManagerService nms = new NotificationManagerService(context);
ServiceManager.addService(Context.NOTIFICATION_SERVICE, nms);

流程:

  1. 初始化 NMS:建立內部資料結構 (例如 NotificationRecord 列表)
  2. 註冊至 ServiceManager:讓應用程式透過 Binder 呼叫
    3.與 StatusBarManagerService 建立連結:通知能夠顯示在狀態列

通知的生命週期

  1. 通知的發送
    應用程式端:
NotificationManager nm = context.getSystemService(NotificationManager.class);
Notification notification = new NotificationCompat.Builder(context, "channel_id")
        .setContentTitle("訊息提醒")
        .setContentText("您有一則新訊息")
        .setSmallIcon(R.drawable.ic_notify)
        .build();
nm.notify(1, notification);

實際流程:

  1. App 呼叫 NotificationManager.notify()
  2. Binder IPC → NotificationManagerService.enqueueNotificationInternal()
  3. NMS 檢查:
  • 應用是否有通知權限
  • 通知通道 (NotificationChannel) 是否存在
  • 系統設定是否允許顯示
  1. NMS 處理邏輯
    NMS 收到通知後,會建立 NotificationRecord,並放入通知列表中。
    主要流程:

  2. 建立 NotificationRecord
    2.檢查 優先級 (Priority) 與 重要性 (Importance)

  3. 檢查 鎖定畫面 (LockScreen Visibility)

  4. 決定是否需要提醒 (聲音 / 震動 / Heads-up)

  5. 通知 StatusBarManagerService 更新 UI

  6. 通知的顯示

  • StatusBarManagerService (SBMS) 會透過 IStatusBar 介面,把通知傳遞給 SystemUI Process
  • SystemUI 中的 NotificationShadeWindow / StatusBar 負責渲染 UI
  • 狀態列會顯示小圖示,下拉後顯示完整通知卡片
  1. 通知的更新
    當應用程式再次呼叫 notify(),如果通知 ID 相同:
  • NMS 會將舊的 NotificationRecord 替換
  • StatusBar UI 重新刷新該通知
  1. 通知的移除
    應用程式呼叫:
nm.cancel(1);

流程:

  1. Binder IPC → NotificationManagerService.cancelNotification()
  2. NMS 從通知列表移除
  3. 通知 StatusBarManagerService 更新畫面

通知通道 (NotificationChannel)

從 Android 8.0 (Oreo) 開始,所有通知必須綁定 NotificationChannel。

  1. 為何需要 NotificationChannel?
  • 提供使用者細粒度控制
  • 不同類型通知可以有不同的重要性
  • 使用者可透過系統設定介面管理
  1. 通道的重要性等級
    |等級 | 常數 | 行為
    |----|----|----|
    |高 |IMPORTANCE_HIGH |Heads-up 通知、音效、震動
    |中 |IMPORTANCE_DEFAULT |顯示在狀態列,有聲音
    |低 |IMPORTANCE_LOW |顯示在狀態列,無聲音
    |最低 |IMPORTANCE_MIN |不顯示在狀態列,只在下拉欄中出現
  2. 流程
  • App 建立 Channel → 註冊給 NMS
  • 使用者可在設定中修改 Channel 行為
  • NMS 會根據 Channel 設定,決定通知的最終表現

狀態列事件 (StatusBar Events)

NMS 不僅負責通知,還需要與 StatusBar 協作,處理「狀態列事件」。

  1. 狀態列小圖示 (StatusBar Icon)
  • 每個通知可指定 setSmallIcon()
  • NMS 通知 SBMS → SBMS 更新 SystemUI → 狀態列顯示圖示
  1. Heads-up 通知
  • 當通知重要性高 (High) 且滿足條件,會觸發 Heads-up 彈出視窗
  • SystemUI 負責渲染浮動通知卡片
  1. 鎖定畫面通知
  • NMS 檢查通知可見性 (VISIBILITY_PUBLIC / PRIVATE / SECRET)
  • 決定是否在鎖屏畫面顯示
App.notify()
   │
   ▼
NotificationManagerService
   │
   ▼
StatusBarManagerService
   │
   ▼
SystemUI(StatusBar/NotificationShade)
   │
   ▼
狀態列圖示 / Heads-up / 通知卡片

權限與安全性

  1. 通知權限
  • Android 13 起,需要 POST_NOTIFICATIONS 權限
    -NMS 會檢查是否授權
  1. 特殊通知
  • 系統通知 (foreground service、重要警告) 可能有額外保護
  • 某些通知只能由系統應用建立 (例如藍牙、網路狀態)
  1. 使用者控制
  • 使用者可關閉 App 的所有通知
  • 或僅關閉某些 Channel

Summary

NotificationManagerService (NMS) 是 Android 通知系統的核心:

  • 負責接收、管理、分發通知
  • 與 StatusBarManagerService、SystemUI 協作,完成通知的 UI 呈現
  • 通知通道 (NotificationChannel) 提供細粒度控制
  • 狀態列事件 (小圖示、Heads-up、鎖屏通知) 都由 NMS 間接驅動

上一篇
#10
系列文
安豬複習12
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言