I've been using GCM just fine for a long time already. One day it suddenly broke. The problem is that the first push I send I get success status back but the app doesn't receive any push whatsoever. The second push I send gets failure with an NotRegistered error. I reinstall the app: success(no notification received), failure(NotRegistered) -> Loop. I don't know what's changed. Google support is being very unhelpful and is taking a lot of time answering simple question whether it is GCM problem, APNs problem or client problem. If anyone had such issue before, please let me know what to look for. That is how it looks like:
I suspect that it happened after updating to iOS 9. I'm not sure though. If there are things in new iOS that might be blocking GCM I would appreciate if somebody pointed it out.
UPDATE:
GCM push fails with NotRegistered
that guy had a similar problem. The issue was with some manifest file. Could there be some entries in the Info.plist that I need to add for iOS 9 to allow GCM ?
UPDATE:
onTokenRefresh is being called every time the app launches. I'm getting the same token back, though. So there is a problem with a token on a GCM server, I suspect.
GCM DELEGATE CODE IN APPDELEGATE:
var connectedToGCM = false
private var deviceToken: NSData?
var gcmSenderID: String!
let authorizedEntity = "my GCM Sender_ID"
public func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
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()
GCMService.sharedInstance().startWithConfig(gcmConfig)
return true
}
public func onTokenRefresh() {
print("Token needs to be refreshed!")
let options = [
kGGLInstanceIDRegisterAPNSOption : deviceToken!,
kGGLInstanceIDAPNSServerTypeSandboxOption : true
]
GGLInstanceID.sharedInstance().tokenWithAuthorizedEntity(authorizedEntity, scope: kGGLInstanceIDScopeGCM, options: options) { (token, error) -> Void in
if error != nil {
print("Error: \(error.localizedDescription)")
} else {
print("Token: \(token)")
}
}
}
public func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
}
public func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
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)
self.deviceToken = deviceToken
}
public func applicationDidEnterBackground(application: UIApplication) {
GCMService.sharedInstance().disconnect()
connectedToGCM = false
}
public func applicationDidBecomeActive( application: UIApplication) {
print("App became active")
UIApplication.sharedApplication().applicationIconBadgeNumber = 0
// 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")
// ...
}
})
}
public func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
print("Notification received: \(userInfo)")
GCMService.sharedInstance().appDidReceiveMessage(userInfo)
}
public func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
print("Error registering")
}
public func application( application: UIApplication,
didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
fetchCompletionHandler handler: (UIBackgroundFetchResult) -> Void) {
print("Notification received(background): \(userInfo)")
NotificationManager.sharedInsteance().parseNotification(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]
handler(UIBackgroundFetchResult.NewData);
// [END_EXCLUDE]
}
UPDATE
OK, so I believe I messed up with .plist location (it wasn't in the root for some reason). I moved to the root and now I'm getting this warning/error when starting GCM:
UPD. Okay, it actually happened only once and stopped. So I don't think the problem is here.
After I moved .plist to the root directory onTokenRefresh() calls stopped, but I'm still getting NotRegistered.