Android Notification 本地通知與推播實戰
通知 (Notification) 是 App 在 UI 介面之外,與使用者進行非同步互動的核心管道。無論是提醒訂單狀態、顯示訊息摘要,還是呈現背景任務進度,良好的通知設計能顯著提升用戶留存。
Android 13+ 權限規範
從 Android 13 (API 33) 開始,發送通知正式列入危險權限 (Dangerous Permission)。App 必須主動向使用者請求權限,且預設是不允許的。
Manifest 宣告
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
動態請求 (Compose)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
val permissionLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted ->
if (isGranted) { /* 發送通知 */ }
}
Button(onClick = { permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) }) {
Text("允許通知")
}
}
通知頻道 (Notification Channels)
從 Android 8.0 (API 26) 開始,所有通知都必須分配到一個「頻道」。頻道允許使用者細粒度地控制通知行為(如:開啟物流通知,但關閉行銷通知)。
fun createNotificationChannel(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
"ORDER_UPDATES", // Channel ID
"訂單更新", // 使用者在系統設定看到的名稱
NotificationManager.IMPORTANCE_HIGH // 重要程度 (影響是否彈出或有聲音)
).apply {
description = "追蹤您的商品寄送狀態"
}
val manager = context.getSystemService(NotificationManager::class.java)
manager.createNotificationChannel(channel)
}
}
發送基礎通知與安全轉向
使用 NotificationCompat.Builder 來構建內容,並透過 PendingIntent 定義點擊後的行為。
fun sendOrderNotification(context: Context) {
// 點擊後開啟 Activity
val intent = Intent(context, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
context, 0, intent,
PendingIntent.FLAG_IMMUTABLE // Android 12+ 強制要求指定 Mutability
)
val builder = NotificationCompat.Builder(context, "ORDER_UPDATES")
.setSmallIcon(R.drawable.ic_delivery) // 必要:小圖示 (通常為全白背景透明)
.setContentTitle("包裹已送達!")
.setContentText("您的訂單 #12345 已經抵達指定門市。")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.setAutoCancel(true) // 點擊後自動從狀態列移除
NotificationManagerCompat.from(context).notify(1001, builder.build())
}
進階通知樣式 (Styles)
長文本 (BigTextStyle)
當內容字數較多時,使用 BigTextStyle 允許使用者展開閱讀完整內容。
.setStyle(NotificationCompat.BigTextStyle()
.bigText("這裡是非長的詳細內容說明,當使用者將通知向下拉開時,可以看到這一段完整的文字訊息內容..."))
圖片通知 (BigPictureStyle)
用於顯示宣傳美圖或截圖。
.setStyle(NotificationCompat.BigPictureStyle()
.bigPicture(myBitmap)
.bigLargeIcon(null as Bitmap?)) // 展開後隱藏大圖示,避免重複
互動與進度追蹤
動作按鈕 (Action Buttons)
你可以直接在通知上增加按鈕(最多 3 個),省去使用者手動切換 App 的麻煩。
val actionIntent = PendingIntent.getBroadcast(...)
builder.addAction(R.drawable.ic_check, "標記為已讀", actionIntent)
進度條 (Progress Bar)
適用於檔案下載或上傳任務。
val PROGRESS_MAX = 100
val PROGRESS_CURRENT = 45
// 顯示確定進度
builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false)
// 顯示不確定進度 (跑馬燈)
builder.setProgress(0, 0, true)
管理與群組化
更新與刪除通知
- 更新:使用同一個
notificationId再次呼叫notify()。 - 刪除:呼叫
manager.cancel(id)或cancelAll()。
通知的群組 (Grouping)
當發送多條相似通知(如多則聯絡人訊息)時,應使用 setGroup() 將其打包,避免霸佔使用者的通知空間。
val GROUP_KEY_MESSAGES = "com.android.example.MESSAGES"
val newMessage = NotificationCompat.Builder(context, channelId)
.setGroup(GROUP_KEY_MESSAGES)
// ...
透過精確的頻道劃分與豐富的樣式展示,通知將成為你 App 最重要的觸及工具。務必遵循規範,避免發送過多無關資訊干擾用戶。