first of all environment is React native, I try to setup push notification in iOS following instruction from rnfirebase package here what step i do and I do testing on Real iPhone Device
create key
then add to firebase
add Google-service.plist and add setup following from firebase doc
and acivate capabillity
then I install pod package
run app got token
use token send on cloud messaging console
notification not delivered I didn't know what wrong because message also send from FCM and what happens on APNS where I get an error just confused
thank for advance
and also try by connecting directly with pusher
and also not received again
then try to use Onesignal with same certificate with Firebase is work even on the test message
The token you are using in Pusher doesn't look right. My tokens for remote notifications look like this.
I was just testing silent pushes, but the token would look similar for regular alerts. Here is the code I use to grab the token. My guess is that you are pushing a bad token up to FCM.
fileprivate func convertHexDataToString(_ data: Data) -> String {
var string: String = ""
for i in 0..<data.count {
string += String(format: "%02.2hhx", data[i] as CVarArg)
}
return string
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenString = convertHexDataToString(deviceToken)
#if DEBUG
print("APN sandbox token: '\(tokenString)'")
Messaging.messaging().setAPNSToken(deviceToken, type: .sandbox)
#else
print("APN prod token: '\(tokenString)'")
Messaging.messaging().setAPNSToken(deviceToken, type: .prod)
#endif
}
Related
I have a SwiftUI app and inside it's custom AppDelagte I get the FCM token and save it to my database. Which works.
But when the user registers and gets put to the main screen of the applcation, their FCM token isn't uploaded to the database until they restart the app and the AppDelagte messaging function is run again. So basically, when the user registers, the app will not function correctly until they restart the app.
I have tried to get and then send the FCM token as soon as they successfully register via:
Messaging.messaging().fcmToken
which returns an empty string, meaning it is only made after they re run the app delegate.
How do I get around this, and send the FCM token to their database profile as soon as they register?
You could store the fcmToken on a static property of the AppDelegate as soon as you get it and then access it whenever the user registers.
Add a static property to the app delegate:
class AppDelegate: UIResponder, UIApplicationDelegate {
static var fcmToken: String?
// when you get the token set it to the static property
Self.fcmToken = fcmToken
}
Then when you need the token simply access:
AppDelegate.fcmToken
You can use this method at any time to access the token instead of storing it.
Messaging.messaging().token { token, error in
if let error = error {
print("Error fetching FCM registration token: \(error)")
} else if let token = token {
print("FCM registration token: \(token)")
self.fcmRegTokenMessage.text = "Remote FCM registration token: \(token)"
}
}
https://firebase.google.com/docs/cloud-messaging/ios/client
I'm trying to integrate my Android and iOS native apps with Notification Hub.
For example, on iOS, as soon as I receive the deviceToken and if my user is already authenticated, I register directly with NotificationHub:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
log.debug("Received device token \(deviceToken.hexEncodedString()). Saving device token to user defaults.", "AppDelegate.didRegisterForRemoteNotificationsWithDeviceToken")
let defaults = UserDefaults.standard
defaults.set(deviceToken, forKey: UserNotificationDeviceTokenKey)
defaults.synchronize()
if let authenticatedUser = Session.shared.authenticatedUser {
log.debug("Trying to register device token \(deviceToken.hexEncodedString()) to user \(authenticatedUser.id) on notification hub with hub name \(String(describing: hubName)) and connection string \(String(describing: connectionString)). Notification hub null? \(notificationHub == nil)")
self.notificationHub?.registerNative(withDeviceToken: deviceToken, tags: Set<String>([authenticatedUser.id]), completion: { error in
if (error != nil) {
log.error("Error registering for notifications: \(error.debugDescription)", "AppDelegate.didRegisterForRemoteNotificationsWithDeviceToken");
} else {
log.debug("Successfully registered device token \(deviceToken.hexEncodedString()) for user with ID \(authenticatedUser.id) and email \(authenticatedUser.emailAddress)", "AppDelegate.didRegisterForRemoteNotificationsWithDeviceToken")
}
})
}
}
And whatever happens, I start by saving the device token to the user defaults so that when a user does log in, he can retrieve the deviceToken from user defaults and call the same registerNative method to create a registration associating this deviceToken with a tag that is the user's identifier:
func userDidSignIn(user: User) {
if let appDelegate = UIApplication.shared.delegate as? AppDelegate,
let deviceToken = UserDefaults.standard.data(forKey: UserNotificationDeviceTokenKey){
log.debug("Trying to register device token \(deviceToken.hexEncodedString()) to user \(user.id) on notification hub with hub name \(String(describing: appDelegate.hubName)) and connection string \(String(describing: appDelegate.connectionString)). Notification hub null? \(appDelegate.notificationHub == nil)")
appDelegate.notificationHub?.registerNative(withDeviceToken: deviceToken, tags: Set<String>([user.id]), completion: { error in
if (error != nil) {
log.error("Error registering for notifications: \(error.debugDescription)");
} else {
log.debug("Successfully registered device token \(deviceToken.hexEncodedString()) for user with ID \(user.id) (\(user.emailAddress)) who just logged in", context: "HTRootViewController.userDidSignIn")
}
})
} else {
log.warning("No device token found in settings.", "HTRootViewController.userDidSignIn")
}
}
I have all my logs remotely sent to Bugfender, which lets me check the logs for all the devices using this app installed in TestFlight, so I can see that all the registerNative's are successful:
Trying to register device token
0fea9a4d99ec37dc4f3ac252c35fa4e1617004fd14740973d80a7dfdaeacc857 to
user 77bfb1c6-b05a-440b-a7a0-71ae5a91bbb2 on notification hub with hub
name Optional("[my notification hub name]") and connection string
Optional("[my notification hub connection string]").
Notification hub null? false
Successfully registered device
token 0fea9a4d99ec37dc4f3ac252c35fa4e1617004fd14740973d80a7dfdaeacc857
for user with ID 77bfb1c6-b05a-440b-a7a0-71ae5a91bbb2
([my user's email]) who just logged in
But then, when I load the list of all the registrations using this .NET C# code:
public async Task<List<RegistrationDescription>> GetRegistrations()
{
var hub = NotificationHubClient.CreateClientFromConnectionString([my notification hub connection string], [my notification hub name]);
var result = await hub.GetAllRegistrationsAsync(1000);
return result.ToList();
}
I can see that some registrations are there, but others are nowhere to be found, even though they succeeded according to my mobile logs.
Does anyone know what else could be going on? What else can I check? Why else would registrations not be saved even though the call to registerNative seems to succeed?
EDIT: As a matter of fact, and after checking more precisely what is happening, the registration first appears in the list of registrations returned by Notification Hub, but as soon as we try to send a notification, it's as if Notification Hub could not reach the corresponding device token and deleted the registration altogether. Is there a way to see the logs of Notification Hub to see what is going on and why it decides to delete this registration?
I figured it out. It turns out it was working on my device because I ran the beta in debug mode, so it was getting its device token from the Sandbox APS environment, which matched the Sandbox endpoint configured in Notification Hub, but other users were using the Production APS environment configured in the archive build, so they got device tokens for a different environment and notification hub correctly identified as incorrect device tokens. Once we switched the Notification Hub to the production APNS endpoint, all the TestFlight users were able to receive notifications because their registrations stayed in Notification Hub. Now that does mean that my debug builds trying to use that environments won't receive notifications, but that's OK, that's why we have a different environment and Notification Hub for development purposes. So if anyone sees something similar, don't forget to double check your Notification Hub configuration matches the type of build your users are using, and don't forget that TestFlight builds are now production-type builds, same as App Store builds.
Been doing a lot of research on this issue, first my setup:
React-native: 0.61.5
react-native-firebase: 5.6.0
Firebase Messaging 6.15.0
My issue quite simple and straight forward though I do not seem to be able to find a clear way to resolve the issue.
I deployed version 4.2 of my app. Firebase Cloud Messaging (FCM) in iOS works just dandy. I then deployed 4.3 to TestFlight to begin testing. Installed 4.3 via TestFlight and FCM stopped working, no push notifications. If I delete the app and install 4.3 via TestFlight push notifications work again, the device is registered.
I can also reproduce this issue updating the installed version of my app from the App Store published latest, no surprise there.
I know that the InstanceId/device token is based on the app build+device so it makes sense that the token changes when the app Updates but my token is the same when I update from 4.2 to 4.3:
const fcmToken = await firebase.messaging().getToken(); //same whether 4.2 or 4.3
And yes firebase.messaging().getToken() is cached on initial creation.
So I am wired up to listen to token change events:
firebase.messaging().onTokenRefresh(async () => {
console.log('======onTokenRefresh=========');
AsyncStorage.removeItem(FCM_TOKEN_KEY);
await getToken();
});
That never seems to fire. I have even added a button to my app to try and force a new InstanceId and register with FCM after updating the version from TestFlight or the AppStore, this does not help:
export async function forceRefresh() {
console.log('================force a new registration!!!==========');
AsyncStorage.removeItem(FCM_TOKEN_KEY);
firebase.messaging().deleteToken();
firebase.iid().deleteToken();
registerForPushNotificationsAsync(true);
}
Nah, doesn't work.
So the moral of the story is, when I update the version of my app, my customers, whom's push notifications were working dandy, will no longer be registered for push notifications when they update their app to the next version.
References that might be leads I have been studying:
didRegisterForRemoteNotificationsWithDeviceToken called twice?
didRegisterForRemoteNotificationsWithDeviceToken is not getting called Swift 5, Xcode 10.2
https://firebase.googleblog.com/2017/01/debugging-firebase-cloud-messaging-on.html
https://github.com/firebase/firebase-ios-sdk/issues/2438
https://github.com/evollu/react-native-fcm/issues/1100
Firebase Cloud Messaging - Handling logout
Interesting on app update start, where push notifications will stop working because of the app update I see two different tokens, perhaps this first one is the APN token from Apple:
2020-01-17 18:48:09.371741-0800 native[4462:1287461] -[RNFirebaseMessaging messaging:didReceiveRegistrationToken:] [Line 86] Received new FCM token: eBBgznWj1FU:APA91bF8vTmpkwcojp4oDSKFzlPDp6ylEIe_WGNzu24SKHS6RR-3xPu2-cX-Qyc8rrMIQMvkCJftT9711ll1WdshBWS4iEpZ3XpiPeTynqM-nvDjpAUUUWJpfT5aeo6G_scDsN9iipwI
2020-01-17 18:48:09.378382-0800 native[4462:1287621] 6.15.0 - [Firebase/InstanceID][I-IID014012] Invalidating cached token for 255558254149 (*) due to token is no longer fresh.
Then a bit later my prior token from the previous version of the app where push notifications working is loaded I and see the work "default token" in the logs:
2020-01-17 18:48:09.987571-0800 native[4462:1287610] 6.15.0 - [Firebase/InstanceID][I-IID014001] Token fetch successful, token: dUY5psWDnkv2td1kB_t6Gs:APA91bEaREBt07CWiEyGvP4YAGjxmVQmF0IcXgef5XcvL5KWrHsqcxZZ8L9PqwGzKTPFGy6cdmuVXSvg6kDQjj-652jt5_jbbKMhUFTcam_-FeBp2vGZvBjaBd4aAOtQf1m48htQ8d6B, authorizedEntity: 255558254149, scope:*
2020-01-17 18:48:09.987764-0800 native[4462:1287461] -[RNFirebaseMessaging messaging:didReceiveRegistrationToken:] [Line 86] Received new FCM token: dUY5psWDnkv2td1kB_t6Gs:APA91bEaREBt07CWiEyGvP4YAGjxmVQmF0IcXgef5XcvL5KWrHsqcxZZ8L9PqwGzKTPFGy6cdmuVXSvg6kDQjj-652jt5_jbbKMhUFTcam_-FeBp2vGZvBjaBd4aAOtQf1m48htQ8d6B
2020-01-17 18:48:09.993088-0800 native[4462:1287610] 6.15.0 - [Firebase/InstanceID][I-IID003010] Successfully fetched default token.
2020-01-17 18:48:09.993755-0800 native[4462:1287610] 6.15.0 - [Firebase/InstanceID][I-IID003008] Got default token dUY5psWDnkv2td1kB_t6Gs:APA91bEaREBt07CWiEyGvP4YAGjxmVQmF0IcXgef5XcvL5KWrHsqcxZZ8L9PqwGzKTPFGy6cdmuVXSvg6kDQjj-652jt5_jbbKMhUFTcam_-FeBp2vGZvBjaBd4aAOtQf1m48htQ8d6B
As interesting, after deleting the current version app and installing the latest version (in previous log it was the update version) we can see the same process in reverse, first my current token is found and is considered no longer fresh:
messaging:didReceiveRegistrationToken:] [Line 86] Received new FCM token: dUY5psWDnkv2td1kB_t6Gs:APA91bEaREBt07CWiEyGvP4YAGjxmVQmF0IcXgef5XcvL5KWrHsqcxZZ8L9PqwGzKTPFGy6cdmuVXSvg6kDQjj-652jt5_jbbKMhUFTcam_-FeBp2vGZvBjaBd4aAOtQf1m48htQ8d6B
2020-01-17 19:03:06.651179-0800 native[4475:1291698] 6.15.0 - [Firebase/InstanceID][I-IID014012] Invalidating cached token for 255558254149 (*) due to token is no longer fresh.
Subsequently the new token is loaded and is considered the default token and my new install receives FCM notifications right away:
2020-01-17 19:03:07.997209-0800 native[4475:1291564] -[RNFirebaseMessaging messaging:didReceiveRegistrationToken:] [Line 86] Received new FCM token: ebz2ACPpBkg0kGsgs9yF7_:APA91bGErCaPMuLyRk-_BLZXUk8_U6FyxvKHbI0NPgddFWl_-nLZuCc6HbHg8kaLMDJiO7sHFS8THAuV132xgri8uQ9YV4g8zDXJySrKsSTNiDq9HcXpzUQXQlPy8bTaxZ3gyRxyCy3p
2020-01-17 19:03:08.018870-0800 native[4475:1291684] 6.15.0 - [Firebase/InstanceID][I-IID014001] Token fetch successful, token: ebz2ACPpBkg0kGsgs9yF7_:APA91bGErCaPMuLyRk-_BLZXUk8_U6FyxvKHbI0NPgddFWl_-nLZuCc6HbHg8kaLMDJiO7sHFS8THAuV132xgri8uQ9YV4g8zDXJySrKsSTNiDq9HcXpzUQXQlPy8bTaxZ3gyRxyCy3p, authorizedEntity: 255558254149, scope:*
2020-01-17 19:03:08.019018-0800 native[4475:1291684] 6.15.0 - [Firebase/InstanceID][I-IID003010] Successfully fetched default token.
2020-01-17 19:03:08.019065-0800 native[4475:1291684] 6.15.0 - [Firebase/InstanceID][I-IID003008] Got default token ebz2ACPpBkg0kGsgs9yF7_:APA91bGErCaPMuLyRk-_BLZXUk8_U6FyxvKHbI0NPgddFWl_-nLZuCc6HbHg8kaLMDJiO7sHFS8THAuV132xgri8uQ9YV4g8zDXJySrKsSTNiDq9HcXpzUQXQlPy8bTaxZ3gyRxyCy3p
Just found this interest statement in the logs:
APNS device token not set before retrieving FCM Token for Sender ID '255558254149'. Notifications to this FCM Token will not be delivered over APNS.Be sure to re-retrieve the FCM token once the APNS device token is set.
It is hard to believe this is happening so consistently but it does certainly seem to be the case, any help would be greatly appreciated.
Well it ended up being a race condition, I found a great hint here
Seems with react-native-firebase Firebase.messaging().getToken() will not always return the latest token - use onTokenRefresh instead. My app was saving and using an old token and not updating a new one - very small race condition.
Simply use Firebase.messaging.onTokenRefresh() as a source of truth to avoid issues with migrating apps. Also to be sure you get a token that works. You may want to delete your token on a migration such as this with v4 -> await Firebase.iid().deleteToken(), or v5 (Firebase.messaging().deleteToken(). Then rely onTokenRefresh to send you a new one to send to your server.
Now firebase.messaging().deleteToken() mentioned in quote above isn't "good enough" to cause a a tokenRefresh when there is an app update from TestFlight or the Apple App Store.
I had to call the asynchronous (everything is asynchronous when it comes to this problem is the rule of thumb):
firebase.iid().delete();
This React Native Firebase api method deletes the InstanceId which is really what Firebase Cloud Messaging (FCM) is using for the token.
This will fire the onTokenRefresh. So what I did is I am checking the version and build number of the app and storing this in the app user data (NSDefaults for iOS), I check if this version and build exists, if it doesn't I "flush" the device token. That way this only happens once.
I am going to add my code in the hopes it helps others with this problem, essentially, from my research, using React Native Firebase 5.x this is what you have to do to maintain seamless push notification registration with Firebase Cloud Messaging across iOS app updates:
In your App.js add the following:
configureFirebaseCloudMessaging = async () => {
//wire up Firebase Cloud Messaging onTokenRefresh listener
this.fcmOnTokenRefreshUnsubscribe = await firebase.messaging().onTokenRefresh(async fcmToken => {
console.log('*********************** onTokenRefresh *****************');
//this is callBack called typically sometime in the future but can be call with app loaded but user not logged in
//check for that case and exit if there is no accessToken to call APIs
const accessToken = await AsyncStorage.getItem('access-token');
if (!accessToken) {
console.log('************** user is not logged in exit onTokenRefresh do not register device ************');
return;
}
await this.registerDevice(fcmToken, BASE_URL);
await AsyncStorage.setItem('fcmToken', fcmToken);
firebase.crashlytics().log(`flushed new fcmToken: ${fcmToken}`);
console.log('***************** success account updated with latest token **************');
});
//Firebase Cloud Messaging time
await this.requestPushPermission();
await this.checkFlushv();
}
checkFlushv = async () => {
let FLUSHV = `${DeviceInfo.getVersion()}-build-${DeviceInfo.getBuildNumber()}`;
const flush = await AsyncStorage.getItem(FLUSHV);
console.log('======= checking FLUSHV=========', flush);
if (flush) {
console.log('***** device token already been flushed ******');
return;
}
const accessToken = await AsyncStorage.getItem('access-token');
console.log('flushy access token:', accessToken);
if (!accessToken) {
console.log('******** user is not logged in do not flush ************');
return;
}
//force push notifications, this will fire onTokenRefresh callback
await firebase.iid().delete();
//iterate all keys and remove other builds to keep tidy and TestFlighters possibly going up and back down build versions for testing
const keys = await AsyncStorage.getAllKeys();
const buildKeys = keys.filter(key => {
return key.indexOf('build') !== -1;
});
await AsyncStorage.multiRemove(buildKeys);
//add current build key so no more flushy
await AsyncStorage.setItem(FLUSHV, FLUSHV);
console.log(`=================FLUSHV clear: ${FLUSHV}===================`)
}
registerDevice = async (token, baseUrl) => {
console.log(`******** registerDevice token: ${token}, baseUrl: ${baseUrl}`);
let data = {
device: 'firebase',
token: token
}
//register token with account
axios.post(`${baseUrl}/myapi/register_device`, data)
.then(response => {
return {}
})
.catch(err => {
console.log(err)
return {}
})
}
And then in your App.js:
async componentDidUpdate() {
//a new version of the app could be loaded post/after App.componentDidMount
await this.checkFlushv();
}
async componentWillUnmount() {
console.log('app componentWillUnmount');
this.fcmOnTokenRefreshUnsubscribe(); //not really sure unsubcribe is needed but keeping tidy
this.fcmOnTokenRefreshUnsubscribe = null;
}
async componentDidMount() {
await this.configureFirebaseCloudMessaging();
}
I spent a lot of time before the found a solution.
So, if you call firebase.iid().delete() in iOS you need to register your new token in APNs. I didn't see this in react native firebase documentation, just found in lib's types
await firebase.messaging().ios.registerForRemoteNotifications()
Please, call this method after generate new token
I am trying to figure out how to perform e2e test via firebase test lab for iOS that allow to check passwordless authentication flow, which essentially should do following
Enters email within my app
Firebase sends auth link to such email
Somehow I need to be logged into such email somewhere in firebases test device, I assume either in mail app, or gmail?
I need to know when new email arrives and open it
Once I opened an email I need to click on auth link
This should bring me back into the app and authenticate
My biggest issue at the moment is figuring out steps that happen outside my app i.e. how can I prepare for this test and log in under my email address (is it better to log into gmail in safari for example or somehow add this acc to apples mail app?).
Testing email
In my experience, testing your own code to see if an email was sent is not straightforward beyond checking if the method call you expect to send the email has happened.
Add on top of that using Firebase, which does not expose its underlying email send code, and that looks like a challenge to me.
In terms of testing, I suggest you assert that your method calls to send email happened or that the relevant code path was reached. In Firebase web, this looks like:
firebase.auth().sendSignInLinkToEmail(email, actionCodeSettings)
.then(function() {
// The link was successfully sent. Inform the user.
// Save the email locally so you don't need to ask the user for it again
// if they open the link on the same device.
window.localStorage.setItem('emailForSignIn', email);
// TODO save email to something accessible in your iOS tests
// TODO In your tests, confirm that email was saved after it was sent
})
.catch(function(error) {
// Some error occurred, you can inspect the code: error.code
});
See: https://firebase.google.com/docs/auth/web/email-link-auth#send_an_authentication_link_to_the_users_email_address
Another option:
You could setup a test user with an email address on a mail server that you manage, and check for incoming mail for that test user with your own custom mail reading code.
I would use Firebase Admin tools for this: https://firebase.google.com/docs/auth/admin/manage-users#create_a_user
I think you should first take a look at firebase docs for iOS on how to create dynamic links that you can use for email auth.
https://firebase.google.com/docs/auth/ios/email-link-auth
https://firebase.google.com/docs/auth/ios/passing-state-in-email-actions#configuring_firebase_dynamic_links
After you're done with those two check out the following code:
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
// [END old_delegate]
if handlePasswordlessSignIn(withURL: url) {
return true
}
}
func handlePasswordlessSignIn(withURL url: URL) -> Bool {
let link = url.absoluteString
// [START is_signin_link]
if Auth.auth().isSignIn(withEmailLink: link) {
// [END is_signin_link]
UserDefaults.standard.set(link, forKey: "Link")
(window?.rootViewController as? UINavigationController)?.popToRootViewController(animated: false)
window?.rootViewController?.children[0].performSegue(withIdentifier: "passwordless", sender: nil)
return true
}
return false
}
This is just an example on how you can handle the deep link in your app after the user taps the link. The delegate method
func application(_ application: UIApplication, open url: URL,
sourceApplication: String?, annotation: Any) -> Bool
in AppDelegate is used for all deep links into an app. You could set up for example your own scheme that your app conforms to. And you can send url type links with your custom scheme into your app from the browser for example.
To do this just Open Xcode, go to Project Settings -> Info, and add inside ‘The URL Types” section a new URL scheme. Add something of the sort of com.myApp in order for it to be as unizue as possible. Then you can just type into a browser com.myApp://main and handle that in the appDelegate.
Edit: It says so in their docs that you can present a prompt inside the app for the user to input the email. Where the user opens his email from isn't really your concern as long as your dynamic link is set up properly.
This is my code:
import FirebaseAuth
class AuthPhoneNum {
static func getPhoneNum(phoneNumber: String) {
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber) { (verificationID, error) in
if let error = error {
print(error)
return
}
UserDefaults.standard.set(verificationID, forKey: "authVerificationID")
}
}
static func verify(verificationCode: String?) {
guard let verificationID = UserDefaults.standard.string(forKey: "authVerificationID") else { return }
if verificationCode != nil {
let credential = PhoneAuthProvider.provider().credential(
withVerificationID: verificationID,
verificationCode: verificationCode!)
Auth.auth().signIn(with: credential) { (user, error) in
if let error = error {
print(error)
return
}
}
} else {
print("No verification code")
}
}
}
This is what the console prints out:
Error Domain=FIRAuthErrorDomain Code=17048 "Invalid token."
UserInfo={NSLocalizedDescription=Invalid token.,
error_name=INVALID_APP_CREDENTIAL}
What am I doing wrong? Thanks
I was also experiencing this problem. Checked the following:
Correct bundle Id
Correct Google-Info.plist
Correct aps-environment value
Correct APNS token type when calling auth.setAPNStoken (.unknown for auto detect)
Nothing helped until in Firebase app settings I uploaded the APNS authentication key (p8) instead of certificates - I used those certificates before for push notifications only and everything was working fine but for phone number notifications something went wrong.
It is most likely that you need to upload an .p8 Key file
(I have an Enterprise account but same thing for developer)
In Apple Developer Account:
All Keys
Create New Key (+)
Type in Global name for all of your apps
Checkbox next to Apple Push Notifications service (APNs)
Download your p8 file
Upload to firebase dashboard
First regenerates APNS key and upload in firebase for cloud messaging
1) Import Firebase and FirebaseAuth
import Firebase
import FirebaseAuth
2) In didFinishLaunchingWithOptions Configure firebase.
FirebaseApp.configure()
3) Write these two func in AppDelegate.
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let firebaseAuth = Auth.auth()
firebaseAuth.setAPNSToken(deviceToken, type: AuthAPNSTokenType.prod)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
let firebaseAuth = Auth.auth()
if (firebaseAuth.canHandleNotification(userInfo)){
print(userInfo)
return
}
}
Very Important note : uthAPNSTokenType set correctly for [sandbox / production] or set for common .unknown
In my case it was the apns token type that was wrong:
Auth.auth().setAPNSToken(deviceToken, type: AuthAPNSTokenType.prod)
should have been:
Auth.auth().setAPNSToken(deviceToken, type: AuthAPNSTokenType.sandbox)
In my case, the problem was an incorrect bundle id in the iOS app, in the firebase project settings (Project settings -> General -> Your apps).
I hope this helps anyone overlooking the same detail.
same problem questions have been before on SO. so would like to tell you setup all pre-require step before run code.
Pre-Require Steps:
Register bundle id on Developer account and enable notifications for
bundle id.
Register same bundle id on firebase console setting page and create
app, download Google-Info.plist file, make sure name should be same.
Upload Push certificates on firebase console for sandbox as well as
development.
follow this below link for code implementation.
setup code for Firebase Auth
Make sure that it is APNs that you are selected under Key Services. The number of APNs certificates per developer account is limited to 2. So if you already had 2 certificates before, there is a chance that you are created the certificate by checking DeviceCheck instead of APNs.
For any one else who double checked the above and still have issues, don't forget to add your team ID and App Id in your ios config file.
And, don't forget to download it again, and replace your old one with the updated one.
If you have tried adding the APNs key (p8) in your Firebase console and also checked for the Correct bundle Id and Correct Google-Info.plist.
And still the issue persists
Do check if you have "Push Notifications" enabled and "Remote notifications" selected in "Signing and capabilities" in Xcode->Runner but are not actually using firebase messaging
Then care to uncheck "Remote notifications" from "Signing and capabilities" and remove "Push Notifications" in Xcode->Runner.
In my case this was the issue
I faced same problem when I want send OTP and get notifications, I created APN key on apple developer console then added it to firebase after that everything got well:
If you did everything right as per the documentation. Try one thing.
Paste this line in AppDelegate.m under,
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[[FIRAuth auth] setAPNSToken:deviceToken type:FIRAuthAPNSTokenTypeProd];