通过 APN 使用 Apple 的推送通知时,我们遇到了一个令人困惑的问题。我们有以下场景(我猜是相当标准的):
当我们的应用程序(我们在这里称之为“MyApp”)首次安装并启动时,我们会请求用户授予通过“MyApp”向他发送推送通知的权限。
在此示例中,AppDelegate 如下所示:
import UIKit
import UserNotifications
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Register Remote Notifications
UNUserNotificationCenter.current().delegate = self
self.registerForPushNotifications()
return true
}
// MARK: - Remote Notifications
func registerForPushNotifications() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
guard granted else {
return
}
self.getNotificationSettings()
}
}
func getNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
guard settings.authorizationStatus == .authorized else {
return
}
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenParts = deviceToken.map { (data) -> String in
return String(format: "%02.2hhx", data)
}
let token = tokenParts.joined()
print("ApnToken: \(token)")
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("did Fail to Register for RemoteNotifications")
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
print("willPresentNotification!")
completionHandler([.badge, .sound, .alert])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
print("UserDidResponseToNotification!")
completionHandler()
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
print("DidReceiveRemoteNotification!")
completionHandler(.newData)
}
}
因此,用户安装并启动应用程序,并询问是否允许“MyApp”向用户发送推送通知。如果用户接受推送通知application(_:didRegisterForRemoteNotificationsWithDeviceToken:)
被调用,我们将收到的 deviceToken 提供给我们的 API。
现在让我困惑的部分是:
用户还可以选择稍后通过 iPhone 设置关闭推送通知,如下所示:设置 >“MyApp”> 通知 > 允许通知 > 关闭开关
我们的 API 现在拥有 APN 的 deviceToken,但用户通过 iPhone 设置关闭了推送通知。
问题”:
用户关闭推送通知后,我们仍然能够向设备发送静默推送通知,并且“MyApp”可以毫无问题地获取正确的数据。
但在另一种情况下:用户安装并启动“MyApp”并在第一次启动时拒绝推送通知,则无法从 Apple 获取 deviceToken。即使用户拒绝推送通知警报,我也尝试从 Apple 获取 deviceToken,如下所示:(但这不起作用 - 我猜如果用户拒绝,Apple 不会提供我的任何设备令牌)
func registerForPushNotifications() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
self.getNotificationSettings()
}
}
func getNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenParts = deviceToken.map { (data) -> String in
return String(format: "%02.2hhx", data)
}
let token = tokenParts.joined()
print("ApnToken: \(token)")
}
如果用户在第一次启动时接受推送通知,那么他做什么似乎并不重要。我的意思是,好吧,我们无法通过横幅或任何内容向用户显示信息,但我们可以使用 APN 将数据传输到设备,即使用户稍后确实关闭了此设置。 (但是如果他在应用程序启动时拒绝,我们就无法发送任何内容 - 我们需要一个 deviceToken 一次)
我在这里误解了一件事吗?这对我来说似乎不一致。
我试图澄清我的问题,以便每个人都能理解我的要求。请原谅我的“糟糕”英语,作为一个非母语人士,在这里提出具有大量上下文的具体问题并不容易。无论如何,如果您需要更多信息,或者您不明白我所问的一个或多个要点,请告诉我,我将提供详细信息并澄清我的问题。
我不知道这是否重要,但目前我们正在使用 APN 开发证书(还不是分发证书)