禁用来自NotificationChannel的声音


78

今天,我开始针对API 26,这迫使我使用通知通道。

我的问题是,现在在每个新通知(包括对其的更新)上都会播放烦人的声音。

如何禁用此声音?

我尝试用自定义的mp3声音替换此声音,然后将其传递给带有静音的mp3,但这被忽略。

我只是添加了一个优先级非常低的通知,基本上是给用户一个与应用程序交互后执行某些操作的选项。没有理由大声喊叫,用户将知道他可以参考该通知,因为他已经对应用进行了某些操作,他知道该操作将导致显示通知。

用户真的会开始被那种声音烦恼。

Answers:


115

如果您想保持频道的重要性,而只是删除声音,notificationChannel.setSound(null, null);似乎就可以了。

编辑: 确保重命名频道(并删除旧频道)以将其应用于现有用户。(可以创建频道,但不能由应用程序修改频道,只有用户可以。)


20
卸载/重新安装,或仅重命名NotificationChannel。
Bjarte Aune Olsen

您可以通过API删除频道,而无需为此卸载应用程序
SolidSnake

1
我认为使用更好的解决方案NotificationManager.IMPORTANCE_DEFAULT。这会禁用声音,并且是重要的一个不错的选择。请注意,如果您使用NotificationManager.IMPORTANCE_HIGH且多次显示相同的通知,它将不断弹出。IMPORTANCE_DEFAULT如果您显示相同的通知,使用还可以防止该通知再次弹出。
Markymark,

13
@Markymark WRONG我曾经用过NotificationManager.IMPORTANCE_DEFAULT,但在创建通知时仍然有声音
user924 '18八月

1
NotificationManager.IMPORTANCE_LOW在音乐应用程序中对我有用以禁用声音。
Akash Bisariya

97

(更新2019-05:Android Q变得更糟NotificationManager.IMPORTANCE_LOW,至少在模拟器中使用时我什至会发出声音...)


解决方案是为其使用NotificationManager.IMPORTANCE_LOW并创建一个新渠道。创建频道后,您将无法更改重要性(可以,但是可以忽略新的重要性)。频道信息似乎将由系统永久存储,并且仅在卸载应用程序时才会删除创建的任何频道。[更新:根据Ferran Negre的评论,您可以通过删除频道nm.deleteNotificationChannel(nChannel.getId());并使用重新创建频道,nm.createNotificationChannel(nChannel);但是显然存在一个限制,即您无法创建具有与已删除频道相同ID的频道,并且期望能够应用不同的频道设置为未删除的频道,请参见编码器的答案]

虽然先前的Android版本默认不会播放声音,但Android O会对此进行更改,但仅当您以API 26为目标(即使用通知通道)时才会发生变化。这是一个不一致的地方,实际上,这是一个错误:

这样做的原因是,当您使用NotificationManager.IMPORTANCE_DEFAULT(默认情况下不配音)创建频道时,Android实际上会将其“注册为” NotificationManager.IMPORTANCE_HIGH(默认情况下播放声音)。

您可以通过进入通知选项(长按通知条目)来进行检查,您将在其中阅读该消息的类型NotificationManager.IMPORTANCE_HIGH,然后禁用该通知,然后重新启用它。在此过程中,它会从降级NotificationManager.IMPORTANCE_HIGH为不发音的实际注册NotificationManager.IMPORTANCE_DEFAULT

该错误已提交给Android问题跟踪器,因此您可能需要对其加注标(Google标记为“不会修复(不可行)”,因为...被宠坏了)。


顺便说一句,在新的文档https://developer.android.com/training/notify-user/channels 要求,默认的行为习惯是这样,即默认发挥之前的Android 8.0,一个声音,是绝对不正确的。这是他们的清单

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

您甚至可以看到可见性重要性高和通知重要性高之间的不匹配...我不知道他们为什么这样做。他们肯定在他们的代码中有一个错误。


下一行下面的所有内容都已过时,但是此处提到的错误仍然有效。我的错误是认为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,就像用户明确将设置从默认更改为高时那样。关闭通知然后再次打开后,该通知也将重置为默认值。


8
这个答案的真正重要的部分:“创建频道后,您将无法更改重要性(可以,但是可以忽略新的重要性)。” 我挣扎了很长时间,因为我不明白为什么我对NotificationChannel所做的任何更改都没有反映在应用程序的行为中。每次更改频道时,都必须重命名该频道才能看到更改。
Bjarte Aune Olsen

新频道ID或新频道名称,还是新频道ID和频道名称?
user924

1
我设定IMPORTANCE_DEFAULT并播放了声音
user924

悲伤,就看到了这样一个简单的错误仍然没有得到解决。谢谢您记下所有细节,经历了同样的痛苦。
基拉(Kira)

1
我想如果您这样做: nm.deleteNotificationChannel(nChannel.getId());nm.createNotificationChannel(nChannel);在以后。然后NotificationManager.IMPORTANCE_LOW将工作(为我工作)。
Ferran Negre

6

据我所知,由于API 26(Oreo),一旦创建通知,便无法更改它的声音。

    notificationManager.deleteNotificationChannel("channel_id"));
    NotificationChannel notificationChannel = new NotificationChannel(
        "channel_id", "channel_name",
        NotificationManager.IMPORTANCE_HIGH);
    notificationChannel.setSound(null, null);
    notificationManager.createNotificationChannel(notificationChannel);

即使删除频道创建之前确实没有帮助。

Google文档说:

android.app.NotificationManager public void deleteNotificationChannel(String channelId)

删除给定的通知通道。如果您使用相同的ID创建一个新频道,则已删除的频道将使用与删除前相同的所有设置进行删除。

NotificationChannel#setSound() 文档状态

只能在频道提交到 NotificationManager#createNotificationChannel(NotificationChannel)

太糟糕了,notificationBuilder.setSound(defaultSoundUri)不能正常工作:

此方法已在API级别26中弃用。请改用NotificationChannel#setSound(Uri,AudioAttributes)。

另外,使用支持库也不起作用。因此,声音只能在应用程序中设置一次,并且用户只能在通知设置中进行更改。对我来说,费兰·内格雷的评论没有用。我不明白为什么Google设置了此限制。太糟糕了。


2
NotificationManager.IMPORTANCE_LOW

创建通知时它不会产生声音,因为我的音乐应用程序中也需要同样的声音。

是的,如果您已经创建了一个通知频道,则您需要更改频道ID或直接卸载以前的应用程序并重新安装。


2

对我来说,解决方案是创建组通知

val builder = NotificationCompat.Builder(this)
        .setGroupAlertBehavior(GROUP_ALERT_SUMMARY)
        .setGroup("My Group")
        .setGroupSummary(false)
        .setDefaults(DEFAULT_ALL)
        .setSound(null)

但是在这种情况下,如果您发送带有新ID的新通知,则它将与以前的通知分组在一起。


1
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上播放,所以不要担心setound或setvibrate

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())

1

我已经测试了很多android设备,以下代码对我来说正常工作

首先,创建一个notificationBuilder,如果您的Build.Version大于26,请添加一个新频道。

  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,并将声音设置为null

   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
        }

希望对您有用。


0

如果情况像我的一样,那我将不得不显示后台服务通知,而我真的不想显示任何通知,适用于8.0的解决方案是:

.setPriority(NotificationManager.IMPORTANCE_NONE)

这样做不仅使我每隔5分钟都没有听到烦人的声音,而且使通知本身的外观最小化。

在8.1上,我没有以下声音问题:

.setPriority(NotificationManager.IMPORTANCE_MIN)

我认为OP仍想显示通知。隐藏通知只是为了消除声音,听起来不像是正确的答案。
tir38

0

您可以使用2个不同的通知通道来发送通知,具体取决于用户的优先级。

如果它是高优先级通知,则通过

new NotificationChannel("Channel ID", "Channel Name", NotificationManager.IMPORTANCE_HIGH);

您的用户收到通知时会听到声音并弹出。

如果您要发送不太重要的通知,请使用此频道。

new NotificationChannel("Channel ID", "Channel Name", NotificationManager.IMPORTANCE_LOW);

您的用户将收到没有声音的通知并弹出。

从这里检查不同的优先级-https: //developer.android.com/reference/android/app/NotificationManager



-1

无需使用 .setSound(null, null)

只需使用下面的代码

NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this,
                getString(R.string.notification_channel_id))
                .setContentTitle("Audio Recording")
                .setContentText("recording in progress")
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
                .setSmallIcon(R.mipmap.ic_launcher);

NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    getString(R.string.notification_channel_id), "AOD+", NotificationManager.IMPORTANCE_LOW
            );
            channel.setDescription("Call Recorder is running");
            channel.setShowBadge(true);
            channel.canShowBadge();
            channel.setLightColor(Color.GREEN);
            channel.enableVibration(false);

            assert notificationManager != null;
            notificationManager.createNotificationChannel(channel);
        }

        assert notificationManager != null;
        startForeground(256/* must be greater than 0*/, notificationBuilder.build()); //I am using this for audio recording
        //notificationManager.notify(0, notificationBuilder.build());

-2

首先你需要设置

importance = NotificationManager.IMPORTANCE_LOW;

然后

Notification n = builder.setPriority(Notification.DEFAULT_ALL).build();
n.defaults = 0;
n.defaults |= Notification.DEFAULT_VIBRATE;

您能解释一下最后一段代码的作用吗?这DEFAULT_VIBRATE有什么关系?
tir38

-2
NotificationManager.IMPORTANCE_LOW

这将起作用,但也会折叠您的通知。


如果是这样,这是一个值得注意的副作用。我无法确认,因为我使用自定义通知,并且它们不会折叠。您正在哪个操作系统版本上进行操作?我在NotificationManager.IMPORTANCE_MIN
Daniel F

如果您传递2条大小不一的BTW通知,自定义通知也会崩溃,因为我正在使用8.1 API设备。
尼基(Nicky)

1
这个答案增加了@DanielF和Akash的答案尚未包含的内容吗?
tir38

-2

NotificationManager.IMPORTANCE_LOW 肯定会工作


4
这似乎只是对许多现有答案的重复/确认。

-2

我在8.1中遇到了相同的问题,并进行了以下更改。将通知的优先级更改为“低”,它将禁用通知声音。

NotificationManager.IMPORTANCE_LOW

代码如下:

NotificationChannel chan1 = new NotificationChannel("default", "default", NotificationManager.IMPORTANCE_LOW);

2
是的,这就是公认的答案以及6月27日和5月16日的答案,后两者的代码格式也更好。
丹尼尔·F
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.