Error invalidregistration fcm

I am currently trying to send a PushNotification to a Device Group using FCM with the help of Firebase Cloud Functions but once the notification is sent, it returns with code 200 but with failure :

I am currently trying to send a PushNotification to a Device Group using FCM with the help of Firebase Cloud Functions but once the notification is sent, it returns with code 200 but with failure :

SUCCESS response= {
multicast_id: 8834986220110966000,
success: 0,
failure: 1,
canonical_ids: 0,
results: [ { error: 'InvalidRegistration' } ] 
}

Here is the code I am using to send this notification… what am I missing?

const options = {
    method: 'POST',
    uri: 'https://fcm.googleapis.com/fcm/send',
    headers: {
       'Authorization': 'key=' + serverKey,
    },
    body: {
       to: groupId,
       data: {
        subject: message
       },
       notification: {
         title: title,
         body: body,
         badge: 1,
        },
       content_available: true
    },
    json: true
};

return rqstProm(options)
    .then((parsedBody) => {
        console.log('SUCCESS response=', parsedBody);
    })
    .catch((err) => {
        console.log('FAILED err=', err);
    });

Where JSON values title, body, subject, message are String

Comments

@umangshuMTX

Issue

Getting InvalidRegistration while sending fcm message.

On the App side, it is configured as per the setup guide.

const registerForNotification = async () => {
  // await requestNotifications(['alert', 'badge', 'sound']);
  await messaging().registerDeviceForRemoteMessages();
};

const requestForNotificationPermission = async () => {
  const granted = await messaging().requestPermission();

  if (granted) {
    console.log('User granted messaging permissions!');
  } else {
    console.log('User declined messaging permissions :(');
  }
};

const getDeviceToken = async () => {
  await requestForNotificationPermission();
  const result = await registerForNotification();
  console.log(result);
  // await messaging().deleteToken();
  const fcmToken = await messaging().getToken();
  return fcmToken;
};

Above give us the fcm token which we are sending to the Firestore and a could function send the fcm message. But sometimes it works and sometimes it sends InvalidRegistration.

{
    "multicast_id": 8080343189913405045,
    "success": 0,
    "failure": 1,
    "canonical_ids": 0,
    "results": [
        {
            "error": "InvalidRegistration"
        }
    ]
}

Project Files

Javascript

Click To Expand

package.json:

{
  "react": "16.9.0",
  "react-native": "0.61.5",
  "@react-native-firebase/app": "^6.4.0",
  "@react-native-firebase/auth": "^6.4.0",
  "@react-native-firebase/functions": "^6.4.0",
  "@react-native-firebase/messaging": "^6.4.0",
  
}

firebase.json for react-native-firebase v6:

iOS

Click To Expand

ios/Podfile:

  • I’m not using Pods
  • I’m using Pods and my Podfile looks like:

AppDelegate.m:


Android

Click To Expand

Have you converted to AndroidX?

  • my application is an AndroidX application?
  • I am using android/gradle.settings jetifier=true for Android compatibility?
  • I am using the NPM package jetifier for react-native compatibility?

android/build.gradle:

android/app/build.gradle:

android/settings.gradle:

MainApplication.java:

AndroidManifest.xml:


Environment

Click To Expand

react-native info output:

  • Platform that you’re experiencing the issue on:
    • iOS
    • Android
    • iOS but have not tested behavior on Android
    • Android but have not tested behavior on iOS
    • Both
  • react-native-firebase version you’re using that has this issue:
    • e.g. 5.4.3
  • Firebase module(s) you’re using that has the issue:
    • e.g. Instance ID
  • Are you using TypeScript?
    • Y/N & VERSION

  • 👉 Check out React Native Firebase and Invertase on Twitter for updates on the library.

@mikehardy

You should try the @next tag to make sure you get the fixes from #3339 — many users have reported success with it, no current known problems — install that and re-test and please report back?

@romainmarchand

@mikehardy

Hi! This issue is still actual on iOS for versions 6.4.1-alpha.0 (@next) and 6.7.1. I don’t have any issue with Android.

I struggled with this these days and noticed it happens as soon as the auth module is installed (works perfectly fine when auth module is not installed). The issue happens even without any import and use of the auth module, just installing it.

Description: the messaging device token seems to get randomly unregistered, most likely when closing the app by swiping it away. It happens around 50% of the time when closing app. Then the server app (nodejs with ‘firebase-admin’ lib for me) fails to send its next message with error:

errorInfo: {
      code: 'messaging/invalid-registration-token',
      message: 'Invalid registration token provided. Make sure it matches the registration token the client app receives from registering with FCM.'
}

and all following messages with:

 errorInfo: {
      code: 'messaging/registration-token-not-registered',
      message: 'The provided registration token is not registered. A previously valid registration token can be unregistered for a variety of reasons. See the error documentation for more details. Remove this registration token and stop using it to send messages.'
}

(I am 100% confident there is no mistake with the token on server side — it’s exactly the same token and it suddenly stops working)
I believe the first error is different than all following errors because the first error might cause «APNS Feedback Service to report the APNS token as invalid», as per the docs (at messaging/registration-token-not-registered):
https://firebase.google.com/docs/cloud-messaging/send-message#admin

Tested with :

  • a fresh new simple project created for the purpose of debugging this issue.
  • iPhone SE device (the old one)

index.js:

/**
 * @format
 */

import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
import notifee, { Importance } from '@notifee/react-native';
import messaging from '@react-native-firebase/messaging';

function onMessageReceived(message) {
  notifee.displayNotification(JSON.parse(message.data.notifee));
}

messaging().onMessage(onMessageReceived);
messaging().setBackgroundMessageHandler(onMessageReceived);

async function onAppBootstrap() {
  await messaging().registerDeviceForRemoteMessages();

  const channelId = await notifee.createChannel({
    id: 'default',
    name: 'Default Channel',
    importance: Importance.HIGH,
  });
}

notifee.onBackgroundEvent(async ({ type, detail }) => {
  const { notification, pressAction } = detail;
	// do nothing for now
});

onAppBootstrap();

AppRegistry.registerComponent(appName, () => App);

Unfortunatly its making messaging module quite unsuable for iOS in my case. If you have any suggestion or need more info I’m here.

@Ehesp

@romainmarchand

Hi, so I tried setting up onTokenRefresh but I get an error everytime it’s called, on both iOS and Android. The same error as reported in this issue : #3556

onTokenRefresh seems to be called at the first launch of the app, and then each time the messaging token is unregistered, e.g :
1 — Lauching the app.
2 — Crash due to onTokenRefresh.
3 — Launching the app.
4 — Foreground Messaging works well.
5 — Putting the app in background without closing.
6 — Background Messaging works well.
7 — Closing the app.
8 — Background messaging randomly continue working OR stop working.
9 — If it stopped working and I relaunch the app : Crash due to onTokenRefresh.

I made a public repo if you want to check my complete code, I only removed GoogleService-Info.plist and notifee.config.json:
https://github.com/romainmarchand/rnfmessaging-test

@AnhVu23

Do we have any updates on this issue? I have the same issue with @romainmarchand.

@dan-arkhipov

We are getting same issue here, any update on that?

@rm167

@AnhVu23 @dan-arkhipov
On what device(s) does this issue occur for you guys? For me it is an old iPhone SE… I wonder if this issue also happens on recent iPhones…

(from @romainmarchand)

@AnhVu23

@rm167 We have issues with iPhone X and XR. After updating to newest firebase version, the function onTokenRefresh seems to work, but I sometimes get the error (like 10% of total tests).

@romainmarchand

Ok, I guess it can occur on any kind of iPhone then. I am still having the invalid registration error as well for last versions:
@react-native-firebase/app: 7.0.1
@react-native-firebase/auth: 7.0.2
@react-native-firebase/messaging: 7.0.1

@hiren2728

I am testing on iPhone SE (iOS 13.4) and having an invalid registration error for the latest version.
«@react-native-firebase/app»: «^7.0.1»,
«@react-native-firebase/auth»: «^7.0.2»,
«@react-native-firebase/messaging»: «^7.0.1»,
On iOS, Its work for a couple of minutes and getting notification but suddenly it’s throwing error in cloud function for token which was working minute ago.

@dan-arkhipov

@mikehardy by any chance you know if this issue could be prioritized or suggest a workaround in the meantime? This seems like it is blocking quite a lot of people now.

@mikehardy

Sorry — I have no say in priorities other than when I go to fix things that directly affect me, and this one hasn’t (yet) so I haven’t put any effort into it

@dan-arkhipov

@mikehardy we are happy to have a look, however we never had experience contributing before. Could you please guide us where do we start to look in order to tackle this problem effectively?

@mikehardy

I think the best way to start is probably just to assume that all the code in node_modules/@react-native-firebase/* is your code too. You can go in there and instrument all you want, add debug statements all you want, breakpoints etc. So I’d take all the parts of code in there that wrap upstream SDK statements and at minimum I’d add log statements that show the current state of all objects going in to and coming out of the API calls to make sure things matched expectations

Note that ‘patch-package’ can be very useful for this as it can persist your Obj-C changes into git and they can be reproduced across all developer and CI machines so things are stable and you don’t have some magic troubleshooting machine where the special code is

@dan-arkhipov

@mikehardy thanks for that, given you are well familiar with the product, could you please direct us where exactly we should start looking in the code at the first place. We think that something invalidates the token or when token gets refreshed our .onTokenRefresh method is not firing.

@mikehardy

Unfortunately I’m not familiar with this area at all — sorry, I think @Ehesp was the last one in there during the big sweep that was #3339

@romainmarchand

@dan-arkhipov
It’s most likely something invalidating the token, because in normal behavior token are not refreshed very often.

Yesterday I looked into Auth module’s index.js file (https://github.com/invertase/react-native-firebase/blob/master/packages/auth/lib/index.js) and noticed that the token wasn’t unregistered anymore when commenting out some lines (but background messaging was not working either…), but the thing is that debugging iOS is a real pain for me (because I don’t actually own a mac: I just use a slow remote mac, and I have to archive at every build, so it take’s almost 1 hour and I can’t get my real phone’s logs). So I wasn’t able to precisely find which part of the code is causing the issue and gave up for now. But if your mac setup is better than mine, maybe you could start by commenting out stuff in this file (like event listeners or other files imports). Just a suggestion though, I don’t know much about how the library works…

There’s also this file from messaging module, with a reference to Auth module at line 103 : https://github.com/invertase/react-native-firebase/blob/master/packages/messaging/ios/RNFBMessaging/RNFBMessaging%2BAppDelegate.m

I wonder if some part of messaging is handled by Auth module instead of Messaging module (as soon as Auth module is installed). If it’s the case, it might be because of the phone number authentication process, that uses silent notifications. But again, just wild thoughts..

@dan-arkhipov

@romainmarchand do you know if there is an official process in iOS to invalidate a token? I wonder if we can reverse engineer it by finding a method that does the invalidation and work backwards.

I can try to debug that and post here my findings here. Please feel free to suggest a few more things I should try to do.

@romainmarchand

@stale

Hello 👋, to help manage issues we automatically close stale issues.
This issue has been automatically marked as stale because it has not had activity for quite some time. Has this issue been fixed, or does it still require the community’s attention?

This issue will be closed in 15 days if no further activity occurs.
Thank you for your contributions.

@stale
stale
bot

added
the

Type: Stale

Issue has become stale — automatically added by Stale bot

label

Jun 17, 2020

@roni-castro

I am having the same problem on iOS. When a token is generated it works fine, but when I close/reopen the app several times and send push during this process, it gets a previous token but for some reason it is invalid, even though it is returned by the messaging().getToken(). After trying to open/close the app a few times I get a new token, but it takes like 1 — 3 minutes, and during this period no push is received because of the InvalidRegistration or Not registered error and the fact the device does not have any valid token.
It seems like the getToken returns an invalid token while it’s generating a new one.

This almost always happens in this flow, and on this order:

-Push sent correctly (First request):

valid token

-InvalidRegistration Error (Second request, after closing and reopening the app a few times and opening it though notification)

InvalidRegistration

-Not registered Error (Third request made, just after the second one)

Captura de Tela 2020-06-20 às 01 27 48

From now on, all requests will return NotRegistered and no push is received

After some action of close/open the app, a new token is generated and returned by the messaging().getToken() and the flow mentioned above happens all again.

Observations:

  • I am using this lib with notifee with a license on release mode.
  • The APNsToken returned by the messaging().getAPNSToken() never changed during several tests, while the FCMToken have refreshed more than three times. If I don’t send any push notification the fcm token does not expires even doing a lot of close/open action. It just expired for me when I close/open the app and receives a notification between these actions.
  • I don’t know if it is related to this problem, but during the tests the FCM server returned InternalServerError a few times, but the problem also happened when I received zero InternalServerError:

Captura de Tela 2020-06-20 às 01 45 55

Captura de Tela 2020-06-20 às 01 46 28

@stale
stale
bot

removed
the

Type: Stale

Issue has become stale — automatically added by Stale bot

label

Jun 20, 2020

@roni-castro

Apparently this problem just happen on iOS if I am running on the release scheme of XCode. I released a new AdHoc version on AppCenter and the app stopped having the refresh token problem, maybe is something related to the Metro Bundler of RN or something related to the APNs key, I don’t know… Apple stuff is just terrible to debug since it existence.

@devpascoe

I am facing this on iOS only, android is fine. Worked without issue in the 5x days, followed upgrade paths to 6x and running into this.
I use the firebase console to test. I can send to the iOS device for a while, then it stops receiving. If i send a push via firebaseadmin-sdk i get the registration-token-not-registered error.
Just seems to drop off after a while. And i have also implemented the token refresh handler.

For now i am trying what @romainmarchand suggested and removing the auth module to see if that yields any result. So far initial pushes work. Will exit the app and periodically test throughout the day. fingers crossed we can narrow down an area to focus on to resolve this.

@devpascoe

Update from me, after 2 days with the auth module omitted as per @romainmarchand suggested i am not receiving those fcm dropouts and the device gets every push note. I’ll give it another day then will try re-adding auth again to prove that is where an issue may lie.

@dan-arkhipov

Hey @devpascoe thank you very much for your input. Could you please let us know more what changes have you done and which files you have commented out? Does it have effect on authentication?

  • Your firebase version
  • File names you have changed
  • Do you use firebase auth (phone, email)

Thank you

@romainmarchand

I am not sure why but it seems to work fine for me now. I choose another type of distribution for the archive, as @roni-castro suggested. I used to choose «Development — Distribute to members of your team.» (signed with development certificate). Now I distribute with App Store Connect (distribution certificate) and I test with «Test Flight», and the issue doesn’t occur anymore.
I also updated react-native-firebase :
react-native-firebase/app: 7.2.1
react-native-firebase/auth: 8.0.6
react-native-firebase/messaging: 7.1.6

@CatalinVoss

Also seeing nightmare-ish inconsistency. This only happens for me on our app center build. Never locally, in debug mode.

  • On initial login and first request, we get provided an invalid push token.

    • First token gets provided after push approve
    • The first message we send (but only first) fails w an invalid argument error; super odd
    • Subsequent messages fail with «token not registered»
  • On second app open, new token gets requested and everything work out.

@stale

Hello 👋, to help manage issues we automatically close stale issues.
This issue has been automatically marked as stale because it has not had activity for quite some time. Has this issue been fixed, or does it still require the community’s attention?

This issue will be closed in 15 days if no further activity occurs.
Thank you for your contributions.

@stale
stale
bot

added
the

Type: Stale

Issue has become stale — automatically added by Stale bot

label

Aug 8, 2020

@stale

Closing this issue after a prolonged period of inactivity. If this is still present in the latest release, please feel free to create a new issue with up-to-date information.

@lestarcdog

Happened consistantly that after the first initial iOS notification was received that the token become invalid.
We have distributed the .apk with the development certs build within XCode

Publishing it on testflight with the production cert the notifications were received everytime.
(Same device same code, firebase auth module is included)

@dooleyb1

This is currently happening to our production app with "react-native-firebase": "^5.5.5". Just recently finished a migration to the following more up to date versions which I hope will resolve the issue:

        "@react-native-firebase/analytics": "^7.6.4",
        "@react-native-firebase/app": "^8.4.3",
        "@react-native-firebase/auth": "^9.2.3",
        "@react-native-firebase/crashlytics": "8.3.0",
        "@react-native-firebase/messaging": "^7.8.6",
        "@react-native-firebase/remote-config": "^9.0.5",

This is affecting a large number of our users fcmTokens. Ran a dryRun test for notifications to all fcmTokens in our database and got the following results:

{ success: 8457, error: 5459 }

{
  'messaging/registration-token-not-registered': 5458,
  'messaging/invalid-registration-token': 1
}

@romainmarchand did you manage to get anywhere with the issue you were encountering?

@romainmarchand

Hi @dooleyb1, I don’t work on this anymore, but after my last message this issue didn’t occur again for me (using App Store Connect).

@freerider7777

@dooleyb1

@dooleyb1 Is the issue resolved?

Not particularly, I’ve decided to just presume that these users with registration-token-not-registered have uninstalled the app and as a result their fcmToken has been unregistered. Not 100% on this though.

@anujraghuvanshi

@IngyuTae

Try to remove @react-native-firebase/analytics. I think there’s a race condition issue between analytics and messaging modules. (don’t forget to uninstall the pod as well after removing the package)

@stackcru-tech

i am still receiving this , can anyone please help me?
my versions
«@react-native-firebase/app»: «^6.7.1»,
«@react-native-firebase/auth»: «^6.7.1»,
«@react-native-firebase/messaging»: «^7.0.1»,
Error: ‘{«multicast_id»:xxxxxxx,»success»:0,»failure»:1,»canonical_ids»:0,»results»:[{«error»:»NotRegistered»}]}’

@mikehardy

@stackcru-tech the first step to receiving help is to make sure you’re on current stable versions, there is no telling how many issues have been found and resolved between your versions and v11.4.1 (current stable)

But the upgrade process itself isn’t that hard! check the changelogs of the app auth and messaging packages for breaking changes until we hit v10, then all the changelog notes are in the main changelog — and there really aren’t that many changes, we are just really strict on making a major version if there is any breaking change at all — https://invertase.io/blog/react-native-firebase-versioning

@stackcru-tech

@mikehardy i am upgrading the versions to the latest stable version, 11.4.1
now i am facing this issue
{ [Error: [messaging/unknown] FIS_AUTH_ERROR] whenever i am getting the token
Here is my code
await messaging().registerDeviceForRemoteMessages();
await messaging().registerDeviceForRemoteMessages();
const token = await messaging().getToken();
i am facing this in ANDROID.
i had also try
implementation «com.google.firebase:firebase-messaging:20.1.0»
but still facing the same issue

@mikehardy

Probably need fresh Google plist and json coming from the versions you had, also enable devicecheck API (check firebase android auth docs)

@stackcru-tech

@mikehardy I had done this but still facing the same issue.

@mikehardy

You may want to open a new issue with full details vs posting on an old one but I can attest 100% that it works. The module works. So you have something project-specific and it will likely then not get a huge amount of priority as it will not result in any change in the module.

@stackcru-tech

can you please let me now why this issue occurs?

@stackcru-tech

@mikehardy i am also facing this, i had check all the logs in abd

Firebase Installations Service is unavailable. Please try again later.

@mikehardy

@stackcru-tech I can’t tell you why it is happening for your project, no. I can say that your versions were old enough you should look at it almost as a completely fresh integration and re-read the docs from that perspective. I also encourage you to try a fresh playground / toy app as a proof of concept it works, and I have a script that generates a full example skeleton so you may do so easily https://github.com/mikehardy/rnfbdemo/blob/master/make-demo.sh

I’m sorry you’re having a difficult time with the upgrade, I know that is frustrating. But something is wrong with your project from the perspective of current firebase native libraries and you’ll just have to slowly work through things to figure out what

@RajeshSFS

Happened consistantly that after the first initial iOS notification was received that the token become invalid.
We have distributed the .apk with the development certs build within XCode

Publishing it on testflight with the production cert the notifications were received everytime.
(Same device same code, firebase auth module is included)

Can anyone explain, why it is working in production build and not development build?

Here are configuration at my side:
"@react-native-firebase/admob": "^11.4.1"
"@react-native-firebase/app": "^11.4.1"
"@react-native-firebase/dynamic-links": "^11.4.1"
"@react-native-firebase/messaging": "^11.4.1"

React native: 0.63.3
Xcode: 12.2
ios devices os: 14.6, 14.2

although it is working fine in testflight, but still want to know, if we missed any configuration, that’s why it is not working in development builds.

@suretarget

Happened consistantly that after the first initial iOS notification was received that the token become invalid.
We have distributed the .apk with the development certs build within XCode

Publishing it on testflight with the production cert the notifications were received everytime.
(Same device same code, firebase auth module is included)

I have the same issue “token become invalid” after first time received notification but after uninstall @react-native-firebase/analytics every working fine. If I’m not mistaken there is an open issue regarding this problem.

@cmg-sovann

I am having the same problem on iOS. When a token is generated it works fine, but when I close/reopen the app several times and send push during this process, it gets a previous token but for some reason it is invalid, even though it is returned by the messaging().getToken(). After trying to open/close the app a few times I get a new token, but it takes like 1 — 3 minutes, and during this period no push is received because of the InvalidRegistration or Not registered error and the fact the device does not have any valid token. It seems like the getToken returns an invalid token while it’s generating a new one.

This almost always happens in this flow, and on this order:

-Push sent correctly (First request):

valid token

-InvalidRegistration Error (Second request, after closing and reopening the app a few times and opening it though notification)

InvalidRegistration

-Not registered Error (Third request made, just after the second one)

Captura de Tela 2020-06-20 às 01 27 48

From now on, all requests will return NotRegistered and no push is received

After some action of close/open the app, a new token is generated and returned by the messaging().getToken() and the flow mentioned above happens all again.

Observations:

  • I am using this lib with notifee with a license on release mode.
  • The APNsToken returned by the messaging().getAPNSToken() never changed during several tests, while the FCMToken have refreshed more than three times. If I don’t send any push notification the fcm token does not expires even doing a lot of close/open action. It just expired for me when I close/open the app and receives a notification between these actions.
  • I don’t know if it is related to this problem, but during the tests the FCM server returned InternalServerError a few times, but the problem also happened when I received zero InternalServerError:

Captura de Tela 2020-06-20 às 01 45 55
Captura de Tela 2020-06-20 às 01 46 28

@roni-castro Have you found solution for this issues?

January 31, 2017

Debugging Firebase Cloud Messaging is one of the most common Firebase-on-iOS questions I see on StackOverflow. And so in an effort to garner as many StackOverflow points as I can (oh, yeah, and to educate the developer community), I thought it might be helpful to write up a full debugging guide on what to do when you can’t seem to get Firebase Cloud Messaging (FCM) working on your iOS device. First off, I’d recommend taking a moment to watch our Understanding FCM on iOS video. It’ll give you a better idea of what’s going on underneath the hood, which is always useful when you’re trying to debug things. Go ahead! I’ll wait.

Okay, back? So you probably noticed in the video that we have several systems all talking to each other:

  1. Your app server (or Firebase Notifications) talks to Firebase Cloud Messaging
  2. Firebase Cloud Messaging then talks to APNs
  3. APNs talks to your user’s target device
  4. On your user’s target device, iOS communicates with your app.

Tips

These four paths of communication means there are four opportunities for things to go wrong. And when they do, they very often manifest as a frustrating «It says my notification was sent, but nothing showed up on my device» kind of bug, which requires some real detective work. So here are the steps I recommend you go through to start tracking down these errors.

1. Temporarily disable any connectToFCM() calls

If you’ll recall from the video, your app can explicitly connect to Firebase Cloud Messaging by calling connectToFCM() when it’s in the foreground, which allows it to receive data-only messages that don’t have a content-available flag directly through FCM.

And while this can be useful in certain circumstances, I recommend disabling this while you’re debugging. Simply because it’s one extra factor that you want to eliminate. I’ve seen a few, «My app receives notifications in the foreground, but not in the background» problems out there that probably occurred because the developer was only receiving messages through the FCM channel, and their APNs setup was never actually working properly.

If things break at this point: If you suddenly go from «Hey, I was receiving foreground notifications» to «I’m not receiving any notifications at all», then this is a sign your app was never properly set up to receive notifications from APNs in the first place. So your app might be a little more broken than before, but at least now it’s consistently broken. (Hooray!) Keep reading to debug your APNs implementation!
For the next several steps, we’re going to go backwards through that «Notifications to FCM to APNs to iOS to your app» chain. Let’s start by making sure that iOS can actually speak to your app…

2. Add some good ol’ fashioned print() debugging

Thanks to some clever method swizzling, Firebase Cloud Messaging makes it totally unnecessary for you to implement either application(_:didRegisterForRemoteNotificationsWithDeviceToken:) or application(_:didFailToRegisterForRemoteNotificationsWithError:) in your app delegate.

However, for debugging purposes, I like to add in these methods and print out some debug information to see if there are any errors happening that I should be aware of. Start by adding some debug output to your failure method. Something like this:

func application(_ application: UIApplication,
    didFailToRegisterForRemoteNotificationsWithError error: Error) {
  print("Oh no! Failed to register for remote notifications with error (error)")
}

In theory, any error message printed out here will also probably be printed out by the FCM client library, but I like having my own messages because I can search for specific strings (like «Oh no!» in the above example) among all the Xcode output. This also gives me a handy line of code where I can add a breakpoint.

While you’re at it, in your didRegister... method, go ahead and print out a human-readable version of your device token:

func application(_ application: UIApplication,
    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
  var readableToken: String = ""
  for i in 0..<deviceToken.count {
    readableToken += String(format: "%02.2hhx", deviceToken[i] as CVarArg)
  }
  print("Received an APNs device token: (readableToken)")
}

You don’t need to disable method swizzling or anything to add these debug methods. Firebase will go ahead and call them just as soon as it’s done calling its own set of methods.

If you’re seeing an error message at this point: If you either receive an error message or don’t get back a device token, check the error message for a good hint as to what went wrong. Most mistakes at this point fall under the, «I’m embarrassed to tell anybody why it wasn’t working» category. Things like:

  • Testing on the iOS simulator and not the device.
  • Forgetting to enable Push Notifications in your Xcode project settings.
  • Not calling application.registerForRemoteNotifications() when your app starts up.

Sure, these are simple mistakes, but without the benefit of printing out messages to the Xcode console, it’s easy for them to go unnoticed.

3. Confirm that you can send user-visible notifications

As with any iOS app, you need to explicitly get the user’s permission to show any kind of notification alert or sound. If you’re in a situation where your app doesn’t appear to be receiving notification messages in the background, your app simply might not have permission from iOS to do so.

You can check this in iOS >= 10 by adding the following code somewhere in your app.

UNUserNotificationCenter.current().getNotificationSettings { (settings) in
  print("Alert setting is (settings.alertSetting ==
    UNNotificationSetting.enabled ? "enabled" : "disabled")")
  print("Sound setting is (settings.soundSetting ==
    UNNotificationSetting.enabled ? "enabled" : "disabled")")
}

If you’re seeing «disabled» messages at this point: Either you accidentally denied granting your app permission to send you notifications, or you never asked for permission in the first place.
If you accidentally clicked on the «Don’t allow» button when the app asked you for permission to send notifications, you can fix this by going to Settings, finding your app, clicking on Notifications, then clicking the Allow Notifications switch.

On the other hand, if you never asked for permission to show user-visible permissions, then it means you need to add code like this (for iOS >= 10) within your app somewhere:

let authOptions : UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: authOptions)
  { (granted, error) in
    if (error != nil) {
      print("I received the following error: (error)")
    } else if (granted) {
      print ("Authorization was granted!")
    } else {
      print ("Authorization was not granted. :(")
    }
  }

But if everything looks good at this point, you can move on to debugging the APNs connection!

4. Make a call directly through APNs

Remember; just because you’re using FCM to handle your notifications doesn’t mean you can’t also use APNs directly. There are a few ways you can try this; one option is to use an open-source tool like NWPusher to send test notifications. But personally, I prefer sending APNs requests directly through a curl call.

Making an APNs curl request is easier these days now that APNs supports HTTP/2. But it does mean you’ll need to make sure your copy of curl is up-to-date. To find out, run curl —version. You’ll probably see something like this:

curl 7.47.1 (x86_64-apple-darwin15.6.0) libcurl/7.47.1 OpenSSL/1.0.2f zlib/1.2.5 nghttp2/1.8.0
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets

If you want to talk to APNs, you’ll need a version of curl that’s greater than 7.43, and you’ll need to see HTTP2 among the features. If your version of curl doesn’t meet these requirements, you’ll need to update it. This blog post by Simone Carletti gives you some pretty nice instructions on how to do that.

Next, you’ll need to convert the .p12 file you downloaded from the Apple Developer Portal to a .pem file. You can do that with this command:

openssl pkcs12 -in MyApp_APNS_Certificate.p12 -out myapp-push-cert.pem -nodes -clcerts

You’ll also need the APNs device token for your target device. If you added the debug text listed earlier in your application(_:didRegisterForRemoteNotificationsWithDeviceToken:) method, you’ll be able to grab this from your Xcode console. It should look something like ab8293ad24537c838539ba23457183bfed334193518edf258385266422013ac0d

Now you can make a curl call that looks something like this:

> curl --http2 --cert ./myapp-push-cert.pem 
-H "apns-topic: com.example.yourapp.bundleID" 
-d '{"aps":{"alert":"Hello from APNs!","sound":"default"}}' 
https://api.development.push.apple.com/3/device/ab8293ad24537c838539ba23457183bfed334193518edf258385266422013ac0d

Three things to notice here:

  1. That --cert argument should link to the .pem file you created in the previous step.
  2. For the apns-topic, include the bundle ID of your app. And yes, the concept of apns-topics are completely different than Firebase Cloud Messaging topics.
  3. Make sure your device ID is included at the end of that URL there. Don’t just copy-and-paste the one that I have. It won’t work.

If all has gone well, you’ll see a push notification on the device, and you can move on to the next step. If not, here’s a few things to look for:

  1. Are you getting back any error message from APNs? That’s a pretty good sign something has gone wrong. Common messages include:

  2. «Bad device token» — This is what it sounds like. Your device token is incorrect. Double-check that you’ve copied it correctly from your app

  3. «Device token not for topic» — This might mean that your topic isn’t properly set to your app’s bundle ID. But it also might mean that you’re not using the correct certificate here — I’ve gotten this message when I’ve used the wrong .pem file.

  4. Is your app in the background? Remember that iOS will not automatically show notification alerts or sounds if your app is in the foreground.

  5. However, in iOS 10, they’ve made it significantly easier to have iOS show these alerts even if your app is in the foreground. You just need to call completionHandler([.alert]) at the end of userNotificationCenter(_:willPresent:withCompletionHandler:)

  6. Are you sending valid APNs requests? There are a few types of requests that, while syntactically correct, may still get rejected. At the time of this writing, these include sending silent notifications that don’t include the content-available flag, or sending silent notifications high priority.

  7. In addition, iOS may throttle silent notifications if your app neglects to call its completionHandler in a reasonable amount of time upon receiving them or uses too much power to process these notifications. Refer to Apple’s documentation for more information.

  8. Is APNs having issues? You can double-check the status of APNs and the APNs Sandbox over at https://developer.apple.com/system-status/

But if things seem to be working correctly here, it’s time to move on to the next step…

5. Make a curl call directly through FCM

Once you’ve confirmed your APNs call seems to be working properly, the next step is to confirm the FCM part of the process is working. For that, I also like to make another curl call. For this to work, you’re going to need two things: The server key and the FCM device token of your target device.
To get the server key, you’ll need to go to the Cloud Messaging settings of your project in the Firebase Console. Your server key should be listed there as a giant 175-character string.

Getting your FCM device token is slightly more work. When your app first receives an APNs token, it will send that off to the FCM servers in exchange for an FCM device token. When it gets this FCM token back, the FCM library will trigger an «Instance ID Token Refresh» notification. 1
So listening to this firInstanceIDTokenRefresh NSNotification will let you know what your FCM device token is, but this notification only gets triggered when your device token changes. This happens infrequently — like when you switch from a debug to production build, or when you run your app for the first time. Otherwise, this notification will not be called.

However, you can retrieve your cached FCM device token simply through the InstanceID library, which will give you any stored device token if it’s available. So to get your latest-and-greatest FCM token, you’ll want to write some code like this:

  func application(_ application: UIApplication, didFinishLaunchingWithOptions
    // ...
    printFCMToken() // This will be nil the first time, but it will give you a value on most subsequent runs
    NotificationCenter.default.addObserver(self, 
      selector: #selector(tokenRefreshNotification), 
      name: NSNotification.Name.firInstanceIDTokenRefresh, 
      object: nil)
    application.registerForRemoteNotifications()
    //...
  }

  func printFCMToken() {
    if let token = FIRInstanceID.instanceID().token() {
      print("Your FCM token is (token)")
    } else {
      print("You don't yet have an FCM token.")
    }
  }

  func tokenRefreshNotification(_ notification: NSNotification?) {
    if let updatedToken = FIRInstanceID.instanceID().token() {
      printFCMToken()
      // Do other work here like sending the FCM token to your server
    } else {
      print("We don't have an FCM token yet")
    }
  }

The very first time your app runs, you’ll see a message that you don’t have an FCM token, followed by a message a short time later with your actual token. In subsequent runs, you should see your cached token right away. It’s a 153-character random string that looks a lot like your server key, so don’t get ’em confused.
So, now that you have both pieces of information, you can make a curl call. Try calling something like this:

> curl --header "Content-Type: application/json" 
--header "Authorization: key=AU...the rest of your server key...s38txvmxME-W1N4" 
https://fcm.googleapis.com/fcm/send 
-d '{"notification": {"body": "Hello from curl via FCM!", "sound": "default"},
"priority": "high",
"to": "gJHcrfzW2Y:APA91...the rest of your FCM token...-JgS70Jm"}'

If all has gone well, you’ll see a notification on your device, as well as receive a «Success» response from FCM.

{"multicast_id":86655058283942579,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1486683492595106961%9e7ad9838bdea651f9"}]}

Don’t get too excited by this success response. That just means FCM has successfully received your message; it doesn’t mean that it has successfully delivered it to APNs. You really want to look for the notification on your device.

If your notification doesn’t seem to be getting received, here’s a few things to look out for:

  • Are you seeing an error message in your response? Don’t ignore those. They’re usually pretty big hints as to what’s going on.

  • InvalidRegistration means you don’t have the correct FCM device token. (Remember, it’s actually called a «registration token»)

  • A 401 error with the message «The request’s Authentification (Server-) Key contained an invalid or malformed FCM-Token» means the server key is probably incorrect. Make sure you’ve copied the whole thing correctly from the Firebase console.

  • Is your priority set to high? Android and iOS devices have different interpretations of medium and high priority values.

  • On Android, medium priority basically means, «Send the message, but be respectful of your user’s device if it’s in doze mode». This is generally why FCM uses «medium» as its default priority if you don’t specify one.

  • On iOS, medium (or 5) priority can best be summarized as, «Maybe we’ll send it at some point. But in this crazy world of ours, who can say for sure?!? ¯_(ツ)_/¯».

  • This is why APNs defaults to a priority value of 10 (or «high») when no priority value is specified and they really only ask you to send messages medium priority when you’re sending a data-only content-available message.

  • Ideally, you should send most user-visible messages with medium priority to Android devices and high priority to iOS devices. If you’re using the Firebase Notifications panel, you can do this pretty easily.

  • Are you using APNs syntax instead of FCM syntax? While FCM will properly translate FCM-speak to APNs, it will get confused if you send it APNs syntax in the first place. So double-check that you’re sending messages properly formatted for FCM. In particular, confirm that you’re setting «priority» to «high» and not «10».

  • If you’re sending a content available message, make sure you’re specifying "content_available": true with an underscore and not "content-available": 2

  • I also recommend trying to send a Notification through the Firebase Notifications panel at this point. If you can make a call through Notifications but not through a curl call, it might be a sign that your message isn’t properly formatted.

  • Have you uploaded your APNs certificate to the Firebase console? And has it expired? Remember, FCM needs that certificate in order to communicate with APNs.

6. Make a call through the Notifications panel and/or your server

So if you’ve gotten to this point, we’ve basically established that the path from FCM to APNs to iOS to your app is working correctly. So I would be very surprised if the Notifications panel wasn’t working at this point. If it is, the best thing to do is check status.firebase.google.com and see if there are any issues with the Cloud Messaging service. (This also includes the Notifications panel)

If the problem is with your server code, well… that’s up to you and your server. But now that you’ve figured out exactly what data you need to generate to make a proper FCM call, I’m hoping you can tackle this part on your own with confidence. Or, at least, the appearance of confidence, which is enough to fool most people.

That’s all!

Whew! Well, I know that was a lot to go through, and hopefully you were able to stop at, like, step 2 because it turns out you forgot to flip some switch in your Xcode project. If that’s the case, you’re probably not even reading this conclusion. Come to think of it, if you made it this far, it’s probably because you’re still having problems with your implementation, in which case… uh… go check out our support channels. Or ask @lmoroney, because I’m basically out of suggestions at this point.

Thanks for reading!

[1] That’s an NSNotification, not an APNs notification. Hooray for overloaded terms!
[2] One interesting error I ran into was a developer who couldn’t understand why his content-available messages were only being received when his app was in the foreground. It turns out he had explicitly connected to FCM (like in step 1) and was using the (invalid) "content-available" key in his message. Since FCM didn’t translate this into a valid APNs content-available message, it interpreted it as a data-only message that should only be sent over FCM, which is why it only worked when his app was in the foreground.

User351573 posted

I have done the following things:

  1. Created a project in FCM console and added ios project into it.
  2. Downloaded the GoogleService-Info.plist and added it to the xamarin forms ios project directory and set the build action as Bundlesource.
  3. On Info.plist enabled remote notification background mode.
  4. Added FirebaseAppDelegateProxyEnabled in the app’s Info.plist file and set it to No.
  5. Created a provisioning profile and distribution certificate and installed it into the keychain access. Also, mapped these certificates in the project options.
  6. Uploaded .p12 certificate in FCM console.
  7. Added codes for handling push notification in AppDelegate.cs.

My Code:

    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();
            LoadApplication(new App("",""));
            RequestPushPermissionsAsync();
            _launchoptions = options;
            return base.FinishedLaunching(app, options);
        }
        NSDictionary _launchoptions;
        public override void OnActivated(UIApplication uiApplication)
        {
            base.OnActivated(uiApplication);
            if (_launchoptions != null && _launchoptions.ContainsKey(UIApplication.LaunchOptionsRemoteNotificationKey))
            {
                var notfication = _launchoptions[UIApplication.LaunchOptionsRemoteNotificationKey] as NSDictionary;
                PresentNotification(notfication);
            }
            _launchoptions = null;
        }

        async Task RequestPushPermissionsAsync()
        {
            var requestResult = await UNUserNotificationCenter.Current.RequestAuthorizationAsync(
                 UNAuthorizationOptions.Alert
                | UNAuthorizationOptions.Badge
                | UNAuthorizationOptions.Sound);

            bool approved = requestResult.Item1;
            NSError error = requestResult.Item2;
            if (error == null)
            {
                if (!approved)
                {
                    Console.Write("Permission to receive notification was not granted");
                    return;
                }

                var currentSettings = await UNUserNotificationCenter.Current.GetNotificationSettingsAsync();
                if (currentSettings.AuthorizationStatus != UNAuthorizationStatus.Authorized)
                {
                    Console.WriteLine("Permissions were requested in the past but have been revoked (-Settings  app)");
                    return;
                }
                UIApplication.SharedApplication.RegisterForRemoteNotifications();
            }
            else
            {
                Console.Write($"Error requesting permissions: {error}.");
            }
        }

        public async override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
        {
            if (deviceToken == null)
            {
                return;
            }
            Console.WriteLine($"Token received: {deviceToken}");
            await SendRegistrationTokenToMainPRoject(deviceToken);
        }

        async Task SendRegistrationTokenToMainPRoject(NSData deviceToken)
        {
            MessagingCenter.Send<object, string>(this, "fcmtoken", deviceToken.ToString());
        }

        public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
        {
            Console.WriteLine($"Failed to register for remote notifications: {error.Description}");
        }

        public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo,
            Action<UIBackgroundFetchResult> completionHandler)
        {
            PresentNotification(userInfo);
            completionHandler(UIBackgroundFetchResult.NoData);
            try
            {
                UIApplication.SharedApplication.ApplicationIconBadgeNumber = 0;
                NSDictionary aps = userInfo.ObjectForKey(new NSString("aps")) as NSDictionary;
                var message = (aps[new NSString("webContentList")] as NSString).ToString();
                LoadApplication(new App("", message));
            }
            catch (Exception ex)
            {
                //LogInfo.ReportErrorInfo(ex.Message, ex.StackTrace, "AppDelegate-DidReceiveRemoteNotification");
            }
        }

        void PresentNotification(NSDictionary userInfo)
        {
            NSDictionary aps = userInfo.ObjectForKey(new NSString("aps")) as NSDictionary;

            var msg = string.Empty;

            if (aps.ContainsKey(new NSString("alert")))
            {
                msg = (aps[new NSString("alert")] as NSString).ToString();
            }
            if (string.IsNullOrEmpty(msg))
            {
                msg = "(unable to parse)";
            }
            MessagingCenter.Send<object, string>(this, App.NotificationReceivedKey, msg);
        }
    }

I am not using any NuGet packages in ios part. When running the project into a device, the FCM token generating part is working and I can see the fcm token on the VS console. I tried to send a test notification to a device from postman but getting InvalidRegistration error.

Postman Response

{
    "multicast_id": 8754155136812875313,
    "success": 0,
    "failure": 1,
    "canonical_ids": 0,
    "results": [
        {
            "error": "InvalidRegistration"
        }
    ]
}

Postman Body

 {
    "to" : "d20ad003 7473bfba 85dffc33 1534decf b4b886f1 c738878f fd7f2c60 d9dabc36",
 "collapse_key" : "type_a",
 "data" : {
     "body" : "Body of Your Notification in Data",
     "title": "Title of Your Notification in Title",
     "key_1" : "Value for key_1",
     "key_2" : "Value for key_2"
 },
 "notification" : {
     "body" : "Body of Your Notification",
     "title": "Title of Your Notification",
     "sound": "default",
     "content_available" : true
 }
}

I have completed the android part implementation and notifications are receiving when push from the postman. But getting InvalidRegistration error on postman and not receiving any notification in my ios device.

Anyone suggest a solution for this issue.

Thanks in advance.

Понравилась статья? Поделить с друзьями:
  • Error invalidfont offendingcommand xshow
  • Error invalid zip file with overlapped components possible zip bomb
  • Error invalid winflash parameters
  • Error invalid username or password перевод
  • Error invalid username or incorrect password lost your password