Out of nowhere, the PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate: nil) started failing on my simulator, but still works on my device (same build obviously). I've tried both real phone numbers and testing phone numbers.
I'm on SDK version 9.6.0 and run it on an iOS 16.1 simulator.
Here's the error I'm getting:
Error Domain=FIRAuthErrorDomain Code=17048 "Token mismatch" UserInfo={NSLocalizedDescription=Token mismatch, FIRAuthErrorUserInfoNameKey=INVALID_APP_CREDENTIAL}
Here's my AppDelegate:
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void
) {
let userInfo = response.notification.request.content.userInfo
completionHandler()
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Auth.auth().setAPNSToken(deviceToken, type: .unknown)
Messaging.messaging().apnsToken = deviceToken
}
func application(_ application: UIApplication, didReceiveRemoteNotification notification: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
Messaging.messaging().appDidReceiveMessage(notification)
if (Auth.auth().canHandleNotification(notification)) {
completionHandler(.noData)
return
}
}
}
extension AppDelegate: MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
let tokenDict = ["token": fcmToken ?? ""]
NotificationCenter.default.post(
name: Notification.Name("FCMToken"),
object: nil,
userInfo: tokenDict)
}
}
Also here’s my Firebase certificates setup:
Any ideas?
EDIT: Now that I think about it, yesterday I updated my macOS to 13.0.1. Could it have anything to do with it?
EDIT 2: It seems that it still works on an iOS 15 simulator
I had the same issue, I finally nailed it : I updated Firebase to the latest version (10.2) and now it works on iOS 16 too :-)
Related
I've implemented FCM push notifications for my iOS app such that when a notification is delivered a banner with the expected payload is displayed on my iPhone screen, but none of my App Delegate methods are invoked.
My implementation closely follows the firebase cloud messaging documentation here with method swizzling disabled.
Why don't my app delegate methods trigger when I receive a push notification?
How can I execute code on receipt of a remote notification?
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
UNUserNotificationCenter.current().delegate = self
Messaging.messaging().delegate = self
return true
}
}
extension AppDelegate: UNUserNotificationCenterDelegate {
/* Invoked when a notification arrives when the app is running in the foreground. */
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler:
#escaping (UNNotificationPresentationOptions) -> Void
) {
let userInfo = notification.request.content.userInfo
Messaging.messaging().appDidReceiveMessage(userInfo)
completionHandler([[.banner, .sound, .badge]])
}
/* Invoked when notification arrives when the app is running in the background. */
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void
) {
let userInfo = response.notification.request.content.userInfo
Messaging.messaging().appDidReceiveMessage(userInfo)
completionHandler()
}
/** Method swizzling disabled requirement. */
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
Messaging.messaging().apnsToken = deviceToken
}
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
Messaging.messaging().appDidReceiveMessage(userInfo)
completionHandler(.noData)
}
}
extension AppDelegate: MessagingDelegate {
func messaging(
_ messaging: Messaging,
didReceiveRegistrationToken fcmToken: String?
) {
let tokenDict = ["token": fcmToken ?? ""]
NotificationCenter.default.post(
name: Notification.Name("FCMToken"),
object: nil,
userInfo: tokenDict
)
writeFCMTokenToFirestore(token: fcmToken)
}
}
On the backend I am using the firebase admin SDK within a Cloud Function to send notifications with a custom payload, as below.
const admin = require('firebase-admin');
const token = getDeviceToken();
const payload = {
notification: {
title: 'test',
badge: '1'
}
}
admin.messaging().sendToDevice(token, payload)
.then((response) => {
// Success
})
.catch((error) => {
// Failure
});
I'm getting strange behavior in iOS 14 with regards to remote notifications on iOS and Firebase Cloud Messaging (FCM).
DEVICE
First, I cannot send Test notifications to my device from the FCM console. I followed the documentation verbatim, and a few tutorials for good measure. Here's my AppDelegate:
import SwiftUI
import Firebase
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
FirebaseConfiguration.shared.setLoggerLevel(.min)
Messaging.messaging().delegate = self
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
(granted, error) in
print("Permission granted: \(granted)")
// 1. Check if permission granted
guard granted else {
print("Permission not granted")
return
}
// 2. Attempt registration for remote notifications on the main thread
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
application.registerForRemoteNotifications()
return true
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
Messaging.messaging().appDidReceiveMessage(userInfo)
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
print(userInfo)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
Messaging.messaging().appDidReceiveMessage(userInfo)
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Unable to register for remote notifications: \(error.localizedDescription)")
}
}
#available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
Messaging.messaging().appDidReceiveMessage(userInfo)
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
print(userInfo)
completionHandler([[.banner, .sound]])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
Messaging.messaging().appDidReceiveMessage(userInfo)
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
print(userInfo)
completionHandler()
}
}
extension AppDelegate: MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
print("Firebase registration token: \(fcmToken ?? "")")
let dataDict:[String: String] = ["token": fcmToken ?? ""]
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "FCMToken"), object: nil, userInfo: dataDict)
// TODO: If necessary send token to application server.
// Note: This callback is fired at each app startup and whenever a new token is generated.
}
func application(application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
}
}
let gcmMessageIDKey = "gcm_Message_ID_Key"
Other things I've tried:
Disabling method swizzling in the Info.pList (FirebaseAppDelegateProxyEnabled - Boolean - 0)
Adding Messaging.messaging().appDidReceiveMessage(userInfo) to update the appropriate methods after disabling swizzling in the App Delegate.
Sending App to background (can we test in foreground while app is running? Will it work in foreground if it works at all?)
SIMULATOR
Second, I am unable to send notifications to the simulator, unless I drag the aps file from Finder to said simulator. This aps file is a JSON file I can use for testing push notifications on simulators. Note: "alert" key has been deprecated in iOS 14.
{
"Simulator Target Bundle": "com.Example.app",
"aps": {
"sound": "default",
"badge": 1
}
}
The terminal command utility looks like this
xcrun simctl push <device> com.Example example.apns
where the <device> is the simulator device identifier (you can also use "booted" in lieu of the device identifier if only one simulator is open) and example.apns is your file. I created my apns file in Atom.
This is what I get in the logs:
These are my reports from the FCM console:
SOLVED
My implementation must've been wrong. I followed this verbatim and got it working on simulator and device. The simulator read, as a default error, remote notifications are not supported in the simulator.
There are a couple reasons why this might be the case:
Bundle IDs from Pusher to Project don't match
Not using the whole identifier e.g. 11FG89IK4-SHEN-13H4-AJD9-SN39FNS82JR for the simulator.
I also had an error in terminal Invalid device: [identifier] when I tried on a real device. The reason is I was using the device identifier in Windows > Devices and Simulator for my iPhone instead of the device token I get back in the console from this method:
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
let token = tokenParts.joined()
print("Device Token: \(token)")
}
I also used Push Notifications Tester instead of FCM. I don't know what I was doing wrong. I'm certain the Firebase tool works fine. Reasonably something on my end.
I'm currently rewriting my app from Objective-C to Swift and working on notifications. For some reason Swift version of the app is not receiving any remote push notifications while Objective-C version does.
Here's the code I'm using to register for notifications in AppDelegate:
UNUserNotificationCenter.current().delegate = self
let options: UNAuthorizationOptions = [.badge, .alert, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: options, completionHandler: { granted, error in
print("access granted: \(granted)")
})
application.registerForRemoteNotifications()
I assume that the app successfully registers because didRegisterForRemoteNotificationsWithDeviceToken method gets called. But when I try to send the test notification using the token I got from that method, I don't get actual notification on device.
Also none of these methods get called:
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) {
}
func userNotificationCenter(_ center: UNUserNotificationCenter, openSettingsFor notification: UNNotification?) {
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (_ options: UNNotificationPresentationOptions) -> Void) {
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
}
func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable : Any], completionHandler: #escaping () -> Void) {
}
What am I doing wrong?
you say that you are not receiving so let's first make sure that those methods you mention before that are not being called are comming from here extension AppDelegate: UNUserNotificationCenterDelegate (By the way when you do implement the didReceive method make sure you call the completionHandler() at the end)
When you do this:
application.registerForRemoteNotifications()
Make sure to run it from the main thread, as it can be called if not specified from the background and that might fail. You can do so by doing
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
I'll assume that you are getting the device token this way or something similar:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// 1. Convert device token to string
let tokenParts = deviceToken.map { data -> String in
return String(format: "%02.2hhx", data)
}
let token = tokenParts.joined()
// 2. Print device token to use for PNs payloads
print("Device Token: \(token)")
}
Finally implement this method to see if there are any errors while registering the device
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
// 1. Print out error if PNs registration not successful
print("Failed to register for remote notifications with error: \(error)")
}
Oh by the way (just in case you have missed it) make sure you enabled in your project's target the push notification.
Make sure you have enabled Push notification in your project setting capabilities.
How to enable:
go to target: -> select project -> go to capabilities -> go to Push Notification. enable it there.
Another thing is the certificate. While development you should not Production certificates.
I want to use FCM to send notifications and data messages to iOS Devices.
All works fine, but for some reason the delegate method messaging didReceiveRemoteMessage is never called. Therefore I cannot get data messages when the app is in the foreground... I tried it with and without a notification block beside the data. So the message I am sending looks like this:
{'message': {
'token': 'mytokenstandshere',
'notification': {
'body': 'message',
'title': 'title'},
'data': {
'datafield': 'datavalue',
'datafield2': 'datavalue2'}
}}
I tried all possibilities (without notification, without data, with both). Notification is working without problems, but the data block is not appearing in clean data messages.
I just want to have this running on iOS 11+. But I even tried it with the parts for iOS 9 and 10 from the docs from google.
This is my AppDelegate:
#
UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
Hardware.start()
Preferences.initDefaults()
FirebaseApp.configure()
Messaging.messaging().delegate = self
Messaging.messaging().shouldEstablishDirectChannel = true
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
application.registerForRemoteNotifications()
return true
}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
print("new Token: \(fcmToken)")
Messaging.messaging().subscribe(toTopic: TOPIC_ALL_MESSAGES)
NotificationSettingsListener.start()
}
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
print("Got a remote")
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
completionHandler(UIBackgroundFetchResult.newData)
}
}
#available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
// Print full message.
print(userInfo)
// Change this to your preferred presentation option
completionHandler([.alert])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
// Print full message.
print(userInfo)
completionHandler()
}
}
I'm not seeing:
application(_: didReceiveRemoteNotification: fetchCompletionHandler:)
I believe that's required for handling. Reference
Please make sure you have to assign Firebase messaging delegate in AppDelegate.m
[FIRMessaging messaging].delegate = self;
I need to handle push notification and that's done with a lower version of ios but in ios 11 never receive any push notification. I using Firebase Cloud Messaging. please, anyone has a solution then please share.
Please Check as
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Use Firebase library to configure APIs
FirebaseApp.configure()
self.registerForPushNotifications(application: application)
Messaging.messaging().delegate = self
if let token = InstanceID.instanceID().token() {
NSLog("FCM TOKEN : \(token)")
DataModel.sharedInstance.onSetUserFCMStringToken(FCM: token)
self.connectToFcm()
}
if launchOptions != nil {
//opened from a push notification when the app is closed
_ = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? [AnyHashable: Any] ?? [AnyHashable: Any]()
}
else {
//opened app without a push notification.
}
return true
}
#available(iOS 10, *)
extension AppDelegate: UNUserNotificationCenterDelegate {
// iOS10+, called when presenting notification in foreground
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
NSLog("[UserNotificationCenter] willPresentNotification: \(userInfo)")
//TODO: Handle foreground notification
completionHandler([.alert])
}
// iOS10+, called when received response (default open, dismiss or custom action) for a notification
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
NSLog("[UserNotificationCenter] didReceiveResponse: \(userInfo)")
//TODO: Handle background notification
completionHandler()
}}
extension AppDelegate : MessagingDelegate {
//MARK: FCM Token Refreshed
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
NSLog("[RemoteNotification] didRefreshRegistrationToken: \(fcmToken)")
}
// Receive data message on iOS 10 devices while app is in the foreground.
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
NSLog("remoteMessage: \(remoteMessage.appData)")
}}
//Register for push notification.
func registerForPushNotifications(application: UIApplication) {
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: [.alert,.sound]) { (granted, error) in
if error == nil{
DispatchQueue.main.async(execute: {
application.registerForRemoteNotifications()
})
}
}
}
else {
let settings = UIUserNotificationSettings(types: [.alert,.sound], categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
}
// Add observer for InstanceID token refresh callback.
NotificationCenter.default.addObserver(self, selector: #selector(self.tokenRefreshNotification), name: NSNotification.Name.InstanceIDTokenRefresh, object: nil)
}
#objc func tokenRefreshNotification(_ notification: Notification) {
print(#function)
if let refreshedToken = InstanceID.instanceID().token() {
NSLog("Notification: refresh token from FCM -> \(refreshedToken)")
}
// Connect to FCM since connection may have failed when attempted before having a token.
connectToFcm()
}
func connectToFcm() {
// Won't connect since there is no token
guard InstanceID.instanceID().token() != nil else {
NSLog("FCM: Token does not exist.")
return
}
Messaging.messaging().shouldEstablishDirectChannel = true
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
NSLog("Notification: Unable to register for remote notifications: \(error.localizedDescription)")
}
// This function is added here only for debugging purposes, and can be removed if swizzling is enabled.
// If swizzling is disabled then this function must be implemented so that the APNs token can be paired to the InstanceID token.
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
}
// iOS9, called when presenting notification in foreground
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
NSLog("didReceiveRemoteNotification for iOS9: \(userInfo)")
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
}
Problem seems to be with
FirebaseInstanceID Version less than 1.0.9
FirebaseInstanceID Version between 2.0.1 - 2.0.3
Set your pod file as below :
For Swift 2.3 and Xcode 8 : (FirebaseInstanceID v1.1.0 gets installed)
pod 'Firebase/Core', '3.8.0'
pod 'Firebase/Messaging'
For Swift 3 and Xcode 9 :
pod 'Firebase/Core'
pod 'Firebase/Messaging'
pod 'FirebaseInstanceID', "2.0.0
I didn't want to upgrade to FirebaseInstanceID 2.0.0 to fix the issue as I wanted use Swift 2.3 only
I had the same problem, the issue was I was missing my APN configuration in firebase console.