0

My app (Swift 1.2, xcode 6.3) does not receive push notification when in background or when closed. But i do recieve them when app is active and in foreground. This is what I did:

First I set up my app exactly like Google tutorial said (https://developers.google.com/cloud-messaging/ios/client?ver=swift#receive_downstream_messages). Here is my AppDelegate.swift file: import 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:.
    }


}

What am I missing? Is there something else to set up background notifications? On google tutorial page there is this text: "After it is disconnected, the client app stops receiving messages without "notification" payload from the GCM connection server. It continues to receive messages with "notification" payload until deletetokenWithAuthorizedEntity is called." If i understand this correclty, when my app stops, it should call disconnect so it will recieve push notifications alerts and badges?

Any help is appreciated :)

Tim
  • 41,901
  • 18
  • 127
  • 145
Phil Boris
  • 104
  • 1
  • 8
  • 1
    I have figured out the problem. It is not my app but the way I send push from server. Now it is working just fine. – Phil Boris Jul 10 '15 at 12:07
  • 5
    It would be nice if you could detail what was wrong and how you fixed it into an answer, and accept it as the solution. It might help others having the same issue. – Antonio Jul 10 '15 at 12:26
  • 1
    yes I have the same problem now and reading your post have be a colossal waste of time! But good for you! – Nebula Aug 03 '15 at 13:35
  • A common problem are wrong formatted messages on the server. This answer describes the correct message format: [http://stackoverflow.com/questions/31109514/making-gcm-work-for-ios-device-in-the-background](http://stackoverflow.com/questions/31109514/making-gcm-work-for-ios-device-in-the-background#answer-31176165) – Jan Laussmann Aug 18 '15 at 12:53

1 Answers1

-1

To receive push notification when app is in the background you need to format notification like below:

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]

}
Israr Ahmad
  • 127
  • 1
  • 6