iOS 10不要调用通知服务扩展。

24

我尝试实现新的通知服务扩展,但是遇到了问题。

在我的NotificationService.swift文件中,我有以下代码:

class NotificationService: UNNotificationServiceExtension {

var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?

override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
    self.contentHandler = contentHandler
    bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

    if let bestAttemptContent = bestAttemptContent {
        // Modify the notification content here...
        bestAttemptContent.title = "\(bestAttemptContent.title) [modified]"

        print(bestAttemptContent.body)

        contentHandler(bestAttemptContent)
    }
}

override func serviceExtensionTimeWillExpire() {
    // Called just before the extension will be terminated by the system.
    // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
    if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
        contentHandler(bestAttemptContent)
    }
}
}

当我收到推送通知时,didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void)方法没有被调用。

也许我对这个扩展的工作原理有误解?


1
你好。你解决了这个问题吗? - user3703910
10个回答

50

检查服务扩展的部署目标。

当我在设备上测试版本为10.1时,部署目标设置为10.2,导致扩展没有被调用,直到我更改了它。

另一个可能会出现的问题是调试。为了使其正常工作,您需要附加服务扩展进程。在Xcode菜单中选择调试(Debug) > 附加到进程(Attach To Process) > 您的扩展名称。


5
为了进一步阐明这个问题:看起来苹果将新扩展的部署目标默认设置为最新的iOS版本,即使你的基础应用程序的目标是较旧的版本。 - Justin Vallely
对于大多数情况来说,这可能是正确的答案。只有正确设置部署目标才能让我正常运行,无论我使用哪种方案。不要忘记以正确的形式推送有效载荷。+1 - choofie
太好了,省了我大量时间!! - user3069232
你是我的英雄。 - Luke
刚刚浪费了两个小时来调试一个带有新的Firebase通知服务扩展的Flutter应用程序。我甚至无法更改通知标题!结果发现,由于我的设备不是最新的iOS版本,所以appex没有被运行...非常感谢Kamilton。 - mrpaint
在XCode 11中,我更喜欢运行扩展目标,然后选择客户端应用程序,因为“选择要运行的应用程序”选择器比“调试->附加到进程”菜单更有帮助。 - paiego

44
  1. 将服务扩展作为目标而不是应用程序运行。然后它会询问您运行服务扩展的应用程序,选择您的应用程序,它将发送通知。

  2. 确保服务扩展的部署目标小于您的物理设备的操作系统版本

  3. 确保负载包含“mutable-content: 1”

{"aps" : {
    "alert" : {
        "title" : "Introduction To Notification",
        "subtitle" : "Session 707",
        "body" : "New Notification Look Amazing"
    },
    "sound" : "default",
    "category" : "message",
    "badge" : 1,
    "mutable-content": 1
    },
    "attachment-url": "https://api.buienradar.nl/Image/1.0/RadarMapNL"
}
  • aps中不要添加content-available标志,如果已经添加,则确保将其设置为0
  • ---------------------------------------- 如果什么都不起作用,请重新启动设备 --------------------------------------


    3
    将扩展程序设为目标是关键!我花了一段时间才明白这一点。感谢你指出来! - kakubei
    3
    1. 能够帮我省下时间。谢谢 :)
    - iVarun
    1
    我的通知 { "registration_ids": ["devicetoken"], "mutable_content": true, "data": { "post_details": { "pcm_message": "asdf", "pcm_img_url": "portalvh/15683.jpg";, } }, "notification" : { "title" : "demo push", "body" : "this is push body" } } 但仍然没有调用通知服务扩展,问题出在哪里或者缺少了一些信息。我已经在整个项目中设置了部署目标10.0。 - Ankur Patel
    4
    我不认为省略 content-available 有什么意义。我们同时发送这两个标志,而且它也能正常工作。 - kas-kad
    1
    这最终为我解决了问题。我看过几篇关于在运行应用程序后附加到服务扩展的帖子,但那样做不起作用。这个方法非常好用! - coping
    显示剩余2条评论

    10

    我变得很疯狂。最后我意识到,通知服务扩展部署目标10.3(我的手机也是)。我改为10.2后,它完美地解决了问题。


    8

    如果一切都失败了,请重新启动您的设备。我刚刚花了2个小时,只需重新启动手机即可解决问题。


    2
    您值得我点赞,谢谢!显然需要杀死之前使用错误部署目标安装的服务扩展。 - ncuillery
    把我标记为花费了2个小时。 - skg

    4

    您的推送通知负载 应包含 "mutable-content" : 1 键值对

    远程通知的aps字典包括可变内容键,其值设置为1。

    推送通知负载JSON示例:

    {
      "aps":{
              "alert": {
                        "body": "My Push Notification", 
                        "title" : "Notification title"},
              "mutable-content" : 1,
              "badge":0},
    }
    

    这段代码完美运行,我将获得以下推送通知: Push Notification 还请注意:

    您无法修改静默通知或仅播放声音或标记应用程序图标的通知。

    您可以尝试 PusherHouston 来测试推送通知。

    2
    在负载中,我看到了 mutable-content:1。我已经尝试在警报对象和 apns 对象中使用此值,但它们都不起作用。 - just
    漂亮的圣诞树! - Kseniya

    3

    我有同样的问题,但我的问题在于通知扩展名是"app"。应该是appex


    1
    我的项目有多个目标,并且我使用.xcconfig文件在所有类似的目标之间共享构建设置。从模板创建服务扩展程序不会将包装器扩展名设置为“appex”,因此它会从项目中获取“app”扩展名。 - Jordan

    3

    如果您尝试从Firebase控制台发送推送,那么不可能发送"mutable_content": true。 因此,您应该从服务器或 postman 或任何类型的终端发送它。 而且,您的有效载荷应该像这样:对于Firebase

    {
        "to" : "your device token/ firebase topic",
        "notification" : {
          "body" : "This is an FCM notification that displays an image.!",
          "title" : "FCM Notification"
         },
        "mutable_content": true
      }
    

    如果不是来自 FCM,则您的有效载荷应该是:
    {"aps" : {
        "alert" : {
            "title" : "Your title",
            "subtitle" : "Your subtitle",
            "body" : "Your body"
        },
        "sound" : "default",
        "category" : "message",
        "badge" : 1,
        "mutable-content": 1
        },
        "attachment-url": "https://yourattachment-url.com"
    }
    

    注意: 确保服务扩展的部署目标版本低于您的物理设备操作系统版本。例如,如果您的开发目标是10.3,则您的服务扩展版本应该是10.2


    2
    UNNotificationServiceExtension类文档中可以得知:
    • 远程通知配置为显示一个alert

    • 远程通知的aps字典包括mutable-content键,其值设置为1

    您无法修改静音通知或只播放声音或标记应用程序图标的通知。

    基本上,必须包含以下内容:
    • mutable-content: 1
    • 一个alert字典。
    不能包含以下内容:
    • content-available: 1
    总之,苹果正在尽力防止应用程序更改静音通知。它只想允许用户通知(面向用户的通知)进行更改。

    0

    你需要在负载中添加"mutable-content": 1

    。 这与编程有关。


    0
    这是一个示例,如果您使用SwiftFirebase cloud functions(Node.js)实现发送具有通知服务扩展附件的通知。下面我只列出了一些重要点。

    负载样本

    const payload = {
        notification: {
            title: name,
            body: messageText,
            badge: "1",
            mutable_content: "true"
        },
        data: {
            type: "MESSAGE",
            fromUserId: name,
            attachmentUrl: imageUrl
        }};
    

    mutable_content: "true" 这部分非常重要,我花了很多时间才找到确切的命名方式,大部分文档现在都已经过时了。

    下一个主要问题是我们运行应用程序的方式

    使用您的设备选择通知服务扩展 enter image description here

    当您收到通知时,运行后会弹出一个窗口来选择您的主项目

    这样它将调用Notification Service Extension中的NotificationService didReceive函数(该函数位于Notification Service Extension内),以便在接收到通知时进行处理。


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