Android kotlin通知功能完整实现指南:从基础到高级功能
本文将详细介绍如何在Android应用中实现通知功能,包括基础通知、动作按钮和内联回复等高级特性。
一、基础通知实现
1. 基本通知发送方法
fun sendBasicNotification(context: Context, title: String, message: String) {// 1. 创建通知渠道(Android 8.0+必需)val channelId = "default_channel"val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManagerif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {val channel = NotificationChannel(channelId,"默认通知",NotificationManager.IMPORTANCE_DEFAULT).apply {description = "普通优先级通知"}notificationManager.createNotificationChannel(channel)}// 2. 创建点击Intentval 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)// 3. 构建并发送通知val notification = NotificationCompat.Builder(context, channelId).setSmallIcon(R.drawable.ic_notification).setContentTitle(title).setContentText(message).setPriority(NotificationCompat.PRIORITY_DEFAULT).setContentIntent(pendingIntent).setAutoCancel(true).build()notificationManager.notify(System.currentTimeMillis().toInt(), notification)
}
2. 检查并请求通知权限(Android 13+)
fun checkAndRequestNotificationPermission(activity: Activity) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {when {ContextCompat.checkSelfPermission(activity,Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED -> {// 已有权限}activity.shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS) -> {// 解释为什么需要权限showPermissionRationaleDialog(activity)}else -> {// 直接请求权限ActivityCompat.requestPermissions(activity,arrayOf(Manifest.permission.POST_NOTIFICATIONS),REQUEST_CODE_NOTIFICATION_PERMISSION)}}}
}
二、带动作按钮的通知
1. 完整实现代码
fun sendNotificationWithActions(context: Context,title: String,message: String,notificationId: Int = System.currentTimeMillis().toInt()
) {// 1. 创建通知渠道val channelId = "actions_channel"val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManagerif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {val channel = NotificationChannel(channelId,"交互通知",NotificationManager.IMPORTANCE_HIGH).apply {description = "包含操作按钮的通知"enableVibration(true)vibrationPattern = longArrayOf(0, 100, 200, 300)}notificationManager.createNotificationChannel(channel)}// 2. 创建主内容Intentval mainIntent = Intent(context, MainActivity::class.java).apply {flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASKputExtra("notification_id", notificationId)}val mainPendingIntent = PendingIntent.getActivity(context,0,mainIntent,PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)// 3. 创建动作按钮val actions = listOf(createNotificationAction(context,"ACTION_REPLY","回复",R.drawable.ic_reply,1,notificationId),createNotificationAction(context,"ACTION_ARCHIVE","归档",R.drawable.ic_archive,2,notificationId))// 4. 构建通知val notification = NotificationCompat.Builder(context, channelId).setSmallIcon(R.drawable.ic_notification).setContentTitle(title).setContentText(message).setPriority(NotificationCompat.PRIORITY_HIGH).setContentIntent(mainPendingIntent).setAutoCancel(true).apply {actions.forEach { addAction(it) }}.build()// 5. 发送通知notificationManager.notify(notificationId, notification)
}private fun createNotificationAction(context: Context,action: String,title: String,iconRes: Int,requestCode: Int,notificationId: Int
): NotificationCompat.Action {val intent = Intent(context, NotificationActionReceiver::class.java).apply {this.action = actionputExtra("notification_id", notificationId)}val pendingIntent = PendingIntent.getBroadcast(context,requestCode,intent,PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)return NotificationCompat.Action.Builder(iconRes, title, pendingIntent).build()
}
2. 广播接收器实现
class NotificationActionReceiver : BroadcastReceiver() {override fun onReceive(context: Context, intent: Intent?) {val notificationId = intent?.getIntExtra("notification_id", -1) ?: returnwhen(intent.action) {"ACTION_REPLY" -> handleReplyAction(context, notificationId)"ACTION_ARCHIVE" -> handleArchiveAction(context, notificationId)// 添加更多动作处理...}}private fun handleReplyAction(context: Context, notificationId: Int) {// 启动回复Activityval intent = Intent(context, ReplyActivity::class.java).apply {flags = Intent.FLAG_ACTIVITY_NEW_TASKputExtra("notification_id", notificationId)}context.startActivity(intent)}private fun handleArchiveAction(context: Context, notificationId: Int) {// 取消通知val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManagernotificationManager.cancel(notificationId)// 显示归档成功提示Toast.makeText(context, "通知已归档", Toast.LENGTH_SHORT).show()// 这里可以添加实际归档逻辑...}
}
三、高级功能实现
1. 内联回复功能
fun sendNotificationWithInlineReply(context: Context,title: String,message: String,conversationId: Int
) {// ...前面的渠道创建等代码与之前相同...// 1. 创建远程输入val remoteInput = RemoteInput.Builder("key_text_reply").setLabel("输入回复内容").build()// 2. 创建回复动作val replyIntent = Intent(context, NotificationActionReceiver::class.java).apply {action = "ACTION_REPLY"putExtra("conversation_id", conversationId)}val replyPendingIntent = PendingIntent.getBroadcast(context,conversationId,replyIntent,PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)val replyAction = NotificationCompat.Action.Builder(R.drawable.ic_reply,"回复",replyPendingIntent).addRemoteInput(remoteInput).build()// 3. 构建消息样式通知val messagingStyle = NotificationCompat.MessagingStyle("Me").addMessage(message, System.currentTimeMillis(), null)// 4. 构建完整通知val notification = NotificationCompat.Builder(context, channelId).setSmallIcon(R.drawable.ic_notification).setStyle(messagingStyle).addAction(replyAction).build()// 5. 发送通知notificationManager.notify(conversationId, notification)
}
2. 处理内联回复
private fun handleInlineReply(intent: Intent) {val remoteInput = RemoteInput.getResultsFromIntent(intent)val replyText = remoteInput?.getCharSequence("key_text_reply")replyText?.let {val conversationId = intent.getIntExtra("conversation_id", -1)// 处理回复文本,如保存到数据库saveReplyToDatabase(conversationId, it.toString())// 更新通知显示已回复updateNotificationAsReplied(conversationId)}
}
四、最佳实践与优化建议
-
通知分组:
.setGroup("messages_group") .setGroupSummary(true)
-
大图标和样式:
.setLargeIcon(bitmap) .setStyle(NotificationCompat.BigTextStyle().bigText(longText))
-
通知重要性分级:
- IMPORTANCE_MIN:只在通知栏显示,无声音或提示
- IMPORTANCE_LOW:显示并可能发出声音
- IMPORTANCE_DEFAULT:显示并发出声音
- IMPORTANCE_HIGH:显示为弹出式通知
-
适配不同厂商:
// 针对小米设备 if (Build.MANUFACTURER.equals("xiaomi", ignoreCase = true)) {builder.setPriority(NotificationCompat.PRIORITY_MAX) }
-
测试建议:
- 测试不同Android版本的表现
- 测试应用处于前台和后台时的行为
- 测试设备锁定状态下的显示
五、常见问题解决方案
-
通知不显示:
- 检查Android 13+的通知权限
- 验证通知渠道重要性设置
- 确保提供了有效的小图标
-
动作按钮不工作:
- 检查PendingIntent的flag设置
- 验证广播接收器是否正确注册
- 确保没有重复使用相同的requestCode
-
内联回复问题:
- 使用FLAG_MUTABLE创建PendingIntent
- 确保RemoteInput的key与处理时一致
- 为Android 12+添加适当的PendingIntent flag
通过本文介绍的方法,您可以实现从基础到高级的各种通知功能,为用户提供丰富的交互体验。记得根据您的应用具体需求进行调整和优化。