invertase / react-native-firebase

šŸ”„ A well-tested feature-rich modular Firebase implementation for React Native. Supports both iOS & Android platforms for all Firebase services.
https://rnfirebase.io
Other
11.53k stars 2.18k forks source link

[šŸ›] The operation couldnā€™t be completed. No APNS token specified before fetching FCM Token #6893

Open k2xl opened 1 year ago

k2xl commented 1 year ago

Issue

Trying to get token from user.

import messaging from '@react-native-firebase/messaging';
import { registerRootComponent } from 'expo';
import React, { useEffect } from 'react';
import {
  Text
} from 'react-native';

async function onAppBootstrap() {
  // Register the device with FCM
  console.log('A');
  await messaging().registerDeviceForRemoteMessages();
  console.log('B');
  // Get the token
  const token = await messaging().getToken();

  // Save the token
  console.log('TOKEN ' + token);
}

function App() {
  useEffect(() => {
    onAppBootstrap();
  }, []);

  return (
    <Text>Hi</Text>
  );
}

console.log('Registering root component');
registerRootComponent(App);
export default App;

When running this on iOS simulator, I get A on the console but it never reaches B. On further debugging just calling await messaging() seems to do enough to hang.

I see now after adding initializeApp() with credentials from firebase the following error

The operation couldnā€™t be completed. No APNS token specified before fetching FCM Token

Project Files

Javascript

Click To Expand

#### `package.json`: ```json "@react-native-firebase/app": "^17.0.0", "@react-native-firebase/messaging": "^17.0.0", ``` #### `firebase.json` for react-native-firebase v6: ```json # N/A ```

iOS

Click To Expand

#### `ios/Podfile`: - [ ] I'm not using Pods - [x] I'm using Pods and my Podfile looks like: ```ruby # N/A ``` #### `AppDelegate.m`: ```objc // N/A ```


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`: ```groovy // N/A ``` #### `android/app/build.gradle`: ```groovy // N/A ``` #### `android/settings.gradle`: ```groovy // N/A ``` #### `MainApplication.java`: ```java // N/A ``` #### `AndroidManifest.xml`: ```xml ```


Environment

Click To Expand

System: OS: macOS 12.5 CPU: (10) arm64 Apple M1 Pro Memory: 227.88 MB / 16.00 GB Shell: 5.8.1 - /bin/zsh Binaries: Node: 19.5.0 - /opt/homebrew/bin/node Yarn: Not Found npm: 9.3.1 - /opt/homebrew/bin/npm Watchman: Not Found Managers: CocoaPods: 1.11.3 - /opt/homebrew/bin/pod SDKs: iOS SDK: Platforms: DriverKit 22.2, iOS 16.2, macOS 13.1, tvOS 16.1, watchOS 9.1 Android SDK: Not Found IDEs: Android Studio: 2022.1 AI-221.6008.13.2211.9477386 Xcode: 14.2/14C18 - /usr/bin/xcodebuild Languages: Java: 17.0.6 - /usr/bin/javac npmPackages: @react-native-community/cli: Not Found react: 18.1.0 => 18.1.0 react-native: 0.70.5 => 0.70.5 react-native-macos: Not Found npmGlobalPackages: *react-native*: Not Found ``` OUTPUT GOES HERE ``` - **Platform that you're experiencing the issue on**: - [ ] iOS - [ ] Android - [x ] **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:** - `"@react-native-firebase/app": "^17.0.0", - "@react-native-firebase/messaging": "^17.0.0",` - **`Firebase` module(s) you're using that has the issue:** - `e.g. Instance ID` - **Are you using `TypeScript`?** - `Y`


k2xl commented 1 year ago

After adding initializeApp() with credentials from new firebase app it stopped hanging. However, now encountering:

The operation couldnā€™t be completed. No APNS token specified before fetching FCM Token

So trying to debug this now

mikehardy commented 1 year ago

with the latest firebase-ios-sdk (v10.4.0+) an APNS token is strictly required as a prerequisite to get an FCM token The SDKs try to handle this for you by swizzling in AppDelegate methods that register an APNS token if one comes, but if you disable swizzling, or you do not register for remote notifications prior to calling getToken, you'll never get one

k2xl commented 1 year ago

Hi @mikehardy thanks for the response. I'm very confused. Apologies as I'm still relatively new to react-native. Note that I'm also using Expo.

In my example above, I am calling registerForRemoteNotifications before calling getToken.

mikehardy commented 1 year ago

I'm not sure why, but the FCM system does not have an APNS token set for your app before you request an FCM token. There can be a few reasons why, as mentioned above it could be that swizzling is disabled in your AppDelegate such that the FCM callback which would normally listen for / register the APNS token with FCM when it comes in is not hooked up. It could be that you do not have remote messaging set up as an entitlement for your app. It could be lots of things.

One thing that might be uncomfortable to hear but is nevertheless important: others have this working. The code works in the module. Why is that important but maybe uncomfortable? Because it implies (though no, it does not quite prove...) that the problem is specific to your app and your configuration. You should triple check everything with the assumption the problem is in your app and no one will be able to help you find it - you will likely find the problem yourself in your app upon further careful inspection.

There is still of course the possibility the problem is in this module, but no one else is experiencing it so I am operating on the assumption the problem is project-specific

k2xl commented 1 year ago

Thank you for your respectful response! Definitely appreciate this input.

I think part of the reason I raised this issue is that I did see some other threads for a few weeks ago related to this issue. So I thought just getting the minimal example to reproduce the issue could cause an issue - so in case anyone else encounters and has found a solution they may stumble upon this ticket.

The fact that this sounds like only affecting me indicates it is indeed a problem with my configuration - I guess the tough part I'll need to figure out is what is the issue with my configuration:).

Anyway best regards, and thanks again for the pointers

mikehardy commented 1 year ago

The new strict requirement for an APNS token prior to an FCM one is bound to turn up issues like this so I will be very curious to hear what you turn up. Right now the entitlements idea is my best one for you but maybe it's something else? There was a lot of traffic about this recently because they added this requirement first on the backend without warning which exposed lots of people getting FCM tokens with no corresponding APNS token and broke their apps.

Of course those non-APNS FCM tokens are useless, but breaking the misconfigured apps unexpectedly was bad and generated all the traffic. They relaxed the backend change but left the SDK change in for firebase-ios-sdk 10.4.0 release so it is now only seen by folks as they upgrade, which is you now. It's a valid change (the APNS token should be required...) but forces everyone to find their corner cases where it fails now. And here we are...

Anyway, definitely report back if you find anything, and I hope you do + quickly. Cheers

nicolasburtey commented 1 year ago

also running into this issue today. not sure right now why that is.

it's not a minimal example, but issue can be seen by cloning this repo: https://github.com/GaloyMoney/galoy-mobile

farojos commented 1 year ago

@k2xl I had the same issue minutes before.

I solved it by checking in signing & capabilities. Inside "Background modes", I selected "Background check" and "Remote notifications". I hope this helps you.

nicolasburtey commented 1 year ago

@k2xl I had the same issue minutes before.

I solved it by checking in signing & capabilities. Inside "Background modes", I selected "Background check" and "Remote notifications". I hope this helps you.

just tried that and had no effect on my end.

I realized I had not set use_frameworks! :linkage => :static in the Podfile even thought it was necessary from a recent update, but it doesn't seem to remove the error message.

tautvilas commented 1 year ago

I have been digging into this problem the whole evening. In my case the problem was that in firebase.json property registerDeviceForRemoteMessages was set to false. This caused getAPNSToken to return null and also triggered this error in case getToken was called.

I don't remember why did I set registerDeviceForRemoteMessages to false earlier before. But this still looks like firebase bug. Because I did call registerDeviceForRemoteMessages in my JS code, but for some reason that did not perform the registration fully. One interesting behaviour that I noticed was that APNSToken was not not null only in the case when app was launched first time after install (with registerDeviceForRemoteMessages=false setup) .

nicolasburtey commented 1 year ago

on my end, solving by doing a full re-install off the app. don't know how it got corrupted in the first place but anyway, no longer seen the error message.

kesha-antonov commented 1 year ago

I fixed this by changing firebase.json

From

{
  "react-native": {
    "analytics_auto_collection_enabled": false,
    "messaging_auto_init_enabled": false,
    "messaging_ios_auto_register_for_remote_messages": false
  }
}

To

{
  "react-native": {
    "analytics_auto_collection_enabled": false,
    "messaging_auto_init_enabled": false,
    "messaging_ios_auto_register_for_remote_messages": true
  }
}

And deleted call

await messaging().registerDeviceForRemoteMessages()
k2xl commented 1 year ago

Thanks for the responses. I am on an expo managed app so didn't have a firebase.json file...

I tried adding a firebase.json to the root of the folder and removed the await messaging().registerDeviceForRemoteMessages() (since it was showing that it was unneeded).

However await messaging().getToken(); hangs... and I still get The operation couldnā€™t be completed. No APNS token specified before fetching FCM Token

Spxc commented 1 year ago

Thanks for the responses. I am on an expo managed app so didn't have a firebase.json file...

I tried adding a firebase.json to the root of the folder and removed the await messaging().registerDeviceForRemoteMessages() (since it was showing that it was unneeded).

However await messaging().getToken(); hangs... and I still get The operation couldnā€™t be completed. No APNS token specified before fetching FCM Token

Hey, i just stumbled upon this issue, got a solution? According to the docs setAPNS needs to be called, just not sure how or where

mikehardy commented 1 year ago

According to the docs setAPNS needs to be called,

I don't believe this statement is true? The docs should say (and I think they say?) that you must call setAPNS *if you have disabled method swizzling or for some other reason have disabled the automatic firebase APNS token handling on remote message registration

In almost all cases, certainly the "default integration" cases, if you call the API to register for remote notifications, and have @react-native-firebase/messaging installed in the default manner with correct entitlements on your iOS project to allow them, the SDK will request an APNS token from Apple and set it into the SDK for you fully automated.

You only want or need to use setAPNS token if you really want to manage APNS tokens yourself (for automated testing on non-Apple-Silicon emulators, perhaps, or if you have some brownfield app where you manage APNS tokens yourself, etc)

mikehardy commented 1 year ago

We appear to have an issue in the reference API docs where line breaks in our method docs stop the rest of the doc from rendering but the whole doc is as such:

https://github.com/invertase/react-native-firebase/blob/2e51817c937247ffe51fb6234c164744c2a71693/packages/messaging/lib/index.d.ts#L888-L906

I'll see what I can about getting the rest of the info to actually show up on the reference site as it should.

Spxc commented 1 year ago

According to the docs setAPNS needs to be called,

I don't believe this statement is true? The docs should say (and I think they say?) that you must call setAPNS *if you have disabled method swizzling or for some other reason have disabled the automatic firebase APNS token handling on remote message registration

In almost all cases, certainly the "default integration" cases, if you call the API to register for remote notifications, and have @react-native-firebase/messaging installed in the default manner with correct entitlements on your iOS project to allow them, the SDK will request an APNS token from Apple and set it into the SDK for you fully automated.

You only want or need to use setAPNS token if you really want to manage APNS tokens yourself (for automated testing on non-Apple-Silicon emulators, perhaps, or if you have some brownfield app where you manage APNS tokens yourself, etc)

Hi Mike, Thanks for the reply!

According to the changelog there were some breaking changes:

[17.0.0](2023-02-02)
āš  BREAKING CHANGES
app, ios: You must have an APNS token before calling getToken to get an FCM token on iOS. Previously it was not required. See documentation for setAPNSToken if you are using getToken in testing or have disabled FCM Swizzling, and use setAPNSToken to set a token before using getToken

EDIT: Saw your reply, i'll have a read through. The thing is, nothing changed in our code, we just updated the package, then it started throwing the APNS error. Been working flawlessly prior to this :)

How i noticed it; the entire app hung on the splash screen (both simulator and device - iOS). Moving the getToken() function to after the app checks for permissions, fixed the freeze. However it's throwing the error: Failed to fetch FCM: Error: [messaging/unknown] The operation couldnā€™t be completed. No APNS token specified before fetching FCM Token

mikehardy commented 1 year ago

Yes, as you quote, I quote the important bit:

See documentation for setAPNSToken if you are using getToken in testing or have disabled FCM Swizzling

That is

if you are using getToken in testing or have disabled FCM Swizzling

Almost no one does either. In the testing case, you can inject a "correctly formatted but useless" APNS token just to exercise FCM APIs, but who would do that except someone that implements FCM APIs (that is: us here, as maintainers...). So it's possible but I expect no one else to do it.

And disabling swizzling is something I'd consider "advanced" on the iOS side. If you're disabling swizzling you are effectively on your own as you have moved past the default + works implementation and are stating clearly (by disabling swizzling): "we know what we're doing on iOS, don't worry about us"

mikehardy commented 1 year ago

EDIT: Saw your reply, i'll have a read through. The thing is, nothing changed in our code, we just updated the package, then it started throwing the APNS error. Been working flawlessly prior to this :)

--> https://github.com/invertase/react-native-firebase/issues/6893#issuecomment-1422890413

Spxc commented 1 year ago

Yes, as you quote, I quote the important bit:

See documentation for setAPNSToken if you are using getToken in testing or have disabled FCM Swizzling

That is

if you are using getToken in testing or have disabled FCM Swizzling

Almost no one does either. In the testing case, you can inject a "correctly formatted but useless" APNS token just to exercise FCM APIs, but who would do that except someone that implements FCM APIs (that is: us here, as maintainers...). So it's possible but I expect no one else to do it.

And disabling swizzling is something I'd consider "advanced" on the iOS side. If you're disabling swizzling you are effectively on your own as you have moved past the default + works implementation and are stating clearly (by disabling swizzling): "we know what we're doing on iOS, don't worry about us"

Yeah, but the thing is; this code have been running fine in a simulator upon until today when doing a package update, then the freeze, now the error. This also occurred on a real device

mikehardy commented 1 year ago

when doing a package update

...across a breaking change boundary, which contains this note:

https://github.com/invertase/react-native-firebase/blob/main/CHANGELOG.md#1700-2023-02-02

app, ios: You must have an APNS token before calling getToken to get an FCM token on iOS. Previously it was not required. See documentation for setAPNSToken if you are using getToken in testing or have disabled FCM Swizzling, and use setAPNSToken to set a token before using getToken

It's a big deal, it must be handled.

Getting an APNS token is an asynchronous network-bound process that could fail, or may even be disabled by some configuration issue.

Previously these misconfigurations or order-of-operations issues were ignored and Firebase would gladly vend an FCM token that was useless as it had no corresponding APNS counterpart.

Now it is (correctly, but maybe painfully) saying "Nope, an FCM token in this context is actually without value, so we won't give you an FCM token without the APNS token behind it"

And we all have to adjust by making sure the APNS token is really there before asking for an FCM token. Might require checking network, re-trying, verifying you really register for remote notifications, you really have your iOS app entitlements correct, you have permission etc, but that's all justified and correct. Just a bit painful, maybe unexpected.

Spxc commented 1 year ago

Yeah, but how do we actually check for the token? That's what we are asking about. How can we adjust the code? We've followed the docs step by step, and it's this simple line: firebase.messaging().getToken()

Isn't that function supposed to check to see if the APNS are there?

Just want to reiterate: that all the certificates/keys etc are in order

mikehardy commented 1 year ago

Isn't that function supposed to check to see if the APNS are there?

well...it does, but not in a pleasant way. It checks and throws an error if it's not there. Shouldn't be hanging you should be getting the error I think you report:

The operation couldnā€™t be completed. No APNS token specified before fetching FCM Token

So, perhaps you want to make sure you have permissions from the user, that you register for remote notifications, and that getAPNSToken returns a token (any token, value doesn't matter - except undefined is bad of course). Once those work (perhaps in a backoff retry loop with a final error to user saying some functionality won't work?) then you go for the FCM token

Spxc commented 1 year ago

So, perhaps you want to make sure you have permissions from the user, that you register for remote notifications, and that getAPNSToken returns a token (any token, value doesn't matter - except undefined is bad of course). Once those work (perhaps in a backoff retry loop with a final error to user saying some functionality won't work?) then you go for the FCM token

Awesome, yes, that's exactly what I ended up doing.

Good to know that it handles the error kinda weird. The hanging/freezing issue was fixed by moving the getToken() function after requesting permissions from the user.

flashman2 commented 1 year ago

Got the same error after upgrade "@react-native-firebase/messaging": "^14.7.0" -> "@react-native-firebase/messaging": "^17.3.0" Only iOS issue, on Android seems everything is fine.

Signing & Capabilities -> Background Modes (Remote notifications, Background processing) enabled.

Before this upgrade everything was fine. Is there any solution for this issue?

I see this is a new issue but I think a lot of people will see this issue after upgrades. So any workaround, patch or instruction is really needed. Right now, I decided to stick with old version of module.

mikehardy commented 1 year ago

@flashman2 it appears based on your comment you have not read the rest of the comments. Explanations and solutions are detailed throughout, please read through.

flashman2 commented 1 year ago

@mikehardy Thanks for your answer. I'm sorry if I missed something. But I really can't find a clear instruction on what to do when migrate to 17.x.x version from older versions. Even in this thread, I see multiple solutions like this: https://github.com/invertase/react-native-firebase/issues/6893#issuecomment-1427998691 or this: https://github.com/invertase/react-native-firebase/issues/6893#issuecomment-1421591979

None of them help to solve issue. I still get error message. Can you please point where and what I need to change to make it work again?

Below is my current code which works fine with version 14.7.0.

import messaging from '@react-native-firebase/messaging';
import notifee from '@notifee/react-native';

const App = () => {
  //Push Notifications

  const requestUserPermission = async () => {
    const authStatus = await messaging().requestPermission();
    const enabled =
      authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
      authStatus === messaging.AuthorizationStatus.PROVISIONAL;

    if (enabled) {
      console.log('Authorization status:', authStatus);
    }
  };
  useEffect(() => {
    if (Platform.OS === 'ios') {
      requestUserPermission();
    }
    messaging()
      .subscribeToTopic('main')
      .then(() => console.log('Subscribed to topic!'));

    const unsubscribe = messaging().onMessage(async (remoteMessage) => {
      await onDisplayLocalNotification(
        remoteMessage.notification.title,
        remoteMessage.notification.body,
      );
    });

    return unsubscribe;
  }, []);

  async function onDisplayLocalNotification(title, message) {
    // Create a channel
    const channelId = await notifee.createChannel({
      id: 'default',
      name: 'Default Channel',
    });

    // Display a notification
    await notifee.displayNotification({
      title: title,
      body: message,
      android: {
        channelId,
      },
    });
  }

  return (
    <GlobalStateContext.Provider value={preferences}>
      ...
    </GlobalStateContext.Provider>
  );
};

export default App;
mikehardy commented 1 year ago

I don't see an await for user permission I don't see a check for apns token and then check for FCM token ( with await) before subscription

iampato commented 1 year ago

How do i do this I don't see a check for apns token and then check for FCM token ( with await) before subscription @mikehardy

mikehardy commented 1 year ago

something like


// How to see if you have an APNS token
const apnsToken = await firebase.messaging().getAPNSToken();
if (apnsToken === undefined) {
    // we do not appear to have an APNS token.
    // possible misconfiguration, possibly user did not grant permission, possible network timeout, possibly non-APNS Simulator
    // if you *really* know you are in a dev environment on Simulator, maybe setAPNSToken to some string to continue
    // if this is a real environment then maybe try a few times with sleeps to see if it comes in?
}

// How to register
if (apnsToken !== undefined) {
  firebase.messaging().<some call here that requires a valid FCM token like getToken or subscribe or whatever>
}

Checking for an APNS token and using the token should be thought of as separate things with FCM usage depending on APNS, so do the APNS check work first and if it succeeds set some state that will trigger the effect of using it

This is all really dependent on a project's requirements so it will vary and I cannot suggest what your project will need in practice.

Spxc commented 1 year ago

How do i do this I don't see a check for apns token and then check for FCM token ( with await) before subscription @mikehardy

The lib does it by auto, sometimes it fails (not loaded yet) but should be found on auto. In order to follow the guidelines (for waiting for permission, to access FCM), you can do something on the lines of this: requestUserPermission().then(async (data) => { let FCMToken = await getToken(); //this is your FCM token for push });

Also, check your .plist to see that you haven't disabled swizzeling as stated prior. The line you're looking for is: <key>FirebaseAppDelegateProxyEnabled</key> <true />

KrisLau commented 1 year ago

@mikehardy So I tried the method you described here, just calling registerDeviceForRemoteMessages, as well as double checking the signing and capabilities to see that it includes both Background fetch & Remote notifications but all of them seem tp result in errors. Swizzling is not disabled and I did not override anything as I do not have a firebase.json file (I did also try adding one as per this comment but it did not seem to work for me).

I either get:

My main problem is only on simulator devices. On physical devices I don't get these errors at all. I'm kind of at a loss as to what to do other than to roll back to a previous version temporarily

Spxc commented 1 year ago

@mikehardy So I tried the method you described here, just calling registerDeviceForRemoteMessages, as well as double checking the signing and capabilities to see that it includes both Background fetch & Remote notifications but all of them seem tp result in errors. Swizzling is not disabled and I did not override anything as I do not have a firebase.json file (I did also try adding one as per this comment but it did not seem to work for me).

I either get:

  • [messaging/unregistered] You must be registered for remote messages before calling getToken, see messaging().registerDeviceForRemoteMessages().
  • [messaging/unknown] The operation couldnā€™t be completed. No APNS token specified before fetching FCM Token

My main problem is only on simulator devices. On physical devices I don't get these errors at all. I'm kind of at a loss as to what to do other than to roll back to a previous version temporarily

Did you ask the user for permissions before trying to collect it? You'd need to ask for permission and the user allowing it, to fetch the correct and valid token. Have you tried looking at the example I provided?

Also FCM dosent work for iOS in the Simulator, and you need to test with a physical device or using Android Simulator (support for FCM)

-scar

SudoPlz commented 1 year ago

If you're on iOS simulator, keep in mind that you'll now get this error (because didRegisterForRemoteNotificationsWithDeviceToken won't be called and thus no APNS token will be set) - you MUST use a real device.

ZakirBangash commented 1 year ago
Spxc commented 1 year ago
  • Restart the system
  • Delete the app from simulator
  • close any metro if opened
  • clean the build
  • and run the app same steps resolved the issue on my end

No this wont work, the error says whats wrong. It simply cant fetch the FCM token. This is due to either the app running in a Simulator, wrong setup in the iOS project (Xcode) or not requesting user permission before trying to fetch the token.

I would strongly recommend you to have a look at the previous answers.

ZakirBangash commented 1 year ago

I really appreciate your response, I was experiencing the same issue. although it was working yesterday, when today morning I run the app, I was facing the same issue, then I did the above steps.

I don't know why but it has been resolved with me

KrisLau commented 1 year ago

@Spxc Thanks for the reply! yeah I did ask for permissions and I did also look at your example but neither seemed to work for me. I understand that FCM doesn't work with the simulator but the errors it's throwing are messing with Sentry since it drops non stop errors which is why I tried to setAPNSToken but it just was not working for me. I ended up rolling back to a previous version just as a temporary workaround as I don't have time to troubleshoot it rn.

mikehardy commented 1 year ago

Simulators can actually get tokens now on Apple Silicon machines with iOS16+ and macOS Ventura+

Basically anyone with up to date software on an Apple Silicon machine can use + test FCM on Simulator now, which is great

For all other Simulators you need to call setAPNSToken with some sort of string if you want to call getToken. At that point the method will work but obviously you won't get messages delivered.

kukuandroid commented 1 year ago

Hello, is it resolved ?. From my case, different mac and simulator are able to get the token, but some of them are not. Latest firebase version

mikehardy commented 1 year ago

Hello, is it resolved ?. From my case, different mac and simulator are able to get the token, but some of them are not. Latest firebase version

I'm not reproducing any problems and was testing many combinations while implementing it. If you were specific about which combinations were failing (exact versions of operating system on the mac, type of mac, version of iOS on the simulator, code sample to reproduce) it would help

anhnch commented 1 year ago

I got the same error after upgrading to 17.3.2 and read through the comments. None helps. I'm on

I tried to get the APNS token as mike suggested and I found this error in the xcode debug console

[RNFBMessagingModule getAPNSToken::] [Line 178] RNFBMessaging getAPNSToken - ARM64 Simulator detected, but no APNS token set. Assuming APNS token is possible. macOS13+ / iOS16+ / M1 mac required for assumption to be valid. Use setAPNSToken in testing if needed.

I'm not sure but I guess It can't get the APNS token on Simulator. But in the previous versions, the APNS token was not required.

codal-mpawar commented 1 year ago

getting same issue.

mikehardy commented 1 year ago

Okay, so:

Use setAPNSToken in testing if needed.

Use setAPNSToken in that situation if you must.

It may be that "swizzling" is disabled, or that the asynchronous (sometimes you've got to wait + retry, just as on real devices during first install + first token fetch etc situations) APNS token fetch has not had enough time to complete. This can happen on real devices as well during a few scenarios and you may simply have not hit it in your testing but needs to be handled for real devices as well

kukuandroid commented 1 year ago

Okay, so:

Use setAPNSToken in testing if needed.

Use setAPNSToken in that situation if you must.

It may be that "swizzling" is disabled, or that the asynchronous (sometimes you've got to wait + retry, just as on real devices during first install + first token fetch etc situations) APNS token fetch has not had enough time to complete. This can happen on real devices as well during a few scenarios and you may simply have not hit it in your testing but needs to be handled for real devices as well

how to use the function ? it takes token as parameter

anhnch commented 1 year ago

Okay, so:

Use setAPNSToken in testing if needed.

Use setAPNSToken in that situation if you must. It may be that "swizzling" is disabled, or that the asynchronous (sometimes you've got to wait + retry, just as on real devices during first install + first token fetch etc situations) APNS token fetch has not had enough time to complete. This can happen on real devices as well during a few scenarios and you may simply have not hit it in your testing but needs to be handled for real devices as well

how to use the function ? it takes token as parameter For me,

if (__DEV__) await messaging().setAPNSToken('anything', 'sandbox');

And it's gone

RubenPM-dev commented 1 year ago

I've read all the comments and don't seem to find a solution despite setting the "messaging_ios_auto_register_for_remote_messages" to true in the firebase.json file. If I set this to false then I can't seem to get the APNS even though I ask user permission, I call registerDeviceForRemoteMessages, try to get the APNS and then the FCM token but it doesn't throw any errors or anything at the APNS, seems to hang in there, more detail below.

I first ask user for permission, when granted I then register the device for notification:

 const getNotificationPermission = async () => {
    const authStatus = await messaging().requestPermission({
      alert: true,
      criticalAlert: true,
      badge: true,
      sound: true,
      announcement: true,
    });
    const enabled =
    authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
    authStatus === messaging.AuthorizationStatus.PROVISIONAL;

    setPermission(enabled);
  };

const registerForNotifications = async () => {
    const isRegisted = messaging().isDeviceRegisteredForRemoteMessages;
    if (!isRegisted) {
      await registerDeviceForNotifications(); // calls await messaging().registerDeviceForRemoteMessages()
    } else {
      const fcmToken = await getFCMnotificationsToken();
      fcmToken && (await updateBackendToken(fcmToken));
    }
  };

  useEffect(() => {
    if(permission) {
         registerForNotifications();
    }
},[permission]);

useEffect(() => {
   if(isAuthenticated) getNotificationPermission();
},[isAuthenticated])

Swizzling is enabled and on the AppDelegate.m have this:

-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken: (NSData *)deviceToken
    {
      [FIRMessaging messaging].APNSToken = deviceToken;
      NSString *fcmToken = [FIRMessaging messaging].FCMToken;
      NSLog(@"++APNS deviceToken : %@", deviceToken);
      NSLog(@"++FCM device token : %@", fcmToken);
    }

-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
    {
      NSLog(@"!!! ERROR regisgering for APNS : %@", error);
    }
  if (Platform.OS === "ios") {

    console.log('GET APNS');  // I can see this log

    const apnsToken = await messaging().getAPNSToken(); 

    console.log("==> APNS token", apnsToken); // THIS NEVER GETS CALLED

    if(apnsToken) {
      return await messaging().getToken();
    } else {
      await messaging().setAPNSToken('randomAPNStoken', 'sandbox').then(async () => await messaging().getToken());
    };

It seems that it hangs on the await.messaging().getANSToken();

No APNS is retrieved unless I enable the messaging_ios_auto_register_for_remote_messages.

Seanmclem commented 1 year ago

I tried adding messaging().getAPNSToken(), and my code just would hang at that line, and not proceed, with no errors. But this was in Simulator. Which never threw the error until yesterday, but oh well. I tried it on a real device, and it's still working totally fine. Provisioning new tokens for FCM messages. The error is erroneous in Simulator.

Personally, I didn't need to add any code to fix the error No APNS token specified before fetching FCM Token, because the error is erroneous in Simulator

mikehardy commented 1 year ago

@Seanmclem what did the device / simulator logs say?

giacomette commented 1 year ago

I solved it in the simulator by doing await messaging().setAPNSToken('test') before getToken. This is just to simulate an apns key :)

if (isIOSSimulator()) {
    await messaging().setAPNSToken('test');
}

fcmToken = await messaging().getToken();