iOS10 未调用 UNNotificationServiceExtension

iOS10 UNNotificationServiceExtension not called

我正在实施新的 iOS10 扩展以使用丰富的通知。我正在尝试在推送通知上对其进行测试,但没有用,我只是收到一个简单的通知,并没有通过扩展。

我做了官方网站和其他一些地方指定的所有内容:

正如我所说,我收到了通知,但从未经历过延期。我看到 OS 如何尝试加载扩展,但随后抛出一个没有相关描述的错误来识别问题:

Dec 31 21:00:00 iPhone SpringBoard(libextension.dylib)[51] <Notice>: calling plugIn beginUsing:   
Dec 31 21:00:57 iPhone pkd[86] <Notice>: assigning plug-in com.test.app.NotificationWithAttachmentExtension(1.0) to plugin sandbox   
Dec 31 21:03:57 iPhone pkd[86] <Notice>: enabling pid=51 for plug-in com.test.app.NotificationWithAttachmentExtension(1.0) 38BB5FF1-2597-42E0-B950-169DBFA80573 /private/var/containers/Bundle/Application/A8C47706-C0EC-4FB1-ABA7-0118372F6900/testapp.app/PlugIns/NotificationWithAttachmentExtension.appex   
Dec 31 21:00:53 iPhone SpringBoard(PlugInKit)[51] <Notice>: plugin com.test.app.NotificationWithAttachmentExtension interrupted   
Dec 31 21:03:56 iPhone SpringBoard(PlugInKit)[51] <Notice>: Hub connection error Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.test.app.NotificationWithAttachmentExtension" UserInfo={NSDebugDescription=connection to service named com.test.app.NotificationWithAttachmentExtension}   
Jun 29 13:33:36 iPhone SpringBoard(libextension.dylib)[51] <Notice>: PlugInKit error in beginUsing:   
Jun 17 23:33:04 iPhone SpringBoard(libextension.dylib)[51] <Notice>: killing invalid plugIn   
Dec 31 21:00:00 iPhone SpringBoard(UserNotificationsServer)[51] <Error>: Extension error whilst trying to modify push notification F502-9B36: Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.test.app.NotificationWithAttachmentExtension" UserInfo={NSDebugDescription=connection to service named com.test.app.NotificationWithAttachmentExtension}   
Dec 31 21:00:00 iPhone SpringBoard(UserNotificationsServer)[51] <Notice>: [com.test.app] Saving notification F502-9B36   
Dec 31 21:00:00 iPhone SpringBoard(libextension.dylib)[51] <Notice>: completed calling plugIn beginUsing: for pid: 0  

相关扩展.plist:

  <dict>
    <key>NSExtensionAttributes</key>
    <dict>
      <key>UNNotificationExtensionCategory</key>
      <string>attachmentCategory</string>
      <key>UNNotificationExtensionInitialContentSizeRatio</key>
      <real>1</real>
    </dict>
        <key>NSExtensionPointIdentifier</key>
        <string>com.apple.usernotifications.service</string>
        <key>NSExtensionPrincipalClass</key>
        <string>$(PRODUCT_MODULE_NAME).NotificationService</string>
  </dict>

有什么问题或缺失?

UNNotificationServiceExtension 中的 public func didReceiveNotificationRequest(request: UNNotificationRequest, withContentHandler contentHandler: (UNNotificationContent) -> Void) 方法在 swift 版本之间发生了变化。

一些在线示例不是最新的。

确保您在 UNNotificationServiceExtension

的自定义子类中覆盖的方法

我有:

func didReceive(request: UNNotificationRequest, withContentHandler contentHandler:(UNNotificationContent) -> Void)

直到我更改为:

才起作用

func didReceiveNotificationRequest(request: UNNotificationRequest, withContentHandler contentHandler: (UNNotificationContent) -> Void)

您的 plist 似乎混合了 2 个 plist。 有 2 个扩展正在运行:

  1. 通知内容扩展 - 负责通过视图控制器显示内容
  2. 通知服务扩展 - 负责在显示通知之前在后台获取内容

这是 Notification Content Extension 目标的 plist:

这是 Notification Service Extension 目标的 plist:

我终于让这个工作正常了,这是我从这个问题中记住的。

1) 不要使用带有 iOS10 测试版的设备,因为我遇到的问题之一是因为我使用的是测试版。

2) 只有应用程序需要 APNS 授权,这对于用于扩展程序的监禁来说不是必需的。

3) 我使用的配置文件与扩展程序的 ID 相匹配(不是通配符),无论如何我无法确认它是否适用于通配符。

4) NSExtensionAttributes 不是必需的,只需为扩展 .plist 使用 NSExtensionPointIdentifier 和 NSExtensionPrincipalClass。除非你使用自己的布局

5) 即使使用 iOS 9 种令牌注册方法也能正常工作。

6) 不要忘记推送通知中有效负载中的可变内容值,这是通过扩展所需的服务器唯一强制值。

我认为这涵盖了我遇到的所有问题

检查扩展的部署目标也可能起到作用。我的设置为 10.2,而我正在测试的设备(仍在)使用 10.1

将部署目标更改为 10.0 后,UNNotificationServiceExtension 实例被完美调用

如果您已正确完成所有操作,请不要忘记将其附加到流程中。

在 运行 包含扩展程序的应用之后:

  1. 在扩展程序中设置断点
  2. Select 通过 PID 或名称调试/附加到进程
  3. 输入扩展目标的名称
  4. 触发推送通知

确保您已设置 'None' 配置。看截图。使用其他参数 didReceive 不起作用。

Configuration

在尝试了许多已经给出的可能的修复但没有成功之后,我突然意识到一个框架被错误地添加到我们的扩展目标而不是单元测试目标。

删除框架并以 10.2 为目标允许我的扩展程序再次被调用。

如果您出于某种原因对哪个框架感到好奇,可以在这里找到它:https://github.com/plu/JPSimulatorHacks

第二次来了。第一次, 帮助了我,第二次,没有。经过大量(内部)发誓后,我发现我不知何故不小心从我的主要应用程序目标中的嵌入式二进制文件中删除了扩展。当我加回分机时,我的分机又会被调用。

所以检查一下:

  1. 点击左侧的应用项目。
  2. 点击您的主要应用目标。
  3. 选择常规。
  4. 在嵌入式二进制文件下,​​确保您的扩展已列出,如果没有,请添加它。

我的问题有两个。第一个可能是我将 Info.plist 属性 NSExtensionPrincipalClass 设置为 bundle.identifier.NotificationService 而不是 ProductModuleName.NotificationService。模块名称是默认的,但我在调试一些与不同方案和不同目标相关的其他东西时错误地更改为标识符。

第二个问题是我通过 运行 通知服务目标进行了测试。对我来说,当 运行 应用程序目标时效果更好。我看到其他一些人建议使用通知服务目标来启用调试。但是当 运行 应用程序目标也是如此时,这工作正常。不过,您必须手动将调试器附加到您的通知服务。

我发现上面的方法是用最少的代码创建一个新的测试项目。事后看来,我绝对推荐这种方法,而不是尝试在 Whosebug 等

上找到的所有不同解决方案

如果您使用的是 Firebase,请尝试将负载更改为:

{
   “aps” : {
      “category” : “SECRET”,
      “<strong>mutable_content</strong>” : true,
      “alert” : {
         “title” : “Secret Message!”,
         “body”  : “(Encrypted)”
     },
   },
   “ENCRYPTED_DATA” : “Salted__·öîQÊ$UDì_¶Ù∞è   Ω^¬%gq∞NÿÒQùw”
}</pre>

mutable_content 字段映射到 APNs 上的可变内容字段。 有关详细信息,请阅读此 link.

有同样的问题,为我解决的是从嵌入式二进制文件中删除扩展并重新添加它。

Swift 5个简单方法

 this is very easy way just do it like this

在我的例子中,我忘记了 select Scheme 中的 NotificationServiceExtension 作为特定应用程序,而不是 "my application" 我尝试使用它的地方。所以我一直 运行 "my app" 并等待另一个应用程序 (NotificationServiceExtension) 代码中的断点,这就是它们从未出现的原因。在那之前我尝试了所有建议。

另一种可能性是检查 UNNotificationContentExtension 的 plist 文件中的类别名称。

plist 中 "UNNotificationExtensionCategory" 的字符串值和 payload 的 "category/click_action" 应该相同。

对于任何想在应用的通知扩展中触发断点的人来说,这个过程在 Xcode 11.3 中非常简单:

  1. Select 扩展方案(不是父应用方案)。
  2. Select Edit Scheme.
  3. Select 可执行文件成为您的父应用程序。
  4. 取消选中 Debug executable。通过取消选中此项,您通知 Xcode 调试扩展而不是父应用程序。这是让 Xcode 在扩展的断点内停止的关键。
  5. Select AutomaticallyLaunch 选项下。
  6. 运行 扩展方案(不是父应用)。
  7. 向您的设备发送通知。利润。

除非其他一些东西触发了 Xcode 的喜怒无常,上面的设置应该确保无论何时你 select 和 运行 扩展方案,扩展中的断点都会被击中.如果您希望 Xcode 在父应用程序中的断点处停止,您可以返回并检查第 4 步中的 Debug executable

专业提示:不要忘记在通知 JSON 有效负载中添加 "mutable-content": 1,否则你会很伤心(iOS 不会在没有的情况下调用扩展那把钥匙)。


这是我的通知扩展方案编辑器对话框的图片:

仅当远程通知的负载包含以下信息时,系统才会执行您的通知内容应用程序扩展:

  • 有效负载必须包含值为 1mutable-content 键。

  • 负载必须包含带有 titlesubtitle正文信息。

Specifying the remote notification payload:

{
   “aps” : {
      “category” : “SECRET”,
      “mutable-content” : 1,
      “alert” : {
         “title” : “Secret Message!”,
         “body”  : “(Encrypted)”
     },
   },
   “ENCRYPTED_DATA” : “Salted__·öîQÊ$UDì_¶Ù∞è   Ω^¬%gq∞NÿÒQùw”
}

在为此苦苦挣扎之后,我终于通过更改 2 项来完成这项工作。

  1. NotificationServiceExtension 目标的 bundleID 必须不同。首选样式 com.companyname.appname.notificationservice(随便)。设置与应用程序相同的 bundleID 会导致构建到设备失败。
  2. 主要是部署目标。我用应用程序的目标仔细检查了这一点,但我们还必须检查新创建的 NotificationServiceExtenion 目标的部署目标,默认情况下是最新版本。将其设置为您希望支持但大于 ios 10 的最低 iOS 版本。

注意:确保你有 "mutable-content" : 1 在远程负载中。

希望这对某人有所帮助。

您必须将部署目标设置为在所有目标上都相同。我想知道为什么 XCode 没有自动完成此操作:/ .. Apple 喜欢浪费开发人员的时间 smh...

我目前正在开发 Xcode 12.3 和 Swift 5.2,当我从 iOS 中退出主项目目标和通知服务扩展目标时14.2iOS 13.2,成功了!

感谢所有好的建议,它们帮助我解决了与部署目标不匹配和遗漏 mutable-content 的问题。但对我来说,我仍然无法调用 NSE。我在这个博客的源代码中找到了解决方案,https://medium.com/gits-apps-insight/processing-notification-data-using-notification-service-extension-6a2b5ea2da17。我缺少将扩展程序复制到我的应用程序的 Embed App Extensions。为什么缺少这个,我不确定,在我阅读的不同教程中,我没有将其视为必需的步骤。

Embed App Extension 只是一个已重命名的“复制文件阶段”,如此处所述

本教程也非常有助于设置不同的应用程序 ID、应用程序组、配置文件等: https://blog.logrocket.com/implement-push-notifications-react-native-onesignal/