1. 前置條件
- Android Studio:確保使用最新版本(2023.3.1+)
- 目標 API:最低 API 21,兼容 Android 8.0(渠道)和 13+(權限)
- 依賴庫:使用
WorkManager
和NotificationCompat
2. 完整實現步驟
2.1 添加權限和依賴
AndroidManifest.xml
<!-- 通知權限 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <!-- Android 13+ 必須 -->
<uses-permission android:name="android.permission.INTERNET" /> <!-- 若需網絡請求 --><application><!-- 添加你的主 Activity --><activityandroid:name=".MainActivity"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity>
</application>
build.gradle (Module)
dependencies {// WorkManager 用于后臺任務implementation "androidx.work:work-runtime-ktx:2.7.1"// 通知兼容庫implementation "androidx.core:core-ktx:1.12.0"
}
2.2 創建通知渠道(Android 8.0+ 必需)
NotificationHelper.kt
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.os.Buildobject NotificationHelper {const val CHANNEL_ID = "dynamic_messages_channel"const val NOTIFICATION_ID = 101 // 用于更新同一通知fun createNotificationChannel(context: Context) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {// 避免重復創建渠道val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManagerif (notificationManager.getNotificationChannel(CHANNEL_ID) != null) return// 配置渠道屬性val name = "動態消息"val importance = NotificationManager.IMPORTANCE_HIGHval channel = NotificationChannel(CHANNEL_ID, name, importance).apply {description = "用于接收實時動態消息的推送"enableLights(true)lightColor = android.graphics.Color.RED}notificationManager.createNotificationChannel(channel)}}
}
2.3 構建動態通知
NotificationUtils.kt
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.example.myapp.R // 替換為你的包名object NotificationUtils {fun showDynamicNotification(context: Context,title: String,message: String) {// 創建點擊跳轉邏輯(示例跳轉到 MainActivity)val intent = Intent(context, MainActivity::class.java).apply {flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK}val pendingIntent = PendingIntent.getActivity(context,0,intent,PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)// 構建通知val builder = NotificationCompat.Builder(context, NotificationHelper.CHANNEL_ID).setSmallIcon(R.drawable.ic_notification) // 必須的圖標(需在 res/drawable 添加).setContentTitle(title).setContentText(message).setPriority(NotificationCompat.PRIORITY_HIGH).setContentIntent(pendingIntent).setAutoCancel(true) // 點擊后自動消失.setStyle(NotificationCompat.BigTextStyle().bigText(message)) // 長文本支持// 發送通知with(NotificationManagerCompat.from(context)) {if (NotificationManagerCompat.from(context).areNotificationsEnabled()) {notify(NotificationHelper.NOTIFICATION_ID, builder.build())}}}// 更新通知(使用相同 ID)fun updateNotification(context: Context, newTitle: String, newMessage: String) {val builder = NotificationCompat.Builder(context, NotificationHelper.CHANNEL_ID).setSmallIcon(R.drawable.ic_notification).setContentTitle(newTitle).setContentText(newMessage)NotificationManagerCompat.from(context).notify(NotificationHelper.NOTIFICATION_ID, builder.build())}
}
2.4 后臺任務調度(WorkManager)
NotificationWorker.kt
import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import kotlinx.coroutines.delayclass NotificationWorker(context: Context,params: WorkerParameters
) : CoroutineWorker(context, params) {override suspend fun doWork(): Result {// 模擬網絡請求延遲delay(3000)// 獲取動態數據(此處為模擬數據,實際需替換為真實邏輯)val title = "您有新的消息!"val content = "當前時間:${System.currentTimeMillis()}"// 顯示通知NotificationUtils.showDynamicNotification(applicationContext, title, content)return Result.success()}
}
調度任務(在 MainActivity 中)
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import java.util.concurrent.TimeUnitclass MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// 初始化通知渠道NotificationHelper.createNotificationChannel(this)// 請求通知權限(Android 13+)requestNotificationPermission()// 啟動周期性后臺任務(每15分鐘一次)val workRequest = PeriodicWorkRequestBuilder<NotificationWorker>(15, TimeUnit.MINUTES // 注意:最短間隔為15分鐘).build()WorkManager.getInstance(this).enqueue(workRequest)}private fun requestNotificationPermission() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {if (checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS) !=PackageManager.PERMISSION_GRANTED) {requestPermissions(arrayOf(android.Manifest.permission.POST_NOTIFICATIONS),REQUEST_CODE_NOTIFICATION)}}}companion object {private const val REQUEST_CODE_NOTIFICATION = 1001}
}
2.5 處理權限請求結果
在 MainActivity
中重寫 onRequestPermissionsResult
:
override fun onRequestPermissionsResult(requestCode: Int,permissions: Array<String>,grantResults: IntArray
) {super.onRequestPermissionsResult(requestCode, permissions, grantResults)when (requestCode) {REQUEST_CODE_NOTIFICATION -> {if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 用戶已授權} else {// 處理拒絕邏輯(例如顯示提示)}}}
}
3. 擴展優化建議
3.1 結合網絡請求
使用 Retrofit + Kotlin Coroutines
獲取真實數據:
// 在 NotificationWorker 中替換模擬數據
val response = apiService.fetchMessages()
if (response.isSuccessful) {val message = response.body()?.latestMessagemessage?.let {NotificationUtils.showDynamicNotification(context, it.title, it.content)}
}
3.2 通知分組(Android 7.0+)
val builder = NotificationCompat.Builder(...).setGroup("messages_group").setGroupSummary(true) // 分組摘要
3.3 通知操作按鈕
// 添加“標記已讀”操作
val readIntent = Intent(context, MarkReadReceiver::class.java)
val readPendingIntent = PendingIntent.getBroadcast(...)
builder.addAction(NotificationCompat.Action.Builder(R.drawable.ic_check,"標記已讀",readPendingIntent).build()
)
4. 常見問題解決
-
通知不顯示
- 檢查是否在 Android 13+ 設備上授予了權限
- 確保通知渠道已正確創建
- 驗證
setSmallIcon
使用了有效的資源 ID
-
后臺任務不觸發
- 確保 WorkManager 依賴已添加
- 檢查設備是否處于 Doze 模式(測試時可暫時禁用)
-
通知點擊無響應
- 確認
PendingIntent
的FLAG_IMMUTABLE
正確使用 - 檢查目標 Activity 是否在 Manifest 中注冊
- 確認
可進一步結合 Firebase Cloud Messaging (FCM) 實現服務端消息推送,或添加更復雜的交互邏輯。