60

When I read Apple Docs, they mention 3 types of notification: local, remote, and silent.

Local notification can be inferred from its name, that is sent by the app locally.

However, what is the difference between the other two types?

4

3 回答 3

209

编辑:虽然这个答案完全适用,但 iOS 12 中的通知有一些添加(而不是更改)。我强烈建议观看WWDC 2018:用户通知中的新功能并阅读这篇令人惊叹的必读文章

主要变化是:

  • 分组通知以及摘要格式
  • 临时通知,即未经用户许可直接在通知中心显示通知
  • 忽略“请勿打扰”或“静音”的重要通知
  • 与扩展中的通知进行交互的能力
  • 完全重置或更新操作的能力
  • 能够从手机的通知中心深度链接到应用程序的通知设置

重要提示:不确定从何时开始,但来自 Apple 文档,“静默通知”已重命名为“后台通知”

有太多设置需要正确设置才能正常工作。我将尝试剖析它们并使它们更易于理解。

总的来说,有几件事很重要。

  • 静默通知和用户通知之间的总体区别
  • 不同类型的用户通知
  • 如何从您的服务器配置远程通知,即有效负载
  • 如何在项目的后台模式下启用推送通知和远程通知
  • 如何使用 APNs 注册您的令牌以获取远程静默通知以及 APNs 架构
  • 如何请求用户通知的权限
  • 从设备启用“后台应用刷新”和“通知”
  • 什么是content-available
  • 了解在接收远程通知时 iOS 在您的应用程序的上游
  • 当应用程序已被用户终止时操作系统收到通知时会发生什么
  • 关于可靠性和 APNs 架构的说明

我强烈推荐大家观看前 7 分钟的内容:WWDC 2015: What's new in Notifications。从那里,演示者提到有两种主要类型的通知:

静默通知

它们发生在后台,因此您永远不会看到任何警报/徽章/声音。东西在你不知道的情况下被下载。

iOS 11 错误

这里。iOS 11 初始版本存在静默通知问题。确保您有最新版本进行测试,否则可能无法正常工作


用户通知

在此处输入图像描述

顾名思义,它与用户有关。也就是说,用户将看到警报/标记或听到声音。它有 2 种类型。

本地通知

可以通过3 种不同的方式触发本地通知:

  • UNLocationNotificationTrigger:当您靠近沃尔玛商店时,您会看到警报。

  • UNTimeIntervalNotificationTrigger:例如,您每 10 分钟就会看到一次警报。

  • UNCalendarNotificationTrigger比如 2017 年 12 月 1 日下午 1:00。

远程通知

它们类似于本地通知,但它们是从服务器触发的,例如具有 From 字段(妈妈)和正文字段(我爱你!)的 WhatsApp 消息。

令牌注册和 APNs 架构:

要接收静默或远程通知,您需要使用以下方式注册令牌:

application.registerForRemoteNotifications() 

注册不需要用户许可。这使得无声通知变得无缝。观看WWDC 视频的这一刻

默认情况下启用无提示通知。用户不需要批准您的 -- 不会授予您的应用使用它们的权限,您可以直接开始使用它们而无需征求用户的许可。

来自 WWDC

请记住,APN 是通过 APN 而不是您的服务器交付给您的用户的。因此,您的 iOS 代码必须将此令牌发送到您的服务器。因此服务器可以将给定的设备令牌与用户相关联。当您想要推送给某个用户时,您的服务器只是告诉 APNs 将有效负载发送到特定令牌。重要的是要了解您的服务器和 APN 是两个不同的东西

它的流程如下所示:

 

在此处输入图像描述

 

  1. 服务器/提供商向 APNs 发送有效负载
  2. APN 向给定帐户的所有目标设备发送通知。例如,您的 iPhone、Mac 都可以接收电子邮件/消息通知。
  3. 然后你的 iPhone/Mac 会将该消息传递给应用程序。APN 不会直接向您的应用发送消息。它将它发送到设备。然后 iOS 将其发送到您的应用程序。

有关这方面的更多信息,请参阅文档APNs 概述向 APNs 发送通知请求


为了能够显示徽章/警报/声音,您需要向用户请求许可

UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
    
    guard error == nil else {
        //Display Error.. Handle Error.. etc..
        return
    }
    
    if granted {
        //Do stuff here..
        
        //Register for RemoteNotifications. Your Remote Notifications can display alerts now :)
        application.registerForRemoteNotifications()
    }
    else {
        //Handle user denying permissions..
    }
}

问题:我是否需要为本地通知和远程通知请求一次访问权限?

不。只需编写上面的代码片段,它就会请求远程和本地的访问权限。

现在让我们进入棘手的部分:D


Xcode 项目 + iPhone 设置

我需要启用某些东西来接收静默通知吗?

  1. 您必须从 Xcode 功能启用推送通知:

在此处输入图像描述

如果您不启用此功能,您的应用将不会收到令牌。如果没有令牌,服务器将无法识别您。

  1. 为了能够从后台下载东西,您需要启用:来自后台模式的远程通知。

要启用backgroundModes,您可以使用plistXcode功能来实现。

无论哪种方式,您都可以这样做的原因是因为 plist 更接近您的代码并且是旧方式,也许它是为了遗留支持。Xcode 功能是更新、简单的方法。

列表:

在此处输入图像描述

Item 0 只是一个index,它不是字典的键(你通常在 plist 中看到的东西), UIBackgroundModes 是一个array字符串。字符串只能来自UIBackgroundModes Array中可接受的值

Xcode 功能:

Remote Notification在后台模式下检查Xcode如下:

在此处输入图像描述

如果您不执行上述任何操作,则使用以下方法关闭通知:

在此处输入图像描述

将杀死远程和本地通知


但是,如果您确实从 plist 或 Xcode 功能启用后台应用程序刷新,那么即使关闭了应用程序的通知,您仍然会收到静默通知!

如果用户想要禁用静默通知,他将不得不禁用这两个通知并禁用“您的应用程序/整个系统的后台应用程序刷新”。要在您的系统中禁用“后台应用刷新”,您必须执行以下操作:

在此处输入图像描述

为什么我要说这一切?向您说明,静默和推送通知的设置因用户而异,发送的限制也不同。有关更多信息,请参阅WWDC 视频中的这一刻。请参阅此处(之前的链接已失效):

默认情况下启用静默通知。

用户不需要批准你不授予你的应用程序使用它们的权限,你可以直接开始使用它们而无需征求用户的许可。

但静默通知是后台应用刷新背后的机制。

在任何时候,您都知道用户可以进入设置并禁用它们。

所以你不能依赖它们总是可用的。

您不知道用户是否将其关闭,并且您不再收到通知。

这也意味着会尽最大努力传递无声通知。

这意味着当通知到达用户的设备时,系统将做出一些选择。

它将使用来自设备和用户行为的不同信号,例如电源或一天中的时间来决定何时是发送通知和启动应用程序的好时机。

它可能会尝试节省电池电量,也可能会尝试匹配用户行为并在用户更有可能使用内容时提供内容。

也见这里

警告:即使您禁用应用程序后台刷新并禁用允许通知,如果您的应用程序处于前台,您仍然可以收到静默通知。如果您的应用程序在后台,则不会交付。


我需要启用某些东西来接收远程通知吗?

您只需要从 Xcode 功能中启用推送通知:

在此处输入图像描述

如果您不启用此功能,您的应用将不会收到令牌。如果没有令牌,服务器将无法识别您。


APNs 有效负载结构

好奇...你能告诉我我的有效载荷应该是什么样子吗?

我强烈建议您查看 Apple § 文档。非常清楚,另请参阅Sending Notification Requests to APNs。基本上平台对 APN 进行 HTTP/2 调用并发送所需的有效负载。发送正确的标头至关重要,否则您的通知不会发送到设备!

谢谢,但你能告诉我重要的部分吗?

嗯……好的,但是你知道这是来自我刚才说的链接:

对于静默通知,只有一个标准:

  • 有效负载的aps字典必须包含content-available值为 的键1
  • 根据文档,您可以发送其他字段

如果有用户可见的更新伴随着后台更新,您可以根据需要在 aps 字典中设置警报、声音或标记键。

示例有效载荷如下所示:

{
    "aps" : {
        "content-available" : 1
    },
    "acme1" : "bar",
    "acme2" : 42
}

acme1、acme2,或者只是一些自定义数据!但是对于aps密钥,你必须遵循苹果的结构,否则,它不会正确映射,你将无法正确读取数据。

注意:我尚未对此进行验证,但另一位工程师提到,如果您启用了临时通知,那么为确保发送静默通知,您必须包含一个带有空正文的警报​​字段。例如:

{
    "aps" : {
        "content-available" : 1,
        "alert" : {
          "body" : "",
        },
    },
}

对于用户通知

您需要alertaps.

举个例子:

{
    "aps" : {
        "alert" : "You got your emails.",
        "badge" : 9,
        "sound" : "bingbong.aiff"
    },
    "acme1" : "bar",
    "acme2" : 42
}

还有第三种选择,我将在答案后面进一步讨论。

至于固定键apsalert字典键是什么,请参阅这些Apple 文档

好的,我知道了。是什么content-available

很简单。它只是一个标志,告诉您的应用您需要唤醒并下载一些内容,因为我有内容可供下载!欲了解更多信息,请参阅这个确切的时刻

默认情况下content-available不包含该标志,即默认情况下,您发送的通知不会触发application(_:didReceiveRemoteNotification:fetchCompletionHandler:)或在您的应用程序中执行某些操作。它只会显示通知。如果您想唤醒应用程序(在后台执行某些操作),您需要将其包含content-available并设置为1.

§: 如果您使用Firebase,您的有效负载结构和键可能会略有不同。例如,密钥content-available被替换为content_available。有关更多信息,请参阅Firebase 文档此处


我知道您告诉我,我只能在使用静默通知时将某些内容下载到我的应用程序中,但是有没有一种方法可以在后台唤醒我的应用程序并下载远程通知的内容?

是的,但是类似于静默通知,您还必须将content-available标志设置为 1,这样它就会知道唤醒并下载一些东西。否则,它只会弹出并发出警报/徽章/声音,但不会下载任何内容。

重要笔记:

  • 如果您的应用只有静默通知,只需从功能中启用“推送通知”+“远程通知”并为每个有效负载设置content-available为。1
  • 如果您的应用只有远程通知,只需从功能中启用“推送通知”。没有什么可做的content-available
  • 但是,如果您希望通知显示警报/徽章/声音并在后台下载某些内容,则必须同时启用“远程通知”和“推送通知”+ 设置content-available1.

(第三个选项)

{
    "aps" : {
        "content-available" : 1 
        "alert" : "You got your emails.",
        "badge" : 9,
        "sound" : "bingbong.aiff"
    },
        "acme1" : "bar",
        "acme2" : 42
}

WWDC 视频中的这一刻提到了

引用 Apple 工程师的话:

现在,您可以在用户远程通知中设置与在静默通知中设置的相同 内容可用标志,这允许您的应用有时间下载内容或更新它想要显示的内容,以便当用户点击通知时,您的内容可用。用户可以看到它做了什么。这是一种在用户通知(如摘要)中进行静默通知的方法。


通知和 iOS 应用程序生命周期

我对远程通知感到困惑。我想每当我收到通知时,我的应用程序就会在后台激活并下载一些东西。你可以解释吗?

例如此时:

在此处输入图像描述

  • 您的 iPhone 刚刚收到一条远程通知,其正文为“无发件人”。要接收此信息,WhatsApp ** 不必** 必须在后台运行,即,您不需要从 BackgroundModes 启用“远程通知”。即使您的应用程序被强制退出或暂停,您仍然会收到通知,因为该过程由操作系统管理,而不是 WhatsApp 应用程序。但是,如果您希望能够将实际消息或其图像/视频下载到 WhatsApp(这样一旦您的用户打开 WhatsApp,视频就会坐在那里等待用户),那么您需要激活您的应用程序. 为此,您需要content-available : 1并实施application(_:didReceiveRemoteNotification:fetchCompletionHandler:) .

  • 同样,如果您禁用某个应用的蜂窝数据,您仍会收到其通知。但是,通过点击该通知,用户将无法对该应用程序发出任何网络请求。他们只能打开应用程序。

  • 或者对于另一个类似的情况,如果您连接的服务器/接入点对 WhatsApp 等具有限制访问权限,它仍然允许您接收 APNs 通知。但是,通过点击该通知,用户将无法对该应用程序发出任何网络请求。他们只能打开应用程序。

警告:如果应用程序被用户强制退出,那么当您因为上述原因收到通知时,您不能做任何事情来使应用程序自动退出其终止状态(即使您已content-available设置为1)。您的任何委托方法都不会受到影响。用户必须打开应用程序,然后才能访问您的委托方法。


关于可靠性和 APNs 架构的说明:

尽管通知被大量用于向应用程序传递实际内容,但它们在某种程度上并不是为了向应用程序传递内容而设计的。相反,它们旨在通知用户“嘿,有新东西到了(2b 消息或 50kb 小图像,或 10MB 图像或 2 GB 视频)。如果你愿意,请打开应用程序。顺便说一下,这里有一个它的一小部分(实际消息本身,如果它可以容纳,图像的标题或通知中显示的缩略图,视频的标题或视频中显示的缩略图”。有关更多信息,请参阅iOS APNs “best-努力”的后备. 再说一遍,您永远不会下载电子邮件中发送的 40MB 附件。您只会收到有关其存在的通知。您只需发送足够的内容(附件的缩略图视图),以便用户了解新内容并决定是否需要打开应用程序以获取更多信息。当我刚接触 iOS 时,我以为您实际上是通过推送通知发送图像/视频。你没有!

特别是在静默通知的情况下:

当设备收到后台通知时,系统可能会暂停和延迟通知的传递,这可能会产生以下副作用:

  • 当系统收到新的后台通知时,它会丢弃旧的通知,只保留最新的通知。

  • 如果某些东西强制退出或终止应用程序,系统会丢弃保留的通知。

  • 如果用户启动应用程序,系统会立即下发所持有的通知。 将后台更新推送到您的应用文档

  • APNs 每天发送有限数量的静默通知(带有内容可用密钥的通知)。此外,如果设备已经超过了当天的功率预算,则在功率预算重置之前不会再次发送静默通知,这种情况每天发生一次。从 Xcode 测试您的应用程序时,这些限制被禁用。请参阅将后台更新推送到您的应用程序。

处理从 ANP 返回的错误的故障排除提示

即使对于远程用户通知,用户也可能不在互联网上,这可能会导致内容过期,或者如果您发送的通知过多或过快,APN 可能会限制您。再看这里

长话短说,APN 和操作系统为王,而您则处于劣势。因此,您不能依赖它来遵守您的每个命令。话虽如此,从您看到大多数消息传递应用程序成功利用它的意义上来说,它是超级可靠的。

附录如何生成推送通知证书,.p12或者.pem如何测试它?

只要看到这个了不起的答案。它拥有我见过的最多的屏幕截图。

于 2017-02-17T16:06:24.157 回答
7

推送通知将让用户知道他们收到了通知(例如显示通知弹出窗口)。静默通知将更新,但用户不会收到有关它的通知。在任何情况下,您都可以在无提示通知时执行操作,就像它是推送通知一样。唯一的区别是用户不会收到弹出通知的通知。

使用推送通知: 在此处输入图像描述

无声通知: 在此处输入图像描述

不同之处在于有效负载:

推送通知:

     aps {
       content-available: 1
       alert: {...}
     }

静默通知:

    aps {
      content-available: 0
      alert: {...}
    }

您必须在Capabilities中设置您选择的背景模式。

于 2017-02-16T13:19:13.383 回答
1

静默推送通知到达设备,用户对通知一无所知,但他的应用程序收到通知,应用程序将有时间下载新内容并将其呈现给用户,无论应用程序的状态如何(即运行与否)跑步)

远程推送通知方法仅在您的应用程序运行时调用。如果应用程序被挂起或未运行,则系统会在调用该方法之前唤醒或启动您的应用程序并将其置于后台运行状态。此方法旨在向用户显示更新的内容。调用此方法时,您的应用程序有最多 30 秒的挂钟时间来执行下载操作并调用指定的完成处理程序块。如果没有及时调用处理程序,您的应用程序将被暂停。

有关更多技术细节,您可以浏览以下链接:

苹果通知

静默通知

于 2017-02-16T13:33:35.597 回答