是否有自动重试获取GCM令牌(ios swift)?

时间:2016-02-13 08:15:37

标签: ios xcode push-notification google-cloud-messaging

我使用此代码获取GCM令牌(APNS,然后是GCM令牌)。

当GCM没有返回令牌时,是否会自动重试?

如果是这样 - 我在哪里可以看到代码?这种情况多久发生一次?

//push
// [START register_for_remote_notifications]
func registerForRemoteNotifications(application: UIApplication, launchOptions:[NSObject: AnyObject]?) -> Bool {
    // [START_EXCLUDE]
    // Configure the Google context: parses the GoogleService-Info.plist, and initializes
    // the services that have entries in the file
    var configureError:NSError?
    GGLContext.sharedInstance().configureWithError(&configureError)
    assert(configureError == nil, "Error configuring Google services: \(configureError)")
    pushManager.gcmSenderID = GGLContext.sharedInstance().configuration.gcmSenderID
    // [END_EXCLUDE]
    // Register for remote notifications
    if #available(iOS 8.0, *) {
        let settings: UIUserNotificationSettings =
        UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
        application.registerUserNotificationSettings(settings)
        application.registerForRemoteNotifications()
    } else {
        // Fallback
        let types: UIRemoteNotificationType = [.Alert, .Badge, .Sound]
        application.registerForRemoteNotificationTypes(types)
    }

    // [END register_for_remote_notifications]
    // [START start_gcm_service]
    let gcmConfig = GCMConfig.defaultConfig()
    gcmConfig.receiverDelegate = pushManager
    GCMService.sharedInstance().startWithConfig(gcmConfig)
    // [END start_gcm_service]
    return true
}

func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings)
{
    UIApplication.sharedApplication().registerForRemoteNotifications()
}




func subscribeToTopic() {
    // If the app has a registration token and is connected to GCM, proceed to subscribe to the
    // topic
    if(pushManager.registrationToken != nil && pushManager.connectedToGCM) {
        GCMPubSub.sharedInstance().subscribeWithToken(pushManager.registrationToken, topic: pushManager.subscriptionTopic,
            options: nil, handler: {(NSError error) -> Void in
                if (error != nil) {
                    // Treat the "already subscribed" error more gently
                    if error.code == 3001 {
                        print("Already subscribed to \(self.pushManager.subscriptionTopic)")
                    } else {
                        print("Subscription failed: \(error.localizedDescription)");
                    }
                } else {
                    self.pushManager.subscribedToTopic = true;
                    NSLog("Subscribed to \(self.pushManager.subscriptionTopic)");
                }
        })
    }
}

// [START connect_gcm_service]
func connectGcmService( application: UIApplication) {

    if (self.pushManager.connectedToGCM == true)
    {
        return
    }
    // Connect to the GCM server to receive non-APNS notifications
    GCMService.sharedInstance().connectWithHandler({
        (NSError error) -> Void in
        if error != nil {
            print("Could not connect to GCM: \(error.localizedDescription)")
        } else {
            self.pushManager.connectedToGCM = true
            print("Connected to GCM")
            // [START_EXCLUDE]
            self.subscribeToTopic()
            // [END_EXCLUDE]
        }
    })
}
// [END connect_gcm_service]

// [START disconnect_gcm_service]
func disconnectGcmService(application: UIApplication) {
    GCMService.sharedInstance().disconnect()
    // [START_EXCLUDE]
    self.pushManager.connectedToGCM = false
    // [END_EXCLUDE]
}
// [END disconnect_gcm_service]


func application( application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken
    deviceToken: NSData ) {
        let tokenChars = UnsafePointer<CChar>(deviceToken.bytes)
        var tokenString = ""

        for i in 0..<deviceToken.length {
            tokenString += String(format: "%02.2hhx", arguments: [tokenChars[i]])
        }

        print("tokenString: \(tokenString)")
        pushManager.receiveApnsToken( application, deviceToken: deviceToken)
}



func application( application: UIApplication, didFailToRegisterForRemoteNotificationsWithError
    error: NSError ) {
        pushManager.receiveApnsTokenError( application, error: error)
}


func application( application: UIApplication,
    didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
        pushManager.ackMessageReception( application, userInfo: userInfo)



}

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
    pushManager.ackMessageReception( application, userInfo: userInfo)
}

和PushManager类:

public class PushManager: NSObject, GGLInstanceIDDelegate, GCMReceiverDelegate {

    var connectedToGCM = false
    var subscribedToTopic = false
    var gcmSenderID: String?
    var registrationToken: String?
    var registrationOptions = [String: AnyObject]()

    let registrationKey = "onRegistrationCompleted"
    let messageKey = "onMessageReceived"
    let subscriptionTopic = "/topics/global"

//    // [START register_for_remote_notifications]
    func registerForRemoteNotifications(application: UIApplication, launchOptions: [NSObject: AnyObject]?) -> Bool {
            // [START_EXCLUDE]
            // Configure the Google context: parses the GoogleService-Info.plist, and initializes
            // the services that have entries in the file
            var configureError:NSError?
            GGLContext.sharedInstance().configureWithError(&configureError)
            assert(configureError == nil, "Error configuring Google services: \(configureError)")
            gcmSenderID = GGLContext.sharedInstance().configuration.gcmSenderID
            // [END_EXCLUDE]
            // Register for remote notifications
            if #available(iOS 8.0, *) {
                let settings: UIUserNotificationSettings =
                UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
                application.registerUserNotificationSettings(settings)
                application.registerForRemoteNotifications()
            } else {
                // Fallback
                let types: UIRemoteNotificationType = [.Alert, .Badge, .Sound]
                application.registerForRemoteNotificationTypes(types)
            }

            // [END register_for_remote_notifications]
            // [START start_gcm_service]
            let gcmConfig = GCMConfig.defaultConfig()
            gcmConfig.receiverDelegate = self
            GCMService.sharedInstance().startWithConfig(gcmConfig)
            // [END start_gcm_service]
            return true
    }

    func subscribeToTopic() {
        // If the app has a registration token and is connected to GCM, proceed to subscribe to the
        // topic
        if(registrationToken != nil && connectedToGCM) {
            GCMPubSub.sharedInstance().subscribeWithToken(self.registrationToken, topic: subscriptionTopic,
                options: nil, handler: {(NSError error) -> Void in
                    if (error != nil) {
                        // Treat the "already subscribed" error more gently
                        if error.code == 3001 {
                            print("Already subscribed to \(self.subscriptionTopic)")
                        } else {
                            print("Subscription failed: \(error.localizedDescription)");
                        }
                    } else {
                        self.subscribedToTopic = true;
                        NSLog("Subscribed to \(self.subscriptionTopic)");
                    }
            })
        }
    }

    // [START connect_gcm_service]
    func connectGcmService( application: UIApplication) {
        // Connect to the GCM server to receive non-APNS notifications
        GCMService.sharedInstance().connectWithHandler({
            (NSError error) -> Void in
            if error != nil {
                print("Could not connect to GCM: \(error.localizedDescription)")
            } else {
                self.connectedToGCM = true
                print("Connected to GCM")
                // [START_EXCLUDE]
                self.subscribeToTopic()
                // [END_EXCLUDE]
            }
        })
    }
    // [END connect_gcm_service]

    // [START disconnect_gcm_service]
    func applicationDidEnterBackground(application: UIApplication) {
        GCMService.sharedInstance().disconnect()
        // [START_EXCLUDE]
        self.connectedToGCM = false
        // [END_EXCLUDE]
    }
    // [END disconnect_gcm_service]

    // [START receive_apns_token]
    public func receiveApnsToken( application: UIApplication, deviceToken: NSData ) {
            // [END receive_apns_token]
            // [START get_gcm_reg_token]
            // Create a config and set a delegate that implements the GGLInstaceIDDelegate protocol.
            let instanceIDConfig = GGLInstanceIDConfig.defaultConfig()
            instanceIDConfig.delegate = self
            // Start the GGLInstanceID shared instance with that config and request a registration
            // token to enable reception of notifications
            GGLInstanceID.sharedInstance().startWithConfig(instanceIDConfig)
            registrationOptions = [kGGLInstanceIDRegisterAPNSOption:deviceToken,
                kGGLInstanceIDAPNSServerTypeSandboxOption:true]
            GGLInstanceID.sharedInstance().tokenWithAuthorizedEntity(gcmSenderID,
                scope: kGGLInstanceIDScopeGCM, options: registrationOptions, handler: registrationHandler)
            // [END get_gcm_reg_token]
    }

    // [START receive_apns_token_error]
    public func receiveApnsTokenError( application: UIApplication, error: NSError ) {
            print("Registration for remote notification failed with error: \(error.localizedDescription)")
            // [END receive_apns_token_error]
            let userInfo = ["error": error.localizedDescription]
            NSNotificationCenter.defaultCenter().postNotificationName(
                registrationKey, object: nil, userInfo: userInfo)
    }

    // [START ack_message_reception]
    func ackMessageReception( application: UIApplication, userInfo: [NSObject : AnyObject]) {//, fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
            print("Notification received: \(userInfo)")
            // This works only if the app started the GCM service
            GCMService.sharedInstance().appDidReceiveMessage(userInfo);
            ...
    }

    func application( application: UIApplication,
        didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
        fetchCompletionHandler handler: (UIBackgroundFetchResult) -> Void) {
            print("Notification received: \(userInfo)")
            // This works only if the app started the GCM service
            GCMService.sharedInstance().appDidReceiveMessage(userInfo);
            // Handle the received message
            // Invoke the completion handler passing the appropriate UIBackgroundFetchResult value
            // [START_EXCLUDE]
            NSNotificationCenter.defaultCenter().postNotificationName(messageKey, object: nil,
                userInfo: userInfo)
            handler(UIBackgroundFetchResult.NoData);
            // [END_EXCLUDE]
    }
    // [END ack_message_reception]

    func registrationHandler(registrationToken: String!, error: NSError!) {
        if (registrationToken != nil) {
            self.registrationToken = registrationToken
            print("Registration Token: \(registrationToken)")
            self.subscribeToTopic()
            let userInfo = ["registrationToken": registrationToken]
            NSNotificationCenter.defaultCenter().postNotificationName(
                self.registrationKey, object: nil, userInfo: userInfo)
        } else {
            print("Registration to GCM failed with error: \(error.localizedDescription)")
            let userInfo = ["error": error.localizedDescription]
            NSNotificationCenter.defaultCenter().postNotificationName(
                self.registrationKey, object: nil, userInfo: userInfo)
        }
    }

    // [START on_token_refresh]
    public func onTokenRefresh() {
        // A rotation of the registration tokens is happening, so the app needs to request a new token.
        print("The GCM registration token needs to be changed.")
        GGLInstanceID.sharedInstance().tokenWithAuthorizedEntity(gcmSenderID,
            scope: kGGLInstanceIDScopeGCM, options: registrationOptions, handler: registrationHandler)
    }

1 个答案:

答案 0 :(得分:0)

基于docs,如果注册失败,建议客户端应用重试。如果GCM对客户端应用程序的运行不是必不可少的,那么应用程序可以忽略注册错误并尝试在下次启动时再次注册。否则,它应该使用指数后退重试注册操作(客户端应用程序应该在重试之前等待前一段时间)。一旦您的客户端应用程序具有注册令牌,它就可以通过GCM APNs界面接收消息。

为了处理已刷新注册令牌的情况,GGLInstanceIDDelegate协议声明了一个onTokenRefresh方法,该方法在系统确定需要刷新令牌时调用。

func onTokenRefresh() {
// A rotation of the registration tokens is happening, so the app needs to request a new token.
print("The GCM registration token needs to be changed.")
GGLInstanceID.sharedInstance().tokenWithAuthorizedEntity(gcmSenderID,
scope: kGGLInstanceIDScopeGCM, options: registrationOptions, handler: registrationHandler)
}