苹果推送通知(APN)不一致?

时间:2018-06-27 05:58:52

标签: ios swift push-notification apple-push-notifications swift4

在通过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设置关闭“推送通知”:“设置”>“我的应用”>“通知”>“允许通知”>“关闭开关”

我们的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开发证书(尚未发行证书)

1 个答案:

答案 0 :(得分:0)

好问题,

问题是,如果用户允许您发送推送通知(给您他/她的设备令牌),您将能够发送推送。通过通知发送的推送数据可以在不通知用户的情况下发送(静默通知),您可以在此处了解更多信息:https://medium.com/@m.imadali10/ios-silent-push-notifications-84009d57794c

这就是为什么即使用户阻止显示通知也可以发送推送的原因。该设置仅控制显示外观,但是由于他/她为您提供了令牌,因此您仍然可以将数据发送给他们。实际上,用户在授予令牌后无法禁用该令牌。

相关问题