I am following this article and M Penades' answer building VoIP Notification Demo. I am able to register notification using didRegisterUserNotificationSettings and can get voip token from didUpdatePushCredentials.
But when I am using houston simulates sending notification to my device, I can get 1 push notification sent successfully message from console but no actions or logs on device side. It seems that didReceiveIncomingPushWithPayload never invoked.
P.S. I am using Xcode 7.3, iPhone 6(iOS 9.3) and iPad Mini(iOS 9.3) for development. Distributed Ad Hoc ipa for installation.
The codes posted here.
import UIKit
import PushKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let voipRegistry = PKPushRegistry(queue: dispatch_get_main_queue())
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
//Enable all notification type. VoIP Notifications don't present a UI but we will use this to show local nofications later
let notificationSettings = UIUserNotificationSettings(forTypes: [UIUserNotificationType.Alert, UIUserNotificationType.Badge, UIUserNotificationType.Sound] , categories: nil)
//register the notification settings
application.registerUserNotificationSettings(notificationSettings)
//output what state the app is in. This will be used to see when the app is started in the background
NSLog("app launched with state \(application.applicationState.stringValue)")
return true
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
//output to see when we terminate the app
NSLog("app terminated")
}
}
extension AppDelegate {
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
//register for voip notifications
NSLog("didRegisterUserNotificationSettings called")
voipRegistry.desiredPushTypes = Set([PKPushTypeVoIP])
voipRegistry.delegate = self;
}
}
extension AppDelegate: PKPushRegistryDelegate {
func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) {
NSLog("didUpdatePushCredentials called")
//print out the VoIP token. We will use this to test the nofications.
NSLog("voip token: \(credentials.token)")
}
func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) {
NSLog("didReceiveIncomingPushWithPayload called")
let payloadDict = payload.dictionaryPayload["aps"] as? Dictionary<String, String>
let message = payloadDict?["alert"]
//present a local notifcation to visually see when we are recieving a VoIP Notification
if UIApplication.sharedApplication().applicationState == UIApplicationState.Background {
NSLog("incoming notificaiton from background")
let localNotification = UILocalNotification();
localNotification.alertBody = message
localNotification.applicationIconBadgeNumber = 1;
localNotification.soundName = UILocalNotificationDefaultSoundName;
UIApplication.sharedApplication().presentLocalNotificationNow(localNotification);
}
else {
NSLog("incoming notificaiton from frontend")
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let alertController = UIAlertController(title: "Title", message: "This is UIAlertController default", preferredStyle: UIAlertControllerStyle.Alert)
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil)
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil)
alertController.addAction(cancelAction)
alertController.addAction(okAction)
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)
})
}
NSLog("incoming voip notfication: \(payload.dictionaryPayload)")
}
func pushRegistry(registry: PKPushRegistry!, didInvalidatePushTokenForType type: String!) {
NSLog("didInvalidatePushTokenForType called")
NSLog("token invalidated")
}
}
extension UIApplicationState {
//help to output a string instead of an enum number
var stringValue : String {
get {
switch(self) {
case .Active:
return "Active"
case .Inactive:
return "Inactive"
case .Background:
return "Background"
}
}
}
}
Any idea on how to receive such notification?
Finally I fixed this issue.
There is ok for swift source code, the issue is I mis-send the push request to apple's development server gateway.sandbox.push.apple.com, actually we should send request to apple's production server gateway.push.apple.com.
If you are following M Penades' procedure, please note that you need modify Simplepush script, just replace ssl://gateway.sandbox.push.apple.com:2195 by ssl://gateway.push.apple.com:2195 at line 20 and try again.
Hope it works for you.
Related
I implemented the procedures in order to use Firebase Cloud Messaging service.
I set
FirebaseAppDelegateProxyEnabled to NO (swizzling disabled)
because I want to customize the message to send to the device by using the structure "data" instead of "notification" structure.
I can see from the debug output that a message is received in this callback:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
// With swizzling disabled you must let Messaging know about the message, for Analytics
Messaging.messaging().appDidReceiveMessage(userInfo)
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
// I want to play a sound
// create a sound ID, in this case its the SMSReceived sound.
let systemSoundID: SystemSoundID = 1007 // file:// /System/Library/Audio/UISounds/sms-received1.caf
// to play sound
AudioServicesPlaySystemSound(systemSoundID)
if let title = userInfo["title"] as? NSString {
let myalert = MyAlert(title: "New message received!", message: title as String, preferredStyle: UIAlertControllerStyle.alert)
myalert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil))
myalert.addAction(UIAlertAction(title: "Open app", style: .default, handler: { _ in
print("The \"OK\" alert occured.")
}))
self.window?.rootViewController?.present(myalert, animated: true, completion: nil)
}// END if let title = alert["title"]
completionHandler(UIBackgroundFetchResult.newData)
}
It raises in both cases (fore and back).
Everything goes perfectly in foreground but no sound and no alert in background.
I am pretty sure I missed something but I cannot understand what... Maybe I need some "authorization" from the operating system to display and alert and play sound?
EDIT 1:
I implemented the UNUserNotificationCenterDelegate to requestAuthorization:
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
// [START set_messaging_delegate]
Messaging.messaging().delegate = self
// [END set_messaging_delegate]
// Register for remote notifications. This shows a permission dialog on first run, to
// show the dialog at a more appropriate time move this registration accordingly.
// [START register_for_notifications]
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
// [END register_for_notifications]
if launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] != nil {
// show alert
let myalert = MyAlert(title: "New message!", message: "MyApp" as String, preferredStyle: UIAlertControllerStyle.alert)
myalert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil))
myalert.addAction(UIAlertAction(title: "Open MyApp", style: .default, handler: { _ in
print("The \"OK\" alert occured.")
}))
self.window?.rootViewController?.present(myalert, animated: true, completion: nil)
}
return true
}
SOLVED!
I used the built-in system with a "notification" structure with swizzling enabled (FirebaseAppDelegateProxyEnabled = YES in info.plist) and here is the json message I created:
{
"message":
{
"topic":"topic",
"notification":
{
"body":"body",
"title":"title"
},
"apns":
{
"payload":
{
"aps":
{
"sound":"default"
}
}
}
}
}
This is the AppDelegate.swift class I used...
import UIKit
import StoreKit
import UserNotifications
import Firebase
import AVFoundation
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate,UNUserNotificationCenterDelegate,MessagingDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.registerForRemoteNotification()
//Firebase initialization
FirebaseApp.configure()
// To receive registration tokens on app start we need to implement the messaging delegate protocol in
// a class and provide it to the delegate property after calling FirebaseApp.Configure
Messaging.messaging().delegate = self
let token = Messaging.messaging().fcmToken
print("FCM TOKEN = \(String(describing: token))")
if let remote = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? [AnyHashable : Any] {
self.sendToNewsPage()
}
return true
}
func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
//
print("Application didRegister notificationSettings")
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// Disable swizzling, explicitly map the APNs token to the FCM registration token.
//Messaging.messaging().apnsToken = deviceToken
Messaging.messaging().subscribe(toTopic: "topic")
print("Subcribed to topic")
}
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 invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active 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.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
// MARK: Remote Notifications
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
#if DEBUG
print(userInfo)
#endif
let state: UIApplicationState = UIApplication.shared.applicationState
if state == .active {
// create a sound ID, in this case its the SMSReceived sound.
let systemSoundID: SystemSoundID = 1007
// to play sound
AudioServicesPlaySystemSound(systemSoundID)
if let aps = userInfo["aps"] as? NSDictionary {
if let alert = aps["alert"] as? NSDictionary {
if let title = alert["title"] as? NSString {
let myalert = MyAlert(title: "New message received!", message: title as String, preferredStyle: UIAlertControllerStyle.alert)
myalert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil))
myalert.addAction(UIAlertAction(title: "Open ViewController", style: .default, handler: { _ in
print("The \"OK\" alert occured.")
self.sendToNewsPage()
}))
self.window?.rootViewController?.present(myalert, animated: true, completion: nil)
}// END if let title = alert["title"]
}// END if let alert = aps["alert"]
}// END if let aps = userInfo["aps"]
}// END else if state == .active
else {
self.sendToNewsPage()
}
}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
print("Firebase NEW registration token: \(fcmToken)")
// Note: This callback is fired at each app startup and whenever a new token is generated.
}
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
print("Firebase registration token REFRESH: \(fcmToken)")
}
func registerForRemoteNotification() {
let application:UIApplication = UIApplication.shared
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
}
// We need to implement this code only if swizzling id disabled - (FirebaseAppDelegateProxyEnabled = NO)
// #available(iOS 10.0, *)
// func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
//
// completionHandler([.alert, .badge, .sound])
// }
//
// #available(iOS 10.0, *)
// func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
//
// completionHandler()
// }
//MARK : Notification
func sendToNewsPage() {
let newsMessage = UIStoryboard(name: "MenuInfo", bundle: nil).instantiateViewController(withIdentifier: "SWRevealViewController")
self.window?.rootViewController = newsMessage
}
}
This json let the notification play a sound in background!
I am trying to develop a VoIP app using Twilio Client iOS SDK. My app receives incoming calls when its not in background. For background mode I am trying to use PushKit Framework as Apple suggests. But my app is not getting registered for PushKit. The method didUpdatePushCredentials is not getting called.
This is my app delegate and settings:
import UIKit
import PushKit;
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var voipRegistry: PKPushRegistry!;
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
if UIApplication.instancesRespondToSelector(#selector(UIApplication.registerUserNotificationSettings(_:))) {
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: [UIUserNotificationType.Alert, UIUserNotificationType.Badge, UIUserNotificationType.Sound], categories: nil))
}
let preferences = NSUserDefaults.standardUserDefaults()
let usrIdKey = "usrId"
let tokenKey = "token"
if preferences.objectForKey(usrIdKey) == nil || preferences.objectForKey(tokenKey) == nil{
// Doesn't exist
} else {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
var nav1 = UINavigationController()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewControllerObj = storyboard.instantiateViewControllerWithIdentifier("NumberScreenViewController") as? NumberScreenViewController
nav1.viewControllers = [viewControllerObj!]
self.window!.rootViewController = nav1
self.window?.makeKeyAndVisible()
}
phone.login{
device in
}
var state:String
switch application.applicationState {
case .Active:
state = "Active"
case .Background:
state = "Background"
case .Inactive:
state = "Active"
}
NSLog("App launched with state \(state)")
return true
}
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) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state informationO to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the active 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.
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
//output to see when we terminate the app
NSLog("app terminated")
}
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
NSLog("Registering for VOIP notifications.")
//register for voip notifications
voipRegistry = PKPushRegistry(queue: dispatch_get_main_queue())
voipRegistry.desiredPushTypes = Set([PKPushTypeVoIP])
voipRegistry.delegate = self;
}
func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification)
{
if ( application.applicationState == UIApplicationState.Active)
{
print("Active")
// App is foreground and notification is recieved,
// Show a alert.
}
else if( application.applicationState == UIApplicationState.Background)
{
print("Background")
// App is in background and notification is received,
// You can fetch required data here don't do anything with UI.
self.redirectToPage(notification.userInfo)
}
else if( application.applicationState == UIApplicationState.Inactive)
{
print("Inactive")
// App came in foreground by used clicking on notification,
// Use userinfo for redirecting to specific view controller.
self.redirectToPage(notification.userInfo)
}
}
func redirectToPage(userInfo:[NSObject : AnyObject]!)
{
var viewControllerToBrRedirectedTo:DialScreenViewController = DialScreenViewController(nibName: "DialScreenViewController", bundle: nil)
if userInfo != nil
{
if let pageType = userInfo["TYPE"]
{
if pageType as! String == "Page1"
{
// viewControllerToBrRedirectedTo = UIViewController() // creater specific view controller
}
}
}
if self.window != nil && self.window?.rootViewController != nil
{
let rootVC = self.window?.rootViewController!
if rootVC is UINavigationController
{
(rootVC as! UINavigationController).pushViewController(viewControllerToBrRedirectedTo, animated: true)
}
else
{
rootVC?.presentViewController(viewControllerToBrRedirectedTo, animated: true, completion: { () -> Void in
})
}
}
}
}
extension AppDelegate: PKPushRegistryDelegate {
func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) {
//print out the VoIP token. We will use this to test the nofications.
NSLog("voip token: \(credentials.token)")
}
func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) {
let payloadDict = payload.dictionaryPayload["aps"] as? Dictionary<String, String>
let message = payloadDict?["alert"]
//present a local notifcation to visually see when we are recieving a VoIP Notification
if UIApplication.sharedApplication().applicationState == UIApplicationState.Background {
let localNotification = UILocalNotification();
localNotification.alertBody = message
localNotification.applicationIconBadgeNumber = 1;
localNotification.soundName = UILocalNotificationDefaultSoundName;
UIApplication.sharedApplication().presentLocalNotificationNow(localNotification);
}
else {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let alert = UIAlertView(title: "VoIP Notification", message: message, delegate: nil, cancelButtonTitle: "Ok");
alert.show()
})
}
NSLog("incoming voip notfication: \(payload.dictionaryPayload)")
}
func pushRegistry(registry: PKPushRegistry!, didInvalidatePushTokenForType type: String!) {
NSLog("token invalidated")
}
}
I have same problem. However it was recovered after rebooting the phone.
Go through https://www.raywenderlich.com/123862/push-notifications-tutorial
Download
import UIKit
import PushKit
class AppDelegate: UIResponder, UIApplicationDelegate,PKPushRegistryDelegate{
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let types: UIRemoteNotificationType = [.Alert, .Badge, .Sound]
application.registerForRemoteNotificationTypes(types)
self. PushKitRegistration()
return true
}
//MARK: - PushKitRegistration
func PushKitRegistration()
{
let mainQueue = dispatch_get_main_queue()
// Create a push registry object
if #available(iOS 8.0, *) {
let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue)
// Set the registry's delegate to self
voipRegistry.delegate = self
// Set the push type to VoIP
voipRegistry.desiredPushTypes = [PKPushTypeVoIP]
} else {
// Fallback on earlier versions
}
}
#available(iOS 8.0, *)
func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) {
// Register VoIP push token (a property of PKPushCredentials) with server
let hexString : String = UnsafeBufferPointer<UInt8>(start: UnsafePointer(credentials.token.bytes),
count: credentials.token.length).map { String(format: "%02x", $0) }.joinWithSeparator("")
print(hexString)
}
#available(iOS 8.0, *)
func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) {
// Process the received push
}
}
Life cycle of app - when app is in terminated and push kit payload comes
I have tried
"Setting up a GCM Client App on iOS" from Google developers.
My app has an android version and the server sends push notifications successfully to Android. In ios, I can retrieve the message to didRecieveRemoteNotification function.It looks like below when printed,
aps: {
alert = {
body = tyyy;
title = "2 is going out at 03/24/2016 15:02:48";
};
badge = 2;
sound = default;
}
It receives this message when the app is in foreground and background. Nothing is shown in system tray when app is background.
When app is terminated and server is sending push notifications, I receive nothing, no activity shown.
My code is as below.
AppDelegate.swift
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GGLInstanceIDDelegate, GCMReceiverDelegate {
var window: UIWindow?
var connectedToGCM = false
var subscribedToTopic = false
var gcmSenderID: String?
var registrationToken = "AIzaSy-.....-11bSP6v72UvyKY"
var registrationOptions = [String: AnyObject]()
let registrationKey = "onRegistrationCompleted"
let messageKey = "onMessageReceived"
let subscriptionTopic = "/topics/global"
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "APP_RUNNING")
// Override point for customization after application launch.
// [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]
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound],categories: nil))
if let options = launchOptions {
if let notification = options[UIApplicationLaunchOptionsLocalNotificationKey] as? UILocalNotification {
if let userInfo = notification.userInfo {
// do something neat here
}
}
}
return true
}
func subscribeToTopic() {
// If the app has a registration token and is connected to GCM, proceed to subscribe to the
// topic
if(registrationToken != "" && connectedToGCM) {
GCMPubSub.sharedInstance().subscribeWithToken(self.registrationToken, topic: subscriptionTopic,
options: nil, handler: {(error:NSError?) -> Void in
if let error = error {
// 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)");
}
})
}
}
func application( application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken
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]
func application( application: UIApplication, didFailToRegisterForRemoteNotificationsWithError
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 application( application: UIApplication,
didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
print("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("reloadTableEvent", object: nil)
NSNotificationCenter.defaultCenter().postNotificationName(messageKey, object: nil,
userInfo: userInfo)
// [END_EXCLUDE]
}
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)")
NSUserDefaults.standardUserDefaults().setValue(registrationToken, forKey: "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]
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)
}
// [END on_token_refresh]
// [START upstream_callbacks]
func willSendDataMessageWithID(messageID: String!, error: NSError!) {
if (error != nil) {
// Failed to send the message.
} else {
// Will send message, you can save the messageID to track the message
}
}
func didSendDataMessageWithID(messageID: String!) {
// Did successfully send message identified by messageID
}
// [END upstream_callbacks]
func didDeleteMessagesOnServer() {
// Some messages sent to this device were deleted on the GCM server before reception, likely
// because the TTL expired. The client should notify the app server of this, so that the app
// server can resend those messages.
}
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) {
NSUserDefaults.standardUserDefaults().setBool(false, forKey: "APP_RUNNING")
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
GCMService.sharedInstance().disconnect()
// [START_EXCLUDE]
self.connectedToGCM = false
// [END_EXCLUDE]
}
func applicationWillEnterForeground(application: UIApplication) {
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "APP_RUNNING")
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(application: UIApplication) {
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "APP_RUNNING")
// 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.
// Connect to the GCM server to receive non-APNS notifications
GCMService.sharedInstance().connectWithHandler({(error:NSError?) -> Void in
if let error = error {
print("Could not connect to GCM: \(error.localizedDescription)")
} else {
self.connectedToGCM = true
print("Connected to GCM")
// [START_EXCLUDE]
self.subscribeToTopic()
// [END_EXCLUDE]
}
})
}
func applicationWillTerminate(application: UIApplication) {
NSUserDefaults.standardUserDefaults().setBool(false, forKey: "APP_RUNNING")
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
if let userInfo = notification.userInfo {
NSNotificationCenter.defaultCenter().postNotificationName(
"LoadEventViewController", object: nil, userInfo: userInfo)
}
}
}
ViewController, popping local notification
func scheduleLocal(message: String) {
let settings = UIApplication.sharedApplication().currentUserNotificationSettings()
if settings!.types == .None {
let ac = UIAlertController(title: "Can't schedule", message: "Either we don't have permission to schedule notifications, or we haven't asked yet.", preferredStyle: .Alert)
ac.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
presentViewController(ac, animated: true, completion: nil)
return
}
// create a corresponding local notification
let notification = UILocalNotification()
notification.alertBody = message // text that will be displayed in the notification
notification.alertAction = "open" // text that is displayed after "slide to..." on the lock screen - defaults to "slide to view"
notification.fireDate = NSDate(timeIntervalSinceNow: 0) // todo item due date (when notification will be fired)
notification.soundName = UILocalNotificationDefaultSoundName // play default sound
notification.userInfo = ["UUID": 1, ] // assign a unique identifier to the notification so that we can retrieve it later
notification.category = "TODO_CATEGORY"
UIApplication.sharedApplication().scheduleLocalNotification(notification)
}
I have 2 questions,
Is it possible to receive and show push notification even when app is in terminated state? If so, how?
Have I done something wrong in the code?
This is your push notification JSON?
aps: { "content-available" = 1; }
If yes, then you are sending a silent push. Silent push means that the user get's no visual notification, just the app delegate callback of your app is called. Remove the content-available tag and pass a message text instead.
If the App is in the foreground iOS does not show a push notification, but just calls the delegate. Then you can show an Alert View or something else you prefer.
Or you can show this: https://github.com/avielg/AGPushNote
Regarding the state "terminated by user", here the Apple doc (for silent push):
Apple documentation
Use this method to process incoming remote notifications for your app.
Unlike the application:didReceiveRemoteNotification: method, which is
called only when your app is running in the foreground, the system
calls this method when your app is running in the foreground or
background. In addition, if you enabled the remote notifications
background mode, the system launches your app (or wakes it from the
suspended state) and puts it in the background state when a remote
notification arrives. However, the system does not automatically
launch your app if the user has force-quit it. In that situation, the
user must relaunch your app or restart the device before the system
attempts to launch your app automatically again.
If you didn't did yet, register on Apple developper and configure your app for receiving push notifications. You have to pay a subscription to do so (99$/year).
GCM send message directly to your app when it is in foreground, but during background GCM rely on APNs (Apple Push Notification services) to reach your device.
Due to this, the format of the message sent by your server to GCM must be precisely formatted, this finally worked for me.
I'm struggling for some time here and probably this is my mistake but I can't find it anywhere, an answer for this.
I have implemented PushKit in some ways, but none of them were effective.
I have added the correct background modes, implemented the callbacks in the correct way, didUpdatePushCredentials is getting called normally...
However, the credentials: PKPushCredentials! variable, is giving me an error pointer... It´s not null... not nil... not anything... It simply does not have a value... it´s allocated garbage... and for that reason.. I´m receiving EXC_BREAKPOINT..
I have tried in 3 different devices... Same behavior...
I have already created the Certificates for VoIP Push...
I have done it in different ways:
By creating the void Push Registry object after didRegisterForRemotePushNotification
By creating the push registry without registering for remote push notification...
By creating the registry with main, global and custom queues..
Allways the same...
Here´s the code:
extension AppDelegate : PKPushRegistryDelegate {
func registerForVoipPush() {
self.registry = PKPushRegistry(queue:nil)
if self.registry != nil {
self.registry!.delegate = self
self.registry!.desiredPushTypes = Set<String>(arrayLiteral: PKPushTypeVoIP)
}
//let notificationSettings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories:nil)
//UIApplication.sharedApplication().registerUserNotificationSettings(notificationSettings)
}
func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) {
//print out the VoIP token. We will use this to test the nofications.
NSLog("voip token: \(credentials.token)")
if credentials != nil {
let username = NSUserDefaults.standardUserDefaults().objectForKey("username") as? String
if username != nil {
ServerDefinitions.subscribeForPush(username!, token: NSString(data: credentials.token, encoding: NSUTF8StringEncoding) as! String, callback: { (retMsg) -> Void in
print(retMsg)
})
}
}
}
func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) {
let payloadDict = payload.dictionaryPayload["aps"] as? Dictionary<String, String>
let message = payloadDict?["alert"]
//present a local notifcation to visually see when we are recieving a VoIP Notification
if UIApplication.sharedApplication().applicationState == UIApplicationState.Background {
let localNotification = UILocalNotification();
localNotification.alertBody = message
localNotification.applicationIconBadgeNumber = 1;
localNotification.soundName = UILocalNotificationDefaultSoundName;
UIApplication.sharedApplication().presentLocalNotificationNow(localNotification);
}
else {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
print("Incoming Call")
})
}
NSLog("incoming voip notfication: \(payload.dictionaryPayload)")
}
func pushRegistry(registry: PKPushRegistry!, didInvalidatePushTokenForType type: String!) {
NSLog("token invalidated")
}
}
EDIT:
Please note, that the above code is an extension of AppDelegate, made only to separate the code, so it gets more readable.
I also added var registry : PKPushRegistry? on the AppDelegate's. In order for this to work, you have to call registerForVoipPush() somewhere in code. In my case, I did it from a button.
PLEASE HELP ME!
I ran into the same issue and I solved this by adding a classic Push implementation before initiating the VoIP registration...
I guess that somehow Apple wants to ensure you firstly ask the user for basic push and get the user's aknowledgment before authorizing you to process further silent voip stuff...
Enable the Push Notifications for your app...
Then, this is the whole resulting AppDelegate file, that is quite similar to yours:
import UIKit
import PushKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
//Enable all notification type.
let notificationSettings = UIUserNotificationSettings(forTypes: [UIUserNotificationType.Alert, UIUserNotificationType.Badge, UIUserNotificationType.Sound] , categories: nil)
//register the notification settings
application.registerUserNotificationSettings(notificationSettings)
NSLog("app launched with state \(application.applicationState.stringValue)")
return true
}
func applicationWillResignActive(application: UIApplication) {
}
func applicationDidEnterBackground(application: UIApplication) {
}
func applicationWillEnterForeground(application: UIApplication) {
}
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.
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
NSLog("app terminated")
}
}
extension AppDelegate {
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
//register for voip notifications
let voipRegistry = PKPushRegistry(queue: dispatch_get_main_queue())
voipRegistry.desiredPushTypes = Set([PKPushTypeVoIP])
voipRegistry.delegate = self;
NSLog("didRegisterUserNotificationSettings")
}
}
extension AppDelegate: PKPushRegistryDelegate {
func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) {
//print out the VoIP token. We will use this to test the nofications.
NSLog("voip token: \(credentials.token)")
}
func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) {
let payloadDict = payload.dictionaryPayload["aps"] as? Dictionary<String, String>
let message = payloadDict?["alert"]
//present a local notifcation to visually see when we are recieving a VoIP Notification
if UIApplication.sharedApplication().applicationState == UIApplicationState.Background {
let localNotification = UILocalNotification();
localNotification.alertBody = message
localNotification.applicationIconBadgeNumber = 1;
localNotification.soundName = UILocalNotificationDefaultSoundName;
UIApplication.sharedApplication().presentLocalNotificationNow(localNotification);
}
else {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let alert = UIAlertView(title: "VoIP Notification", message: message, delegate: nil, cancelButtonTitle: "Ok");
alert.show()
})
}
NSLog("incoming voip notfication: \(payload.dictionaryPayload)")
}
func pushRegistry(registry: PKPushRegistry!, didInvalidatePushTokenForType type: String!) {
NSLog("token invalidated")
}
}
extension UIApplicationState {
//help to output a string instead of an enum number
var stringValue : String {
get {
switch(self) {
case .Active:
return "Active"
case .Inactive:
return "Inactive"
case .Background:
return "Background"
}
}
}
}
For a bit more information, this is inspired by this post
As #JBA I forgot to active the push notification. It's look like even you need just the push VOIP you have to active the push (traditional)
I'm using google cloud messaging to send notifications to my iOS application.
I've configured the GCM services in my App and the notifications are working correctly. I mean that my device can request a gcmRegistrationToken and I can send notification using postman to my app. These notifications are working both when app is active and inactive.
Now I want to use the Device Groups Notifications feature. So I created a group for all my user's device:
https://android.googleapis.com/gcm/notification
Content-Type:application/json
Authorization:key=API_KEY
project_id:SENDER_ID
{
"operation": "create",
"notification_key_name": "appUser-userA",
"registration_ids": ["regToken1", "regToken2"]
}
I receive my device group key:
{
"notification_key": "deviceGroupKey"
}
But no when I want to send notification to the device group using postman, I only receive the notification when the app is ACTIVE.
Here is my POST request:
https://android.googleapis.com/gcm/send
Content-Type:application/json
Authorization:key=API_KEY
{
"to" : "deviceGroupToken",
"content_available" : true,
"priority": "high",
"sound": "default",
"notification" : {
"body_loc_key" : "NOTIF_FRIEND_REQUEST",
"body_loc_args" : ["UserB"],
"click_action": "NEW_FRIEND_REQUEST"
},
"data" : {
"friendRequestId": "12345678901234567890"
}
}
Here is my AppDelegate.swift:
//
// AppDelegate.swift
//
import UIKit
import CoreData
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GGLInstanceIDDelegate, GCMReceiverDelegate {
var window: UIWindow?
var connectedToGCM = false
var gcmSenderID: String?
var gcmRegistrationToken: String?
var gcmRegistrationOptions = [String: AnyObject]()
let gcmRegistrationKey = "onRegistrationCompleted"
var subscribedToTopic = false
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
print("bundleId=\(NSBundle.mainBundle().bundleIdentifier)")
// Configure Google Analytics
// Configure tracker from GoogleService-Info.plist.
var configureError:NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError)")
// Optional: configure GAI options.
let gai = GAI.sharedInstance()
gai.trackUncaughtExceptions = true // report uncaught exceptions
gai.logger.logLevel = GAILogLevel.Verbose // remove before app release
// Override point for customization after application launch.
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)) // types are UIUserNotificationType members
// Register for remotes notifications
UIApplication.sharedApplication().registerForRemoteNotifications()
// Get the gcm sender id
gcmSenderID = GGLContext.sharedInstance().configuration.gcmSenderID
var gcmConfig = GCMConfig.defaultConfig()
gcmConfig.receiverDelegate = self
GCMService.sharedInstance().startWithConfig(gcmConfig)
return true
}
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) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
GCMService.sharedInstance().disconnect()
connectedToGCM = false
}
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.
// -->The app go through this point
// Connect to the GCM server to receive non-APNS notifications
GCMService.sharedInstance().connectWithHandler(gcmConnectionHandler)
// -->The app go through this point
}
func gcmConnectionHandler(error: NSError?) {
// -->The app never enter in this function
if let error = error {
print("Could not connect to GCM: \(error.localizedDescription)")
} else {
self.connectedToGCM = true
print("Connected to GCM")
// ...
}
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
self.saveContext()
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
// 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)
gcmRegistrationOptions = [kGGLInstanceIDRegisterAPNSOption:deviceToken,
kGGLInstanceIDAPNSServerTypeSandboxOption:true]
GGLInstanceID.sharedInstance().tokenWithAuthorizedEntity(gcmSenderID,
scope: kGGLInstanceIDScopeGCM, options: gcmRegistrationOptions, handler: gcmRegistrationHandler)
}
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
print("-- Failed to get deviceToken: \(error.localizedDescription)")
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
application.applicationIconBadgeNumber += 1
print(userInfo)
let apsInfo = userInfo["aps"] as! NSDictionary
var alertMessage = ""
print("********************** Received Notif")
if let alert = apsInfo["alert"] as? String{
alertMessage = alert
print(alertMessage)
}
else if let alert = apsInfo["alert"] as? NSDictionary {
if let body = alert["body"] as? String {
alertMessage = body
print(alertMessage)
}
else if let locKey = alert["loc-key"] as? String {
var alertBody = ""
if let locArgs = alert["loc-args"] as? [String] {
var safeArgs = ["", "", "", "", "", "", "", "", "", ""]
for var i = 0; i < locArgs.count && i < safeArgs.count; i++ {
safeArgs[i] = locArgs[i]
}
alertBody = String(format: NSLocalizedString(locKey, comment: ""),
safeArgs[0], safeArgs[1],
safeArgs[2], safeArgs[3],
safeArgs[4], safeArgs[5],
safeArgs[6], safeArgs[7],
safeArgs[8], safeArgs[9])
}
else {
alertBody = NSLocalizedString(locKey, comment: "")
}
alertMessage = alertBody
}
}
// If the application is currently on screen "Active" then we trigger a custom banner View for that notification to be shown
// Else the system will handle that and put it in the notification center
if application.applicationState == UIApplicationState.Active {
AGPushNoteView.showWithNotificationMessage(alertMessage, autoClose: true, completion: { () -> Void in
// Do nothing
})
}
else {
// if the app is inactive I try to trigger a local notification to check if the notification is received but not displayed
// or just not received because consol print doesn't work when app is inactive
var localNotification: UILocalNotification = UILocalNotification()
localNotification.alertBody = alertMessage
localNotification.fireDate = NSDate(timeIntervalSinceNow: 1)
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
}
}
func gcmRegistrationHandler(registrationToken: String!, error: NSError!) {
if (registrationToken != nil) {
self.gcmRegistrationToken = registrationToken
print("GCM Registration Token: \(registrationToken)")
let userInfo = ["registrationToken": registrationToken]
NSNotificationCenter.defaultCenter().postNotificationName(
self.gcmRegistrationKey, object: nil, userInfo: userInfo)
} else {
print("Registration to GCM failed with error: \(error.localizedDescription)")
let userInfo = ["error": error.localizedDescription]
NSNotificationCenter.defaultCenter().postNotificationName(self.gcmRegistrationKey, object: nil, userInfo: userInfo)
}
}
// MARK: - GGLInstanceIDDelegate
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: gcmRegistrationOptions, handler: gcmRegistrationHandler)
}
// MARK: - GCMReceiverDelegate
func willSendDataMessageWithID(messageID: String!, error: NSError!) {
if (error != nil) {
// Failed to send the message.
} else {
// Will send message, you can save the messageID to track the message
}
}
func didSendDataMessageWithID(messageID: String!) {
// Did successfully send message identified by messageID
}
// [END upstream_callbacks]
func didDeleteMessagesOnServer() {
// Some messages sent to this device were deleted on the GCM server before reception, likely
// because the TTL expired. The client should notify the app server of this, so that the app
// server can resend those messages.
}
func subscribeToTopic() {
// If the app has a registration token and is connected to GCM, proceed to subscribe to the
// topic
let subscriptionTopic = "/topics/test-global"
if(gcmRegistrationToken != nil && connectedToGCM) {
GCMPubSub.sharedInstance().subscribeWithToken(gcmRegistrationToken, 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 \(subscriptionTopic)")
} else {
print("Subscription failed: \(error.localizedDescription)");
}
} else {
subscribedToTopic = true;
NSLog("Subscribed to \(subscriptionTopic)");
}
})
}
}
}
Do I have forgotten something in my code? or maybe it is not possible?
Any help would be appreciated.
PS: I tryed to send notification to topics "/topics/general" and it workss fine.