如何在静默模式下保留Heads Up Notification的同时关闭通知提示音
问题核心原因
安卓8.0(API 26)及以上系统中,通知的声音、震动、优先级等核心属性由通知渠道统一管控,NotificationBuilder中设置的setSound、setVibrate属性会被渠道配置覆盖,动态修改单渠道的声音配置不会生效;调用setSilent(true)会强制降低通知优先级,导致Heads Up Notification消失。
解决方案
通过创建两个优先级相同的通知渠道实现需求:一个渠道配置声音震动,另一个渠道关闭声音震动,发通知前根据系统当前铃音模式选择对应渠道发送即可。
实现代码
1. 初始化双通知渠道
private fun initNotificationChannels() { val manager = getSystemService(NotificationManager::class.java) // 1. 带声音震动的高优先级渠道 val soundChannel = NotificationChannel( "CHANNEL_HEADS_UP_SOUND", "来电类通知(有声)", NotificationManager.IMPORTANCE_HIGH ).apply { setSound(uri, attribute) enableVibration(true) vibrationPattern = createVibrate() lightColor = Color.BLUE lockscreenVisibility = Notification.VISIBILITY_PUBLIC } // 2. 无声音震动的高优先级渠道 val silentChannel = NotificationChannel( "CHANNEL_HEADS_UP_SILENT", "来电类通知(无声)", NotificationManager.IMPORTANCE_HIGH ).apply { setSound(null, null) // 关闭通知提示音 enableVibration(false) // 关闭震动 lightColor = Color.BLUE lockscreenVisibility = Notification.VISIBILITY_PUBLIC } manager.createNotificationChannels(listOf(soundChannel, silentChannel)) }
2. 发通知前动态选择渠道
val audioManager = getSystemService(AudioManager::class.java) // 根据系统铃音模式选择对应渠道 val targetChannelId = when(audioManager.ringerMode) { AudioManager.RINGER_MODE_NORMAL -> "CHANNEL_HEADS_UP_SOUND" else -> "CHANNEL_HEADS_UP_SILENT" // 震动、静默模式下走无声渠道 } // 构造通知,移除冗余的setSound、setVibrate配置 val notificationBuilder = NotificationComBuilder(this, targetChannelId) .setContentTitle(title) .setContentText(text) .setSmallIcon(R.drawable.ic_menu_logo) .setContentIntent(pendingIntent) .setPriority(PRIORITY_MAX) // 兼容安卓7及以下设备的Heads Up展示 .setCategory(CATEGORY_CALL) .setAutoCancel(true) .setLights(Color.BLUE, 5000, 10)
注意事项
- 两个渠道的重要性必须保持为
IMPORTANCE_HIGH,才能保证Heads Up Notification正常弹出 - 通知渠道一旦创建,后续修改代码中的渠道配置不会生效,需要卸载应用重装、或者升级应用使用新的渠道ID重新创建才会生效
- API26及以上系统不需要在
NotificationBuilder中重复设置声音、震动属性,会被渠道配置覆盖
内容的提问来源于stack exchange,提问作者msickpaler
相关产品推荐
相关产品推荐

