今天我开始针对API 26进行开发,这迫使我使用通知渠道。
我的问题是,现在每次新通知(包括更新)都会播放一个恼人的声音。
如何禁用这个声音?
我尝试将此声音替换为自定义mp3声音,然后传递一个带有静音的mp3给它,但被忽略了。
我只是添加了一个非常低优先级的通知,基本上给用户提供了与应用程序交互后执行一些操作的选项。没有理由让它变成大声的,用户会知道他可以参考通知,因为他已经做了一定的事情,他知道会引起通知的出现。
用户确实会因为那个声音而感到烦恼。
今天我开始针对API 26进行开发,这迫使我使用通知渠道。
我的问题是,现在每次新通知(包括更新)都会播放一个恼人的声音。
如何禁用这个声音?
我尝试将此声音替换为自定义mp3声音,然后传递一个带有静音的mp3给它,但被忽略了。
我只是添加了一个非常低优先级的通知,基本上给用户提供了与应用程序交互后执行一些操作的选项。没有理由让它变成大声的,用户会知道他可以参考通知,因为他已经做了一定的事情,他知道会引起通知的出现。
用户确实会因为那个声音而感到烦恼。
如果您想保留频道的重要性,只是想删除声音,notificationChannel.setSound(null, null);
似乎可以解决问题。
编辑:请确保更改频道 ID(并删除旧频道),以便将其应用于现有用户。 (应用程序无法修改频道,只能由用户进行修改。)
NotificationManager.IMPORTANCE_DEFAULT
。这将禁用声音,并且对于重要性来说是一个不错的选择。请注意,如果您使用NotificationManager.IMPORTANCE_HIGH
并且多次显示相同的通知,则它将继续弹出。使用IMPORTANCE_DEFAULT
还可以防止再次弹出相同的通知。 - MarkymarkNotificationManager.IMPORTANCE_DEFAULT
,但是在创建通知时仍然有声音。 - user924(2019 年 5 月更新:使用 NotificationManager.IMPORTANCE_LOW
,并为其创建一个新频道,这样才能避免在 Android Q 上出现问题,至少在模拟器中会有声音...)
解决方法是使用 NotificationManager.IMPORTANCE_LOW
并为其创建一个新的通道。一旦创建了通道,就无法更改其重要性(当然你可以尝试更改,但新的重要性将被忽略)。系统似乎会永久存储通道信息,并且仅在卸载应用程序时才会删除任何已创建的通道。[更新:根据Ferran Negre的评论,您可以通过 nm.deleteNotificationChannel(nChannel.getId());
删除通道,并使用 nm.createNotificationChannel(nChannel);
重新创建它,但明显存在一个限制,即不能创建具有已删除通道相同 ID 的通道,并期望能够对未删除的通道应用不同的设置,参见 acoder 的回答]
之前的 Android 版本默认情况下没有播放声音,但自 Android O 起发生了变化,只有在目标 API 26(使用通知频道)时才会发出声音。这是一种不一致性,实际上是一个 bug:
造成这种情况的原因是当你使用 NotificationManager.IMPORTANCE_DEFAULT
(默认情况下不需要声音)创建通道时,Android 实际上将其“某种程度上”注册为 NotificationManager.IMPORTANCE_HIGH
(默认情况下播放声音)。
可以通过进入通知选项(长按通知条目)来检查此问题,在那里您将看到它是 NotificationManager.IMPORTANCE_HIGH
类型,然后禁用通知并重新启用通知。在此过程中,它从 NotificationManager.IMPORTANCE_HIGH
"降级" 到非声音的实际注册状态 NotificationManager.IMPORTANCE_DEFAULT
。
该 bug 已提交到 Android 问题跟踪器,请对其进行标记(由 Google 标记为“无法修复(不可行)”,因为... 特权)。
顺便说一句,https://developer.android.com/training/notify-user/channels 上的新文档声称默认行为以前就是这样,即在 Android 8.0 之前,default播放声音,这是绝对不正确的。以下是它们的列表:
User-visible importance level Importance Priority
(Android 8.0 and higher) (Android 7.1 and lower)
Urgent Makes a sound and appears as IMPORTANCE_HIGH PRIORITY_HIGH
a heads-up notification or PRIORITY_MAX
High Makes a sound IMPORTANCE_DEFAULT PRIORITY_DEFAULT
Medium No sound IMPORTANCE_LOW PRIORITY_LOW
Low No sound and does not appear IMPORTANCE_MIN PRIORITY_MIN
in the status bar
你甚至可以看到可见性重要性高和通知重要性高之间的不匹配...我不知道他们为什么这样做。他们在代码中肯定有一个bug。以下所有内容都已过时,但提到的错误仍然有效。我的错误是认为NotificationManager.IMPORTANCE_MIN是从NotificationManager.IMPORTANCE_DEFAULT开始的下一个更低级别,但实际上是NotificationManager.IMPORTANCE_LOW。当您通过长按通知并切换该通道的所有频道按钮进入应用程序的通知设置后,再将该通道的开关关闭并再次打开时,它实际上会将自身设置为NotificationManager.IMPORTANCE_DEFAULT,并且不会播放任何声音。我还注意到,在崩溃之后,它被重置为NotificationManager.IMPORTANCE_HIGH。因此,基本上解决方法是使用NotificationManager.IMPORTANCE_MIN。但是,您必须创建一个新的通道,以便此NotificationManager.IMPORTANCE_MIN生效,因为一旦创建了一个通道,似乎就无法更改其重要性。更新:结果发现使用NotificationManager.IMPORTANCE_MIN的解决方法具有缺点。当您使用该重要性级别时,通知将不再完全显示在通知抽屉中,而是插入一个默认情况下折叠的新通知通道组中(每次拉下抽屉时都会重新折叠)。真糟糕!更新2:深入挖掘后,发现这好像是正确注册为NotificationManager.IMPORTANCE_DEFAULT,但某种方式它神奇地升级到NotificationManager.IMPORTANCE_HIGH,就像当用户将设置从默认设置更改为高级设置时一样。关闭通知然后再次打开后,该选项也会重置为默认值。IMPORTANCE_DEFAULT
并且声音被播放了。 - user924nm.deleteNotificationChannel(nChannel.getId());
和 nm.createNotificationChannel(nChannel);
之后再次执行,那么 NotificationManager.IMPORTANCE_LOW
将会生效(对我来说是有效的)。 - Ferran Negre那么我将添加一个完整的答案来帮助解决问题。如果您阅读androidx中的NotificationCompat
代码。
/**
* Silences this instance of the notification, regardless of the sounds or vibrations set
* on the notification or notification channel.
*/
public @NonNull Builder setNotificationSilent() {
mSilent = true;
return this;
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
// no sound or vibration
.setNotificationSilent()
// no sound
builder.setSound(null);
// no vibration
mChannel.setVibrationPattern(new long[]{ 0 });
mChannel.enableVibration(true);
setSilent
也会使通知不再弹出,这不是我想要的。 setSound(null)
的效果符合预期。 - Florian WaltherNotificationCompat.Builder.setSilent(true)
该方法可以发布一个无声无振动的通知,无论通知渠道的重要性设置如何。
androidx
) 的一部分,而我们大多数人可能已经在使用它了。 - Daniel F notificationManager.deleteNotificationChannel("channel_id"));
NotificationChannel notificationChannel = new NotificationChannel(
"channel_id", "channel_name",
NotificationManager.IMPORTANCE_HIGH);
notificationChannel.setSound(null, null);
notificationManager.createNotificationChannel(notificationChannel);
我测试了许多安卓设备,以下代码对我有效。
首先,创建一个通知构建器(notificationBuilder),如果您的Build.Version大于26,请添加一个新渠道(channel)。
private val notificationBuilder: NotificationCompat.Builder by lazy {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) NotificationCompat.Builder(context) else {
val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channelId = "MUSIC"
val channelName = "音乐控制栏"
val importance = NotificationManager.IMPORTANCE_MIN
val channel = NotificationChannel(channelId, channelName, importance)
manager.createNotificationChannel(channel)
channel.enableLights(false)
channel.vibrationPattern = longArrayOf(0L)
channel.enableVibration(false)
channel.setSound(null, null)
NotificationCompat.Builder(context, channelId)
}
}
notificationBuilder.setDefaults(Notification.DEFAULT_LIGHTS ).setVibrate( longArrayOf(0L)).setSound(null)
第三,如果build.version大于24,请设置其优先级。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
notificationBuilder.priority = NotificationManager.IMPORTANCE_MIN
}
NotificationManager.IMPORTANCE_LOW
当我需要在我的音乐应用中创建通知时,它不会发出声音。
如果您已经创建了一个通知渠道,则需要更改渠道ID或仅卸载先前的应用程序并重新安装。
对我来说解决方案是创建群组通知。
val builder = NotificationCompat.Builder(this)
.setGroupAlertBehavior(GROUP_ALERT_SUMMARY)
.setGroup("My Group")
.setGroupSummary(false)
.setDefaults(DEFAULT_ALL)
.setSound(null)
但是在这种情况下,如果您发送一个新的通知并带有新的ID,那么它将与先前的通知分组。
https://github.com/anars/blank-audio/blob/master/1-second-of-silence.mp3
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel(
channelId.toString(), title,
NotificationManager.IMPORTANCE_DEFAULT
)
notificationChannel.setSound(null,null)
notificationChannel.enableVibration(false)
notificationChannel.description = body
if(notificationManager.getNotificationChannel(channelId.toString())==null) {
notificationManager.createNotificationChannel(notificationChannel)
}
if (data["sound"]?.equals("default", true) == true) {//if your app need contorl sound enable
RingtoneManager.getRingtone(
this,
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
).play()
}
if(pushShake.isTrue() ){//if your app need contorl vibarate enable
val vbmanager= getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vbmanager.vibrate(VibrationEffect.createOneShot(500,VibrationEffect.DEFAULT_AMPLITUDE))
}
}
以下代码涉及通知,但在API 26上不会播放声音或震动,因此不必担心设置声音或振动。
notificationManager.notify(channelId.toInt(), notificationBuilder.apply {
setContentIntent(pendingIntent)
setSmallIcon(R.drawable.img_logo)
setTicker(title)
setNumber(data["badge"]?.toIntOrNull() ?: 0)
setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL)
color = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
resources.getColorMuteDepre(R.color.colorAccent2)
} else {
Color.parseColor("#ffffff")
}
setContentTitle(title)
setContentText(body)
setWhen(System.currentTimeMillis())
setAutoCancel(true)
setSound(null)
setVibrate(longArrayOf())
if (pushShake.isTrue() && data["sound"]?.equals("default", true) == true) {
setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
val vbmanager = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vbmanager.vibrate(500)
}
}else{
if (data["sound"]?.equals("default", true) == true) {
setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
}
if (pushShake.isTrue() ) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
val vbmanager = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vbmanager.vibrate(500)
}
}
}
setStyle(
NotificationCompat.BigTextStyle().bigText(body).setSummaryText(body).setBigContentTitle(
title
)
)
setPriority(NotificationCompat.PRIORITY_DEFAULT)
}.build())