APNS 严重警报被视为正常通知

APNS critical alert is treated as normal notification

我正在尝试通过 FCM 从 PHP 后端向我的 iOS 应用程序发送严重警报。问题是,通知未被视为严重警报,不会绕过 "Do Not Disturb"-模式。

从后端发送到 FCM 的负载(示例)

{
    "to": "<fcm token>",
    "data": {"property-1": "value-1"},
    "priority": "high",
    "notification": {
        "title": "Hello World!",
        "body": "Lorem Ipsum ...",
        "badge": 1
        "sound": {
            "critical": 1,
            "name": "default",
            "volume": 1.0
        },
        "color": "#ffffff"
    },"time_to_live": 300,
    "content_available": true
}

根据 Apple documentation 这种格式应该是有效的。

在设置中启用了严重警报。

到目前为止我发现的唯一可疑的事情是,保存推送通知信息的 userInfo 变量将 sound 保存为 JSON-string 而不是序列化的对象。

Printing description of userInfo:
▿ 4 elements
  ▿ 0 : 2 elements
    ▿ key : AnyHashable("gcm.message_id")
      - value : "gcm.message_id"
    - value : <message-id>
  ▿ 1 : 2 elements
    ▿ key : AnyHashable("google.c.a.e")
      - value : "google.c.a.e"
    - value : 1
  ▿ 2 : 2 elements
    ▿ key : AnyHashable("aps")
      - value : "aps"
    ▿ value : 4 elements
      ▿ 0 : 2 elements
        - key : content-available
        - value : 1
      ▿ 1 : 2 elements
        - key : alert
        ▿ value : 2 elements
          ▿ 0 : 2 elements
            - key : title
            - value : Hello World!
          ▿ 1 : 2 elements
            - key : body
            - value : Lorem Ipsum ...
      ▿ 2 : 2 elements
        - key : badge
        - value : 1
      ▿ 3 : 2 elements
        - key : sound
        - value : {"volume":1.0,"critical":1,"name":"default"}
  ▿ 3 : 2 elements
    ▿ key : AnyHashable("message")
      - value : "message"
    - value : {"data":...}

这是 iOS 或 APNS 中的错误吗?

{"volume":1.0,"critical":1,"name":"default"}

有什么想法可以让它发挥作用吗?

The only suspicious thing I´ve found so far, is that the userInfo variable holding the information of the push notification holds sound as JSON-string instead of a serialized object.

这听起来确实是您可能面临的问题。根据 Apple 文档,sound 属性 必须是严重警报 (Apple Developer – Generating a Remote Notification) 的字典:

A dictionary that contains sound information for critical alerts. For regular notifications, use the sound string instead.

我建议您使用像这样的工具 GitHub – onmyway133/PushNotifications 来测试发送推送通知以进行测试,您可以在其中将声音 属性 指定为字典,然后看看会发生什么。

也许这是 FCM 中的错误?如果测试显示推送通知按预期工作,则可能是这种情况。

严重警报

首先,关于苹果推送通知服务的一些信息。

来自 Apple 文档:criticalAlertSetting:

When UNNotificationSetting.enabled, this property authorizes the app to play critical sounds that ignore Do Not Disturb and the device’s mute switch.

For remote notifications, the system attempts to play a critical sound when the notification’s payload contains a sound directory that contains the critical key. Critical alerts require a special entitlement issued by Apple.

来自 Apple 文档:UNNotificationContent:

Don't create instances of this class directly. For remote notifications, the contents of this object are derived from the JSON payload that your server sends to the APNS server.

UNNotificationContent有几个属性:

var title: String // A short description of the reason for the alert.
var subtitle: String // A secondary description of the reason for the alert.
var body: String // The message displayed in the notification alert.
var badge: NSNumber? // The number to display as the app’s icon badge.
var sound: UNNotificationSound? // The sound to play when the notification is delivered.
var launchImageName: String // The name of the launch image to display when your app is launched in response to the notification
var userInfo: [AnyHashable : Any] // A dictionary of custom information associated with the notification.
var attachments: [UNNotificationAttachment] // An array of attachments to display with the notification.

请注意 sound 属性 和 userInfo 属性 是分开的。这意味着严重警报设置必须存储在 sound 下,而不是 userInfo.


Firebase 云消息传递 (FCM)

以前,Firebase 云消息传递 (FCM) 不支持关键警报,必须直接使用 Apple 推送通知服务 (APNS) 来完成。但是,据我所知,FCM API 现在为此设置了 sound 属性。


重要的两点:

1:您必须拥有来自 Apple 的 critical alerts entitlement 才能正常工作。你必须证明为什么你的应用程序应该被允许绕过用户偏好来提供通知,即使在“请勿打扰”打开的情况下也是如此。然后,您必须在 Xcode.

中使用此更新您的配置文件

2:在请求通知权限时,您还必须专门针对严重警报请求权限:

var authOptions: UNAuthorizationOptions?
if #available(iOS 12.0, *) {
    authOptions = [.alert, .badge, .sound, **.criticalAlert**]
} else {
    authOptions = [.alert, .badge, .sound]
}
UNUserNotificationCenter.current().requestAuthorization(options:   
  authOptions!) { (granted, error) in
    // Handle outcome here
}

然后系统将提示用户明确允许关键通知。


总而言之,使用较新版本的 FCM 应该可以做到这一点,但如果实施了上述步骤,使用本机 APNS 肯定可以。

您可能还想查看 this answer 以了解使用通知扩展程序在收到警报时将其设为关键的方法。 mutable-content 键必须设置为 true,以便调用通知扩展。