禁用通知震动功能

40

我正在编写一个使用通知的应用程序。谷歌开发者指南鼓励开发者提供设置以自定义通知(关闭震动,设置通知音...)。因此,如果用户将其设置为该方式,我正在尝试为通知禁用震动。

我正在使用 NotificationCompat.Builder 创建通知,代码如下:

NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(Application.getContext())
            .setDefaults(Notification.DEFAULT_ALL)
            .setPriority(Notification.PRIORITY_MAX)
            .setSmallIcon(R.drawable.ic_launcher)
            .setLargeIcon(largeIconBitmap)
            .setAutoCancel(true)
            .setContentIntent(resultPendingIntent)
            .setContentTitle(title)
            .setContentText(content);

我尝试了不同的方法来禁用通知:

notificationBuilder.setVibrate(null);

notificationBuilder.setVibrate(new long[]{0l, 0l});

notificationBuilder.setDefaults(Notification.DEFAULT_ALL | ~Notification.DEFAULT_VIBRATE);

notificationBuilder.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND);`

我也尝试构建通知并更改生成对象上的值:

Notification notification = notificationBuilder.build();
notification.vibrate = null;

但是当通知出现时,手机仍会震动。

我如何禁用通知的震动?

11个回答

68

在长时间的试错过程中,我终于明白了问题所在。

问题出在这个指令上:notificationBuilder.setDefaults(Notification.DEFAULT_ALL)

无论你在设置了DEFAULT_ALL或者DEFAULT_VIBRATE后传递给notificationBuilder.setVibrate()的参数是什么,都会被静默丢弃。谷歌的某位开发人员决定将setDefaults的优先级高于setVibrate

这就是我最终禁用我的应用程序通知震动的方式:

notificationBuilder.setDefaults(Notification.DEFAULT_LIGHT | Notification.DEFAULT_SOUND)
                   .setVibrate(new long[]{0L}); // Passing null here silently fails

这样做是有效的,但初始化一个新的long[]来禁用振动感觉不太对。


2
我完全理解将一个变量传递给设备,以便让它在0毫秒内振动的粗糙之处,但这仍然不是我见过的最糟糕的修复方法。至少当你考虑它在做什么时,它是有道理的。 - Gabriel
1
我只是想做同样的事情,这里还有几个要点。通知渠道的优先级为3或更高,将导致震动发生,无论您的震动设置如何。此外,似乎Android正在缓存通知渠道。如果使用NotificationManager.getNotificationChannel(id),您将获取上一个实例的设置。 - Jesse
1
@Jesse 谢谢!你说得对,是缓存的问题。我之前用了 setVibrate(null) 没有效果,但当我改变了我的频道 ID 后它就起作用了。 - Undefined
3
这在我的设备上不起作用!我仍然能感觉到震动。 - Steve Moretz
我不会说通知渠道被缓存了,但是第一次应用程序安装时使用的设置被记住了。为什么?想象一下,用户自定义了通知渠道设置。然后,具有新通道设置的应用程序更新不应覆盖这些设置。这意味着,如果您更改了通道ID(或仅在测试时卸载应用程序),则只能在应用程序更新中更改这些设置。结果:用户的自定义设置将针对旧通道进行记忆,但您已为通知分配了一个新通道。当然,不要经常这样做以避免让用户感到恼怒! - P Kuijpers

8

在2020年:

将通知渠道的重要性设置为NotificationManager.IMPORTANCE_NONE对我有效。


2
这根本不起作用!它只是从状态栏中删除所有通知(-1)。 - Zhar
1
将通知渠道的重要性设置为NotificationManager.IMPORTANCE_LOW对我起作用了。 - Sandaru

4

您可以通过通知渠道有两种解决方案。

  1. 设置“虚假”模式以禁用振动。
  2. 设置重要性标志,但不够灵活(请参见https://developer.android.com/training/notify-user/channels#importance)。请注意,它还会影响其他一些内容,例如优先级...

因此,您可以使用:

NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
            // no vibration
            channel.setVibrationPattern(new long[]{ 0 });
            channel.enableVibration(true);

或者

 int importance = NotificationManager.IMPORTANCE_LOW;
            NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
        

3

它们没有停止,因为您使用了"setDefaults(Notification.DEFAULT_ALL)",如果您需要停止振动和声音,请删除此行代码,或者如果您需要使用默认声音并停止振动,则可以考虑使用setDefaults(Notification.DEFAULT_SOUND)等...


1

之前的解决方案都没有起作用,但是在我的通知构建器中添加 mBuilder.setOnlyAlertOnce(true); 解决了我的问题。

 if (mBuilder == null) {
            String channelId = "channel-id";
            String channelName = "Channel Name";
            int importance = NotificationManager.IMPORTANCE_MAX;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                NotificationChannel mChannel = new NotificationChannel(
                        channelId, channelName, importance);

                mChannel.setSound(null, null);
                mChannel.enableVibration(false);

                notificationManager.createNotificationChannel(mChannel);
            }
            mBuilder = new NotificationCompat.Builder(Application.context, channelId);
            mBuilder.setSmallIcon(R.drawable.ic_ulakbel)
                    .setContentTitle("YOURTITLE")
                    .setAutoCancel(true)
                    .setColor(ContextCompat.getColor(Application.context, R.color.green))
                    .setColorized(true);
            mBuilder.setChannelId(channelId);
            mBuilder.setPriority(1);
            mBuilder.setCustomContentView(notificationLayout);
            mBuilder.setCustomBigContentView(notificationLayout);
            mBuilder.setOnlyAlertOnce(true);
            notificationManager.notify(1452, mBuilder.build());
        }else{
            Notification notification = mBuilder.build();
            notification.flags = Notification.FLAG_ONGOING_EVENT;
            notificationManager.notify(1452,notification);
        }

1

.setVibrate(null)对我很有效 - 而且比创建一个不必要的长数组更好的解决方案。

结果:设备不会振动,LogCat中也没有抱怨。 :)


我同意,你的解决方案比我的更优雅。不幸的是,在三星Galaxy Note上测试时对我不起作用。 - nstCactus
是否抛出了异常并/或设备震动? - ban-geoengineering
据我所记,它振动了,但没有抛出任何异常或警告。 - nstCactus
这似乎有点奇怪,因为我已经查看了 Notification 的源代码 - http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/app/Notification.java#Notification - 并且 null 震动似乎被正确处理了。当你输出 notification.toString() 时得到什么?(你确定没有应用默认值吗?) - ban-geoengineering
坦白地说,我现在没有时间对这个问题进行更多的测试。当我再次开始处理该项目时,我会尝试您的解决方案,但这不会很快,抱歉。 - nstCactus
1
OP明确表示在原帖中这个解决方案已经测试过但不起作用。我也在测试,它也不行。 - Kyle Sweet

1
notification.vibrate = new long[] { -1 };

这段代码对我有效。

为什么?你能解释一下吗? - pppery

0
private void removeSoundAndVibration(Notification notification) {
        notification.sound = null;
        notification.vibrate = null;
        notification.defaults &= ~DEFAULT_SOUND;
        notification.defaults &= ~DEFAULT_VIBRATE;

这段代码来自 Notification Compat Api Class。这应该可以工作,将所有这些内容添加到您的构建器中。


0
   private void createNotificationChannel() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel serviceChannel = new NotificationChannel(
                CHANNEL_ID,
                "Example Service Channel",
                NotificationManager.IMPORTANCE_MIN
        );
        serviceChannel.setVibrationPattern(new long[]{ 0 });
        serviceChannel.enableVibration(true);
        serviceChannel.enableLights(false);
        serviceChannel.setSound(null, null);
        serviceChannel.setShowBadge(false); // 
        NotificationManager manager = getSystemService(NotificationManager.class);
        manager.createNotificationChannel(serviceChannel);
    }

如果你将IMPORTANCE_MIN设为禁用震动,而将IMPORTANCE_DEFAULT设为启用震动,那么你可以尝试使用IMPORTANCE_MIN。


目前你的回答不够清晰,请编辑并添加更多细节以帮助他人理解如何回答问题。你可以在帮助中心找到更多关于如何撰写好回答的信息。 - Community

0

2022年7月:我尝试了这个帖子中的所有方法,唯一有效的是Zhar建议将重要性设置为低:

int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);

我正在针对Android API 24级进行开发。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接