我使用此代码获取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)
}
答案 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)
}