I'm trying to use FCM for push notification . I follow the docs and I'm trying to use :
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
print("Error fetching remote instange ID: \(error)")
} else if let result = result {
print("Remote instance ID token: \(result.token)")
self.instanceIDTokenMessage.text = "Remote InstanceID token: \(result.token)"
}
}
as specified in the docs but I'm not sure where I should put it, should it be inside didFinishLaunchingWithOptions?
I get this compilation error :
Static member 'instanceID' cannot be used on instance of type
'InstanceID'
Add Observer in didFinishLaunchingWithOptions.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
NotificationCenter.default.addObserver(self, selector: #selector(self.tokenRefreshNotification), name: NSNotification.Name.InstanceIDTokenRefresh, object: nil)
}
Call it inside didRegisterForRemoteNotificationsWithDeviceToken
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
self.connectToFcm()
}
Method
#objc func tokenRefreshNotification(_ notification: Notification) {
self.connectToFcm()
}
Create 1 function.
func connectToFcm() {
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
print("Error fetching remote instange ID: \(error)")
}
else {
print("FCM Token = \(String(describing: result?.token))")
print("Remote instance ID token: \(result.token)")
self.instanceIDTokenMessage.text = "Remote InstanceID token: \(result.token)"
}
}
}
I am certain that a few people coming through here and experiencing this issue are not having their problem solved by the solution given by Kuldeep.
I had the same exact issue.
Inside didRegisterForRemoteNotificationsWithDeviceToken instead of using the InstanceID.instanceID().instanceID as suggested by the capacitor guide, do this.
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidRegisterForRemoteNotificationsWithDeviceToken.name()), object: Messaging.messaging().fcmToken )
}
The only difference from the standard didRegisterForRemoteNotificationsWithDeviceToken is that we are using Messaging.messaging().fcmToken.
Found solution on medium. You would expect this or at least a working version to be on the capacitor docs... It is up to you which guide you follow, I used all of capacitors guide but needed this to test notifications with the fcmToken. The medium guide has more about the fcmToken, so, depending on your use case it may be a good idea to look into this guide.
Related
I want to develop a simple code which use push notifications. I create certificates and provision profiles based on existing tutorials, such as link, and this, but the register function application:didRegisterForRemoteNotificationsWithDeviceToken: is not called at all, thus I can't get device token.
I also turned on Push notification and Remote notification for background in Capabilities tab in xcode. here is my code in AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]){ (granted, error) in }
UIApplication.shared.registerForRemoteNotifications()
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
print("APNs device token: \(deviceTokenString)")
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("APNs registration failed: \(error)")
}
func application(_ application: UIApplication, didReceiveRemoteNotification data: [AnyHashable : Any]) {
print("Push notification received: \(data)")
}
I am working with an iPhone 5s running iOS 10.3.2
Please call registerForNotifications from didFinishLaunchingWithOptions method in AppDelegate
//MARK:- Methods
func registerForNotifications(){
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options:[.alert,.sound]) { (granted, error) in
if granted{
UIApplication.shared.registerForRemoteNotifications()
}else{
print("Notification permission denied.")
}
}
} else {
// For ios 9 and below
let type: UIUserNotificationType = [.alert,.sound];
let setting = UIUserNotificationSettings(types: type, categories: nil);
UIApplication.shared.registerUserNotificationSettings(setting);
UIApplication.shared.registerForRemoteNotifications()
}
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = String(format: "%#", deviceToken as CVarArg).trimmingCharacters(in: CharacterSet(charactersIn: "<>")).replacingOccurrences(of: " ", with: "")
print(token)
}
I couldn't find why it wasn't called, but when I changed my test target to an iPhone 7 which is running iOS 10.3.2, it worked fine.
I'm not sure why it is happening, but changing your target may solve the problem
My push notifications sent from the Firebase console does not appear.. Yesterday, they appeared when i deleted my app, and freshly installed again - but only 1 time, and then they stopped appearing again. Today they dont appear at all..
I've tried to renew my APNs certificate, to create a new app on Firebase, to run the examplecode, check for correct bundle identifiers, check settings in xcode and now im lost for ideas..
I am able to receive push notifications from an APNs-tester, so I'm quite sure my certificate is good! It must be a Firebase problem somehow..
Here's my appDelegate:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
UIApplication.sharedApplication().statusBarStyle = .Default
// Parse
User.initialize()
PFCategory.initialize()
Follow.initialize()
Activity.initialize()
PostElement.initialize()
PFComment.initialize()
Socials.initialize()
Notification.initialize()
let configuration = ParseClientConfiguration {
$0.applicationId = "Agpq2y3O2Gxxxxxx"
$0.clientKey = "k2bM8XTYf354fxAxxxxxxxxxx"
$0.server = "https://parseapi.back4app.com/"
$0.localDatastoreEnabled = false
}
Parse.initializeWithConfiguration(configuration)
PFFacebookUtils.initializeFacebookWithApplicationLaunchOptions(launchOptions)
// Firebase configuration
FIRApp.configure()
// Facebook
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
// Add observer for InstanceID token refresh callback.
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.tokenRefreshNotification), name: kFIRInstanceIDTokenRefreshNotification, object: nil)
//Register for remote notifications
let notificationTypes: UIUserNotificationType = [UIUserNotificationType.Alert, UIUserNotificationType.Badge, UIUserNotificationType.Sound]
let pushNotificationSettings = UIUserNotificationSettings(forTypes: notificationTypes, categories: nil)
application.registerUserNotificationSettings(pushNotificationSettings)
application.registerForRemoteNotifications()
return true
}
// When app registered for remote notification
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
print("** DEVICE TOKEN = \(deviceToken) **")
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.Unknown)
print("** APNS Token set!! **")
}
// When app failed to register for remote notification
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
// Print the error, if failing to register for push notifications
print("AppDelegate, failed with registering for remote notifications: \(error)")
}
// If no token, or token has changed, this method is called to refresh it!
func tokenRefreshNotification(notification: Notification) {
if let refreshedToken = FIRInstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
}
// Connect to FCM since connection may have failed when attempted before having a token.
connectToFcm()
}
func connectToFcm() {
FIRMessaging.messaging().connectWithCompletion { (error) in
if error != nil {
print("Unable to connect with FCM. \(error)")
} else {
print("Connected to FCM.")
}
}
}
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
print("didRegisterUserNotificationSettings")
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject: AnyObject]) {
// Let FCM know about the message for analytics etc.
FIRMessaging.messaging().appDidReceiveMessage(userInfo)
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// Print message ID.
print("Message ID: \(userInfo["gcm.message_id"]!)")
// Print full message.
print(userInfo)
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
// Let FCM know about the message for analytics etc.
FIRMessaging.messaging().appDidReceiveMessage(userInfo)
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// Print message ID.
print("Message ID: \(userInfo["gcm.message_id"]!)")
// Print full message.
print(userInfo)
}
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
return PDKClient.sharedInstance().handleCallbackURL(url) || FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
}
func applicationWillResignActive(application: UIApplication) {
}
func applicationDidEnterBackground(application: UIApplication) {
print("------APP IN BACKGROUND!!!!!------")
// Setting the user to offline in Parse - be aware of bad connection, this may fuck it up
api.setOnlineStatus("offline")
// Setting the batchnumber to 0 and disconnecting from FCM
application.applicationIconBadgeNumber = 0;
FIRMessaging.messaging().disconnect()
print("Disconnected from FCM.")
}
func applicationWillEnterForeground(application: UIApplication) {
}
func applicationDidBecomeActive(application: UIApplication) {
print("------APP DID BECOME ACTIVE!!!!!------")
firebase = FirebaseManager()
connectToFcm()
FBSDKAppEvents.activateApp()
}
func applicationWillTerminate(application: UIApplication) {
}
}
I cant see whats missing - have anyone experienced the same problem, or know about a possible solution? :)
Best regards!
i had implement Firebase with FirebaseAuth/FCM etc and did sent notification successfully through Firebase Console.
However i would need to push the notification from my own app server.
i am wondering below which way is correct way to retrieve the registration id for the device:-
1) retrieve registration id token from didRegisterForRemoteNotificationWithDeviceToken
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
var token = ""
for i in 0..<deviceToken.count {
token += String(format: "%02.2hhx", arguments: [deviceToken[i]])
}
print("Registration succeeded!")
print("Token: ", token)
Callquery(token)
}
2) Retrieve Registration token from firebase (Based on Firebase document which retrieve the current registration token)
let token = FIRInstanceID.instanceID().token()!
i was using the first way, the push notification is not being received even the registration id is stored on my app server database accordingly and i get this CURL session result :-
{"multicast_id":6074293608087656831,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}
i had also tried the second way and get fatal error while running the app as below:-
appreciated if anyone could point me the right way, thanks!
The tokenRefreshNotification function doesn't always get called when launching the app.
However, when placing the code inside the regular didRegisterForRemoteNotificationsWithDeviceToken delegate function, I can get the token every time:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
if let refreshedToken = InstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
}
}
(Swift 3 + Firebase 4.0.4)
The recommended way by Firebase:
let token = Messaging.messaging().fcmToken
Reference : Setting Up a Firebase Cloud Messaging Client App on iOS
Swift 3 + Firebase 4.0.4 :
static var FirebaseToken : String? {
return InstanceID.instanceID().token()
}
Swift 4 + Firebase (5.3.0)
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
InstanceID.instanceID().instanceID(handler: { (result, error) in
if let error = error {
print("Error fetching remote instange ID: \(error)")
} else if let result = result {
print("Remote instance ID token: \(result.token)")
}
})
}
Swift 4
Courtesy of: https://stackoverflow.com/a/50945350/1014164
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
print("Error fetching remote instange ID: \(error)")
} else if let result = result {
print("Remote instance ID token: \(result.token)")
}
}
FCM Device Token swift3
let fcmDeviceToken = FIRInstanceID.instanceID().token()
print("FCM token: \(fcmDeviceToken ?? "")")
Go with the second option, and this is going to seem really stupid/simple, but to fix that nil optional fatal error, just remove the force-unwrap at the end
Your code:
var token = FIRInstanceID.instanceID().token()!
Make it:
var token = FIRInstanceID.instanceID().token()
That will at least fix that nasty crash
First register for the firebase token refresh notification:
NotificationCenter.default.addObserver(self, selector:
#selector(tokenRefreshNotification), name:
NSNotification.Name.InstanceIDTokenRefresh, object: nil)
Then you can receive the token in the tokenRefreshNotification selector:
func tokenRefreshNotification(_ notification: Notification) {
if let refreshedToken = FIRInstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
}
// Connect to FCM since connection may have failed when attempted before having a token.
connectToFcm()
}
To Get current FCM Token
if let token = Messaging.messaging().fcmToken {
// token is current fcmToken
}
To Renew current FCM Token
If we delete current instanceId, new token will be received vi MessagingDelegate (messaging:didReceiveRegistrationToken) a moment later.
InstanceID.instanceID().deleteID { (error) in
if let er = error {
print(er.localizedDescription)
} else {
print("instanceID().deleteID success ---------------➤")
}
}
I was having the same problem, but could not figure out what was going on.
The didRegisterForRemoteNotificationsWithDeviceToken suggested by #Sam is called (almost) every time, so it is a good work around. BUT, it is NOT called the first time you open the app with the refreshed token.
So for this scenario you still need the:
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
print("Refreshed Token: \(fcmToken)")
}
So if you only use the:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
if let fcmToken = InstanceID.instanceID().token() {
print("InstanceID token: \(fcmToken)")
}
}
You will only get the "refreshed token" the second time the user opens the app.
I managed to force a refresh token by uninstalling the app and cleaning the Build Folder (Product > Clean Build Folder). Good for testing.
Ideally it could all be handled at messaging:didReceiveRegistrationToken delegate method, but I was not able to make it work. Another way to get notified for changes in the FCM token is to listen NSNotification named kFIRMessagingRegistrationTokenRefreshNotification as suggested in the documentation: https://firebase.google.com/docs/cloud-messaging/ios/client
First import the libraries like:
import FirebaseInstanceID
import FirebaseMessaging
import UserNotifications
set Delegate:MessagingDelegate, UNUserNotificationCenterDelegate
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate, UNUserNotificationCenterDelegate {
Write this code on didFinishLaunching():
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
Messaging.messaging().delegate = self
//remote Notifications
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (isGranted, err) in
if err != nil {
//Something bad happend
} else {
UNUserNotificationCenter.current().delegate = self
Messaging.messaging().delegate = self
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
} else {
// Fallback on earlier versions
}
if #available(iOS 10, *) {
UNUserNotificationCenter.current().requestAuthorization(options: [.badge,.sound,.alert], completionHandler: { (granted, error) in
application.registerForRemoteNotifications()
})
}else{
let notificationSettings = UIUserNotificationSettings(types: [.badge,.sound,.alert], categories: nil)
UIApplication.shared.registerUserNotificationSettings(notificationSettings)
UIApplication.shared.registerForRemoteNotifications()
}
return true
}
Write connectFCM method like this way:
func ConnectToFCM() {
Messaging.messaging().shouldEstablishDirectChannel = true
if let token = InstanceID.instanceID().token() {
print("\n\n\n\n\n\n\n\n\n\n ====== TOKEN DCS: " + token)
}
Also write delegate methods for registering and receiving push notification:
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
print("\n\n\n\n\n ==== FCM Token: ",fcmToken)
HelperFunction.helper.storeInUserDefaultForKey(name: kFCMToken, val: fcmToken)
ConnectToFCM()
}
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
// UIApplication.shared.applicationIconBadgeNumber += 1
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "Barker"), object: nil)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
print(userInfo)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
}
Now we can test it from firebase console.
100% working, easy and tested
Note:
Enable push notification from capability section of xcode.
check twice your both p12 certificates uploaded on firebase project setting.
Device token only can get from real device not a simulator.
First of all, you should import all required libs
import Firebase
import UserNotifications
later in AppDelegate.swift call next function
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
print("Error fetching remote instance ID: \(error)")
} else if let result = result {
print("Remote instance ID token: \(result.token)")
}
}
}
confirm to MessagingDelegate protocol.
then you can add below delegate method and get the Firebase Token. (documentation https://firebase.google.com/docs/cloud-messaging/ios/client )
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
// send to remote server
InstanceID.instanceID().instanceID { result, error in
if let error = error {
print("Error fetching remote instance ID: \(error)")
} else if let result = result {
print("Remote instance ID token: \(result.token)")
}
}
}
This question is old but still if someone want to use in Objective C.
Latest Firebase: 6.27.0
In iOS Objective C we can use like this
[[FIRInstanceID instanceID] instanceIDWithHandler:^(FIRInstanceIDResult * _Nullable result,
NSError * _Nullable error) {
if (error != nil) {
NSLog(#"Error : %#", error);
} else {
token = result.token;
}
NSLog(#"Token %#", result.token);
}];
and to get Instance Id:
[[FIRInstanceID instanceID] getIDWithHandler:^(NSString *identity, NSError *error) {
if (error != nil) {
NSLog(#"Error : %#", error);
} else {
NSLog(#"instance ID: %#", identity);
}
NSLog(#"IID %#", identity);
}];
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
let deviceTokenString = deviceToken.reduce("") { $0 + String(format: "%02X", $1) }
print("APNs device token: \(deviceTokenString)"
}
I am making use of Firebase Cloud Messaging to send me push notifications in my iOS application. I am listening to the notification of kFIRInstanceIDTokenRefreshNotification in my AppDelegate. Once the app delegate gets the device token in application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData), my selector method of kFIRInstanceIDTokenRefreshNotification is getting called.
My problem is, once the user signs out and then signs in again, this time however after the device token is received in application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData), my selector method of kFIRInstanceIDTokenRefreshNotification is not getting called.
As an observation point, the selector method doesn't get called after the first time it is called (even if user doesn't sign out).
I am enclosing my required code below. Let me know if any other parts of code is necessary. Please can somebody explain me where I am going wrong in this.
class AppDelegate: UIResponder {
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(tokenRefreshNotification(_:)), name: kFIRInstanceIDTokenRefreshNotification, object: nil)
return true
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.Unknown)
}
func tokenRefreshNotification(notification: NSNotification) {
print("Called only first time")
}
func loginFirebaseWithFacebookAccessToken(accessToken: String) {
let credential = FIRFacebookAuthProvider.credentialWithAccessToken(accessToken)
if let user = FIRAuth.auth()?.currentUser {
user.linkWithCredential(credential) { (user, error) in
print("Sign in done")
}
} else {
FIRAuth.auth()?.signInWithCredential(credential) { (user, error) in
print("Sign in done")
}
}
}
func signOutFromFirebase() {
do {
try FIRAuth.auth()?.signOut()
}
catch {
}
}
}
actually i tried this lines, works for me:-
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
[[FIRInstanceID instanceID] deleteIDWithHandler:^(NSError * _Nullable error) {
// Add observer for InstanceID token refresh callback.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(tokenRefreshNotification:) name:kFIRInstanceIDTokenRefreshNotification object:nil];
}];
return true;
}
did you try to force the logout ?
try! FIRAUTH.auth()!.signOut()
For Swift3 / iOS10 see this link:
ios10, Swift 3 and Firebase Push Notifications (FCM)
I'm trying to use the Firebase for Notifications and I integrated it exactly as described in the docs.
But I don't understand why is doesn't work. When I build my project I see this line:
2016-05-25 16:09:34.987: <FIRInstanceID/WARNING> Failed to fetch default token Error Domain=com.firebase.iid Code=0 "(null)"
This my AppDelegate:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
FIRApp.configure()
FIRDatabase.database().persistenceEnabled = true
var service: DataService = DataService()
service.start()
registerForPushNotifications(application)
application.registerForRemoteNotifications()
return true
}
func registerForPushNotifications(application: UIApplication) {
let notificationSettings = UIUserNotificationSettings(
forTypes: [.Badge, .Sound, .Alert], categories: nil)
application.registerUserNotificationSettings(notificationSettings)
}
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
if notificationSettings.types != .None {
application.registerForRemoteNotifications()
}
}
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]])
}
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.Unknown)
print("Device Token:", tokenString)
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
// Print message ID.
print("Message ID: \(userInfo["gcm.message_id"]!)")
// Print full message.
print("%#", userInfo)
}
I too had the same issue and nothing worked for me. But all you have to do is go to your firebase console and then find your project and goto its settings, there check in its cloud messaging tab and upload your .p12 certificate into that.
thats it! happy coding :)
1.Set Notification Observer in didFinishLaunchingWithOptions Method
2.And Set tokenRefreshNotification method then u get Token in this method.
See below Code
import Firebase
import FirebaseMessaging
override func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
FIRApp.configure()
NotificationCenter.default.addObserver(self,
selector: #selector(self.tokenRefreshNotification(notification:)),
name: NSNotification.Name.firInstanceIDTokenRefresh,
object: nil)
}
// NOTE: Need to use this when swizzling is disabled
public func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.Sandbox)
}
func tokenRefreshNotification(notification: NSNotification) {
// NOTE: It can be nil here
let refreshedToken = FIRInstanceID.instanceID().token()
print("InstanceID token: \(refreshedToken)")
connectToFcm()
}
func connectToFcm() {
FIRMessaging.messaging().connectWithCompletion { (error) in
if (error != nil) {
print("Unable to connect with FCM. \(error)")
} else {
print("Connected to FCM.")
}
}
}
public func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
print(userInfo)
}
1 - Have you correctly configured your certificates as specified in the google documentation ( I won't recall the process here, it is quite long... )?
( https://firebase.google.com/docs/cloud-messaging/ios/certs#configure_an_app_id_for_push_notifications )
2 - I've been through some difficulties when setting up FCM. Once I thought everything was ok but notifications were still not working, I've decided to completely remove the app from the phone, clean my build folder and reinstall the whole thing. After that, it was working.
3 - The app was receiving notifications, but I was still getting the "Failed to fetch default token..." message. It disappeared after a while. Don't ask me why!
This is not really a proper answer, I just share my experience because I know configuring notification is not easy and every clue is welcome. So maybe this one can help. Cheers :)
After trying all of the above (and anything I could find elsewhere), what resolves the problem for me is to move
let token = FIRInstanceID.instanceID().token()
to be called when pressing a button, and not on app loading.
I know it's probably not the most elegant solution, but it's good enough for debugging purposes.
Im guessing the token is not available immediately by the server, and takes some time to be generated.
The answers above cover most of the issue, but I had the same issue and I found the following info useful:
Firebase can 'rotate' (change) a user's FCM token at any time. This is the 128 character ID that your server will use to send the push notification to the device.
Firebase docs say best practice is to use a delegate to monitor for changes with the delegate callback method:
- (void)messaging:(nonnull FIRMessaging *)messaging didRefreshRegistrationToken:(nonnull NSString *)fcmToken
[Obj - C]
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String)
[Swift]
The delegate method should be called on every change, at which point you can update the record in your server.
Unfortunately that wasn't working for me, I had a delegate but the callback wasn't being invoked. So I had to resort to manually updating the token on each app launch (as suggested by #micheal chein above) as follows:
NSString *deviceToken = [FIRInstanceID instanceID].token; // Send this to your server
[Obj-C]
let token = FIRInstanceID.instanceID().token() // Send this to your server
[Swift]
** Important: update the token after a delay (20-25s), as the rotation can sometimes only reflect after some time. You can use a timer for this.
After this I still get the APNS warning/error message:
2017-06-06 09:21:49.520: <FIRInstanceID/WARNING> Failed to fetch APNS token Error Domain=com.firebase.iid Code=1001 "(null)"
BUT, push notifications work every time without fail. So I think that log message is a bit off (possibly mistimed). If you can get option 2 to work for you, definitely do that!
FCM was working for me then just stopped. I did what Rabs G. suggested and removed the app and installed again and the notifications started working again.