0

我的應用(Swift 1.2,xcode 6.3)在後臺或關閉時不會收到推送通知。但是,當應用程序處於活動狀態並在前臺時,我會收到它們。這是我做的:在後臺收到Swift GCM Push

首先,我設置了我的應用程序,就像谷歌教程說的(https://developers.google.com/cloud-messaging/ios/client?ver=swift#receive_downstream_messages)。 這裏是我的AppDelegate.swift文件: 進口的UIKit

@UIApplicationMain 
class AppDelegate: UIResponder, UIApplicationDelegate, GGLInstanceIDDelegate { 

    var window: UIWindow? 

    // GCM iVars. 
    var registrationOptions = [String: AnyObject]() 
    var gcmSenderID: String? 

    var connectedToGCM = false 
    var subscribedToTopic = false 
    var registrationToken: String? 

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

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 
     // Override point for customization after application launch. 

     /**************** GCM Google service. ***********************/ 
     // [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) 
     if configureError != nil { 
      println("Error configuring the Google context: \(configureError)") 
     } 
     gcmSenderID = GGLContext.sharedInstance().configuration.gcmSenderID 
     // [END_EXCLUDE] 

     // Register for remote notifications 
     var types: UIUserNotificationType = UIUserNotificationType.Badge | UIUserNotificationType.Alert | UIUserNotificationType.Sound 
     var settings: UIUserNotificationSettings = 
     UIUserNotificationSettings(forTypes: types, categories: nil) 
     application.registerUserNotificationSettings(settings) 
     application.registerForRemoteNotifications() 

     // [START start_gcm_service] 
     GCMService.sharedInstance().startWithConfig(GCMConfig.defaultConfig()) 
     // [END start_gcm_service] 

     return true 
    } 

    func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) { 
     // Start the GGLInstanceID shared instance with the default config and request a registration token to enable reception of notifications 
     GGLInstanceID.sharedInstance().startWithConfig(GGLInstanceIDConfig.defaultConfig()) 
     registrationOptions = [kGGLInstanceIDRegisterAPNSOption:deviceToken, 
      kGGLInstanceIDAPNSServerTypeSandboxOption:true] 
     GGLInstanceID.sharedInstance().tokenWithAuthorizedEntity(gcmSenderID, scope: kGGLInstanceIDScopeGCM, options: registrationOptions, handler: registrationHandler) 
    } 

    // [START receive_apns_token_error] 
    func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError 
     error: NSError) { 
      println("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) 
    } 


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

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

    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 { 
          println("Already subscribed to \(self.subscriptionTopic)") 
         } else { 
          println("Subscription failed: \(error.localizedDescription)"); 
         } 
        } else { 
         self.subscribedToTopic = true; 
         NSLog("Subscribed to \(self.subscriptionTopic)"); 
        } 
      }) 
     } 
    } 

    /******************** DID RECIEVE PUSH NOTIFICATION ************************/ 
    // [START ack_message_reception] 
    func application(application: UIApplication, 
     didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) { 
      println("Notification received: \(userInfo)") 
      // This works only if the app started the GCM service 
      GCMService.sharedInstance().appDidReceiveMessage(userInfo); 
      // Handle the received message 
      // [START_EXCLUDE] 
      NSNotificationCenter.defaultCenter().postNotificationName(messageKey, object: nil, 
       userInfo: userInfo) 
      // [END_EXCLUDE] 
    } 

    func application(application: UIApplication, 
     didReceiveRemoteNotification userInfo: [NSObject : AnyObject], 
     fetchCompletionHandler handler: (UIBackgroundFetchResult) -> Void) { 
      println("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 applicationWillResignActive(application: UIApplication) { 
     // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 
     // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 
    } 

    func applicationDidEnterBackground(application: UIApplication) { 
     GCMService.sharedInstance().disconnect() 
     // [START_EXCLUDE] 
     self.connectedToGCM = false 
     // [END_EXCLUDE] 
     println("Stop executing app and whent into background!") 
    } 

    func applicationWillEnterForeground(application: UIApplication) { 
     // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 
    } 

    func applicationDidBecomeActive(application: UIApplication) { 
     // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 
     GCMService.sharedInstance().connectWithHandler({ 
      (NSError error) -> Void in 
      if error != nil { 
       println("Could not connect to GCM: \(error.localizedDescription)") 
      } else { 
       self.connectedToGCM = true 
       println("Connected to GCM") 
       // [START_EXCLUDE] 
       self.subscribeToTopic() 
       // [END_EXCLUDE] 
      } 
     }) 
    } 

    func applicationWillTerminate(application: UIApplication) { 
     // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 
    } 


} 

我缺少什麼?是否有其他設置背景通知? 在谷歌教程頁面有這樣的文字:「斷開連接後,客戶端應用程序停止接收沒有來自GCM連接服務器的」通知「有效載荷的消息,它繼續接收帶有」通知「有效載荷的消息,直到調用deletetokenWithAuthorizedEntity爲止。如果我瞭解這種相關性,當我的應用停止時,它應該調用斷開連接,以便它可以接收推送通知警報和徽章?

任何幫助表示讚賞:)

+1

我想通了這個問題。這不是我的應用程序,而是我從服務器發送推送的方式。現在它工作得很好。 –

+5

如果你能詳細說明什麼是錯誤的,以及如何將它固定在答案中,並將其作爲解決方案接受,那將會很好。它可能會幫助其他人有同樣的問題。 – Antonio

+1

是的,我現在有同樣的問題,閱讀你的文章是一個巨大的浪費時間!但對你有好處! – Luben

回答

-1

要接收推送通知時,應用程序在您需要格式化通知像下面的背景:

func getMessage(to: String,m:String) -> NSDictionary { 

    // important field: "content_available":true 
    // [START notification_format] 
    return ["to": to, 
     "content_available":true, 
     "notification":[ 
     "body":m, 
     ], 
     "sound": "default", 
     "badge": "2", 
     "title": "default" 
     ] 

    // [END notification_format] 

}