Android应用程序 - 检测应用程序推送通知是否关闭

39
在我们的Android应用程序(使用SDK23编译)中,“推送通知”设置在应用程序安装后默认为“开启”。但是用户当然可以手动将其关闭。

两个问题:

从应用程序内部,使用Android API,是否可以(如何简单概括地解释?):

  1. 检查“推送通知”设置的当前状态(开启或关闭)?

  2. 与我们可以重定向用户到GPS设备设置(如果GPS处于“关闭”状态)类似,如果设置为“关闭”,我们是否也可以重定向用户到“推送通知设置”,以便用户可以自行选择是否将其重新“开启”?

令人惊讶的是(也许我们错了?因此我们在此寻求您的意见/确认),似乎以上“1”和“2”都不可能??!

如果我们错了,它确实是可能的,我们会感激一个简短的“如何概述地实现它”。

感谢您的输入!


如果你是指通知的一般情况,那么有一个新方法可以检查启用状态,它应该在最新的支持库更新中,但据我所知,它尚未发布,而我目前也无法检查。 - Mike M.
如果有帮助的话,请查看这篇帖子。这里有人问了一个类似的问题。 - intellignt_idiot
4个回答

85

您可以使用以下命令检查用户是否允许您的应用程序发送通知:

NotificationManagerCompat.from(context).areNotificationsEnabled()

这个代码片段可以在API 19+的版本中使用。但是,从Android O开始,将引入通知渠道(notification channels)。这允许用户在应用设置屏幕上禁用特定的通知渠道,并禁用应用程序的所有通知。使用上述命令,您只能检查整个应用程序是否允许通知,而不能检查特定的通知渠道。也就是说,即使上面的命令返回值为true,您也无法看到任何通知。

下面的代码仅在应用程序允许所有通知并且所有现有通知渠道已启用时返回true。可以从API 19+的版本中使用,包括从Android O开始需要的更改:

Java

public boolean areNotificationsEnabled() {
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    if (!manager.areNotificationsEnabled()) {
      return false;
    }
    List<NotificationChannel> channels = manager.getNotificationChannels();
    for (NotificationChannel channel : channels) {
      if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) {
        return false;
      }
    }
    return true;
  } else {
    return NotificationManagerCompat.from(context).areNotificationsEnabled();
  }
}

Kotlin
fun areNotificationsEnabled(notificationManager: NotificationManagerCompat) = when {
    notificationManager.areNotificationsEnabled().not() -> false
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
        notificationManager.notificationChannels.firstOrNull { channel ->
            channel.importance == NotificationManager.IMPORTANCE_NONE
        } == null
    }
    else -> true
}

1
作为 Kotlin 扩展函数:fun NotificationManagerCompat.areNotificationsEnabled() = when { areNotificationsEnabled().not() -> false Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> { notificationChannels.firstOrNull { channel -> channel.importance == NotificationManager.IMPORTANCE_NONE } == null } else -> true } - Innova
不要忘记在API级别大于等于28时检查组是否已禁用。 - Victor Rendina
3
在 >=Android O 版本中,代码可以更简单:notificationManager.notificationChannels.none { it.importance == NotificationManager.IMPORTANCE_NONE } - hanswim

10

Android O开始,通知被引入,并且Android P开始,可以禁用整个组。必须考虑到这一点。请参见下面的代码片段,其中包含一个示例解决方案。

fun NotificationManagerCompat.areNotificationsFullyEnabled(): Boolean {
    if (!areNotificationsEnabled()) return false
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        for (notificationChannel in notificationChannels) {
            if (!notificationChannel.isFullyEnabled(this)) return false
        }
    }
    return true
}

@RequiresApi(Build.VERSION_CODES.O)
fun NotificationChannel.isFullyEnabled(notificationManager: NotificationManagerCompat): Boolean {
    if (importance == NotificationManager.IMPORTANCE_NONE) return false
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        if (notificationManager.getNotificationChannelGroup(group)?.isBlocked == true) return false
    }
    return true
}

你可以从一个片段(fragment)中调用它,例如:
if (!NotificationManagerCompat.from(requireContext()).areNotificationsFullyEnabled()) {
            //todo notifications DISABLED
        }

这个回答需要被置顶。 - Divesh

8

根据文档,第一种情况是可能的。我还没有研究你问题的第二部分(将用户带到通知设置)。

要检查通知的当前状态,首先必须知道您使用的设备是否低于Oreo。在Oreo以下版本中,只需在支持库的NoticificationManagerCompat对象上调用areNotificationsEnabled()即可。在Oreo或更高版本中,您需要通过调用NotificationChannel对象上的getImportance()来逐个检查通知通道。如果通知已禁用,则getImportance()将返回NotificationManager.IMPORTANCE_NONE。如果返回其他任何内容,则表示已启用通知。以下是一些可以完成工作的代码:

public boolean areNotificationsEnabled(Context context, String channelId) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        if(!TextUtils.isEmpty(channelId)) {
            NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            NotificationChannel channel = manager.getNotificationChannel(channelId);
            return channel.getImportance() != NotificationManager.IMPORTANCE_NONE;
        }
        return false;
    } else {
        return NotificationManagerCompat.from(context).areNotificationsEnabled();
    }
}

希望这有所帮助!

我会移除 !TextUtils.isEmpty(channelId) 并检查 channel != null,因为无效的频道 ID 字符串也可能导致这种情况。 - Florian Walther
即使从设置中禁用了通知,它仍然始终返回IMPORTANCE_HIGH。 - Fazal Hussain
@FlorianWalther 顺便说一下,TextUtils.isEmpty() 会检查 null 和 length==0 两种情况。 - Alex
manager.getNotificationChannel(channelId); 它返回 NULL。 - Ganesh kumar Raja

3
您可以通过此命令检查系统推送是否启用或禁用。
NotificationManagerCompat.from(context).areNotificationsEnabled()

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