iOS 上未触发静默推送

问题描述 投票:0回答:1

我正在通过 APN 向我的 iOS 应用程序发送静默推送通知。有效负载似乎正确,并且 APNs 接受通知(响应显示 success=true)。但是,应用程序在收到通知时不会触发任何日志或后台处理。

我之前有一个NodeJS后端项目。在这个项目中,我成功发送静默推送,然后我切换到 Spring Boot 项目,我开始看不到任何静默推送。然后,当我回到我的nodejs项目时,令人惊讶的是,当我再次发送静默推送时,我在设备上看不到任何日志。但它曾经有效。

我检查过的内容:

  • content-available
    设置为
    1

  • 我的应用程序未处于终止状态,它处于前台或在后台挂起。

  • 我在物理设备上使用此 iOS 版本进行了测试

    15.3.1
    17.5

  • 当我发送简单的通知时,我可以毫无问题地看到我的 swift 项目中的日志和物理设备上的通知。

  • 不,我的证书尚未过期,如果它有问题,我将无法看到正常的通知。

  • 我的手机未处于省电模式,并且应用程序设置中的

    “Background App Refresh”
    选项已打开。

  • 应用程序功能:

    Background Modes
    通过
    Remote Notifications
    启用。

当我在静默推送的有效负载中仅提供徽章属性时,我会成功记录

“Received Push Notification: \(userInfo)”
。但是当我提供徽章以外的其他属性时,我无法显示任何日志。

我在 Spring Boot 项目中使用

com.eatthepath.pushy
库来处理 APNs 请求。

更新:

我在 Apple 开发者控制台中使用新的 CloudKit 工具进行了测试,我在其中创建了静默通知并将其发送到我的设备。根据日志,通知已成功发送到设备,但我在设备上仍然看不到任何日志。

重要更新2: 我在 iOS 版本 16.5.1 的设备上进行了尝试,静默推送工作正常。造成差异的原因可能是什么?

CloudKitConsole

我的 Swift 项目:

import SwiftUI
import UIKit
import UserNotifications

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
            if granted {
                DispatchQueue.main.async {
                    UIApplication.shared.registerForRemoteNotifications()
                }
            }
        }
        return true
    }

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
        let token = tokenParts.joined()
        print("Device Token: \(token)")
    }

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("Failed to register: \(error)")
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        logInfo("Received Push Notification: \(userInfo)")

        if let aps = userInfo["aps"] as? [String: AnyObject], aps["content-available"] as? Int == 1 {
            logInfo("This is a silent push notification")
            //DO SOME WORK
            completionHandler(.newData)
        }

        completionHandler(.newData)
    }
}

我的 Spring Boot 项目:(KOTLIN)

package io.initial.apptrackbe.service

import com.eatthepath.pushy.apns.*
import com.eatthepath.pushy.apns.auth.ApnsSigningKey
import com.eatthepath.pushy.apns.util.SimpleApnsPushNotification
import com.eatthepath.pushy.apns.util.TokenUtil
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
import java.io.File
import java.util.concurrent.CompletableFuture
import com.eatthepath.pushy.apns.DeliveryPriority
import com.eatthepath.pushy.apns.PushType
import com.eatthepath.pushy.apns.util.ApnsPayloadBuilder

@Service
class PushNotificationService(
    @Value("\${apns.key-file}") private val keyFilePath: String,
    @Value("\${apns.team-id}") private val teamId: String,
    @Value("\${apns.key-id}") private val keyId: String

) {

    private val apnsClient: ApnsClient

    init {
        try {
            apnsClient = ApnsClientBuilder()
                .setApnsServer(ApnsClientBuilder.DEVELOPMENT_APNS_HOST)
                .setSigningKey(
                    ApnsSigningKey.loadFromPkcs8File(
                        File(keyFilePath),
                        teamId,
                        keyId
                    )
                )
                .build()
        } catch (e: Exception) {
            throw IllegalStateException("Failed to initialize APNs client", e)
        }
    }
//THIS SILENT PUSH DIDINT WORK
    fun sendSilentNotification(deviceToken: String): CompletableFuture<PushNotificationResponse<SimpleApnsPushNotification>> {
        val sanitizedToken = TokenUtil.sanitizeTokenString(deviceToken)
        val payloadBuilder = object : ApnsPayloadBuilder() {
            override fun build(): String {
                setContentAvailable(true)
                return super.buildPayloadMap().toString()
            }

            override fun buildMdmPayload(p0: String?): String {
                return super.buildPayloadMap().toString()
            }
        }

        val payload = payloadBuilder.build()

        val notification = SimpleApnsPushNotification(
            sanitizedToken,
            "io.myapp.package",
            payload,
            null,
            DeliveryPriority.IMMEDIATE,
            PushType.BACKGROUND,
            null
        )

        return apnsClient.sendNotification(notification)
    }

//THIS SIMPLE PUSH WORKING
    fun sendExampleNotification(deviceToken: String, threadId: String): CompletableFuture<PushNotificationResponse<SimpleApnsPushNotification>> {
        val sanitizedToken = TokenUtil.sanitizeTokenString(deviceToken)
        val payload = """
            {
              "aps": {
                "alert": "Hello App With Group: $threadId",
                "sound": "default",
                "badge": 1,
                "thread-id": "$threadId"
              }
            }
        """.trimIndent()

        val notification = SimpleApnsPushNotification(
            sanitizedToken,
            "io.myapp.package",
            payload
        )

        return apnsClient.sendNotification(notification)
    }
}

APNS 的回应:

{token='myDeviceToken', payload='{aps={content-available=1}}', invalidationTime=null, priority=IMMEDIATE, pushType=BACKGROUND, topic='io.myapp.package', collapseId='null', apnsId=null}, success=true, apnsId=********, apnsUniqueId=*********, rejectionReason='null', tokenExpirationTimestamp=null}

ios swift spring-boot apple-push-notifications
1个回答
0
投票

静默推送通知在 iOS 上未触发可能是由于多种原因造成的,例如不正确的通知负载、应用程序状态限制或设备设置。以下是排查和解决问题的综合指南:

1。确保有效负载正确

{
  "aps": {
    "content-available": 1
  },
  "customKey": "customValue"
}

要点: content-available: 1 向 iOS 发出信号,表明这是静默通知。 避免包含警报、徽章或声音键,因为它们会将其变成可见的通知。 有效负载大小不得超过 4 KB。

2。检查应用程序权限 无声推送通知与后台获取权限相关。 确保应用程序已被授予接收通知的权限:

UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
    if granted {
        print("Notifications permission granted")
    } else {
        print("Notifications permission denied: \(String(describing: error))")
    }
}
  • 在后台模式下启用远程通知: 转到目标设置 > 签名和功能 > 后台模式。

  • 检查远程通知。

3.应用程序状态和后台获取 静默通知仅在以下情况下有效:

  • 应用程序位于前台或后台。后台获取是 已启用。

  • 启用后台获取:转到目标设置 > 签名和 功能 > 背景模式。检查后台获取。实施 背景获取

© www.soinside.com 2019 - 2024. All rights reserved.