Skip to content

[🐛] 🔥RNFBMessaging getToken - no APNS token is available. #8435

@stalteri

Description

@stalteri

Issue

When calling messaging.getAPNSToken(), it returns null even though the APNS token is correctly received in didRegisterForRemoteNotificationsWithDeviceToken (verified by logging a device token with a byte length of 32). Consequently, calling messaging.getToken() halts execution and never returns an FCM token. Notifications permission is granted.

Have this message in xcode logs:
-[RNFBMessagingModule getToken::::] [Line 134] RNFBMessaging getToken - no APNS token is available. Firebase requires an APNS token to vend an FCM token in firebase-ios-sdk 10.4.0 and higher. See documentation on setAPNSToken and getAPNSToken.
Image

Background Modes and Push Notifications are enabled in xcode:
Image

All settings enabled in AppStoreConnect, APNS key created and uploaded to Firebase Console.

Also have this warning multiple times:
Image


Project Files

Javascript

Click To Expand

executionFile.ts:

import React, { useState, useEffect } from 'react';
import { PermissionsAndroid, Platform } from 'react-native';
import { getMessaging, AuthorizationStatus } from '@react-native-firebase/messaging';
import PushNotificationIOS from '@react-native-community/push-notification-ios';
import logger from 'app/utilities/logger';

const NOTIFICATIONS_PERMISSION = PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS;

const messaging = getMessaging();

function usePermissions() {
  const [permissionGranted, setPermissionGranted] = useState<boolean>(false);
  const [token, setToken] = useState<string | null>(null);

  const getNotificationPermissions = React.useCallback(async () => {
    if (Platform.OS === 'ios') {
      const authStatus = await messaging.requestPermission();
      const enabled = authStatus === AuthorizationStatus.AUTHORIZED
        || authStatus === AuthorizationStatus.PROVISIONAL;

        setPermissionGranted(enabled);

      if (enabled) logger.success('Notification permission granted');
      else logger.error('Notification permission denied');

      return;
    }

    if (Platform.OS === 'android') {
      const notificationPermission = await PermissionsAndroid.check(NOTIFICATIONS_PERMISSION);

      if (notificationPermission) {
        logger.success('Notification permission granted');
        return setPermissionGranted(true);
      }

      const hasPermissions = await PermissionsAndroid.request(NOTIFICATIONS_PERMISSION);

      if (hasPermissions) {
        logger.success('Notification permission granted');
        return setPermissionGranted(true);
      }

      logger.error('Notification permission denied');
    }
  }, []);

  const getFCMToken = React.useCallback(async () => {
    try {
      const APSNToken = await messaging.getAPNSToken();
      logger.success('APNS token retrieved', APSNToken);

      const token = await messaging.getToken();

      if (token) {
        setToken(token);
        logger.success('FCM token retrieved', token);
      } else {
        logger.error('No registration token obtained');
      }
    } catch (error) {
      logger.error('Unable to get FCM token', error);
    }
  }, []);

  useEffect(() => {
    const check = async () => {
      await getNotificationPermissions();
      await getFCMToken();
    };
    check();
  }, [getFCMToken, getNotificationPermissions]);

useEffect(() => {
    const check = async (token: string) => {
      try {
        console.log('Setting APNS token', token);

        await messaging.setAPNSToken(token);
        await getFCMToken();
      } catch (error) {
        logger.error('Unable to set APNS token', error);
      } finally {
        logger.success('APNS token set', token);
      }
    };
    if (Platform.OS === 'ios') {
      PushNotificationIOS.addEventListener('register', token => {
        console.log('APNS token', token);

        if (token) check(token);
      });
    }
  }, [getFCMToken]);

  return { permissionGranted, FCMToken: token };
}

export default usePermissions;

package.json:

{
  "name": "nexops",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint .",
    "xcode": "xed -b ios",
    "pod:update": "cd ./ios && pod update && cd ..",
    "pod:install": "npm i && cd ./ios && pod install && cd ..",
    "build:ios": "react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ios/main.jsbundle --assets-dest ios",
    "build:android": "mkdir -p android/app/src/main/assets && rm -rf android/app/build && react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res && cd android && ./gradlew assembleDebug",
    "open:debugger": "open \"rndebugger://set-debugger-loc?host=localhost&port=8081\"",
    "open:link:android": "adb shell am start -W -a android.intent.action.VIEW -d",
    "open:link:ios": "xcrun simctl openurl booted",
    "babel:clear:cache": "rm -rf ./node_modules/.cache/babel-loader/*",
    "gradlew:clean": "cd ./android && ./gradlew clean && cd ..",
    "metro:clear:cache": "rm -rf /tmp/metro-bundler-cache-*"
  },
  "dependencies": {
    "@api.video/react-native-livestream": "2.0.2",
    "@notifee/react-native": "9.1.8",
    "@react-native-async-storage/async-storage": "2.0.0",
    "@react-native-community/hooks": "^2.8.0",
    "@react-native-community/netinfo": "11.4.1",
    "@react-native-firebase/app": "21.12.3",
    "@react-native-firebase/messaging": "21.12.3",
    "@react-navigation/bottom-tabs": "6.5.11",
    "@react-navigation/drawer": "6.6.6",
    "@react-navigation/elements": "1.3.21",
    "@react-navigation/native": "^6.0.8",
    "@react-navigation/native-stack": "6.9.17",
    "@react-navigation/stack": "^6.3.21",
    "@reduxjs/toolkit": "^1.9.7",
    "@rnmapbox/maps": "10.1.35",
    "@sayem314/react-native-keep-awake": "1.2.3",
    "axios": "1.6.2",
    "i18next": "23.7.9",
    "intl-pluralrules": "2.0.1",
    "lodash.memoize": "4.1.2",
    "lodash.merge": "4.6.2",
    "lodash.set": "4.3.2",
    "luxon": "3.4.4",
    "react": "18.3.1",
    "react-i18next": "13.5.0",
    "react-native": "0.75.4",
    "react-native-auth0": "3.2.1",
    "react-native-awesome-gallery": "0.3.9",
    "react-native-background-fetch": "^4.2.5",
    "react-native-background-geolocation": "4.18.3",
    "react-native-background-timer": "2.4.1",
    "react-native-context-menu-view": "1.16.0",
    "react-native-create-thumbnail": "2.0.0",
    "react-native-device-info": "10.12.0",
    "react-native-fast-image": "8.6.3",
    "react-native-flash-message": "0.4.2",
    "react-native-gesture-handler": "2.20.1",
    "react-native-get-random-values": "1.11.0",
    "react-native-image-crop-picker": "0.41.2",
    "react-native-linear-gradient": "2.8.3",
    "react-native-media-console": "2.2.4",
    "react-native-modalfy": "3.5.2",
    "react-native-nodemediaclient": "0.3.4",
    "react-native-reanimated": "3.17.1",
    "react-native-safe-area-context": "4.11.1",
    "react-native-screens": "3.34.0",
    "react-native-select-dropdown": "3.4.0",
    "react-native-sensitive-info": "5.5.8",
    "react-native-size-matters": "0.4.2",
    "react-native-status-bar-height": "2.6.0",
    "react-native-svg": "^15.2.0",
    "react-native-toast-notifications": "3.4.0",
    "react-native-video": "6.11.0",
    "react-native-vlc-media-player": "1.0.67",
    "react-redux": "7.2.9",
    "reanimated-color-picker": "3.0.4",
    "redux": "4.2.1",
    "redux-devtools-extension": "2.13.9",
    "redux-form": "8.3.10",
    "redux-form-validators": "3.3.2",
    "redux-persist": "6.0.0",
    "redux-persist-sensitive-storage": "1.0.0",
    "redux-saga": "1.2.3",
    "socket.io-client": "4.8.1",
    "uuid": "9.0.1"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "@babel/eslint-parser": "^7.23.3",
    "@babel/plugin-proposal-optional-chaining": "^7.21.0",
    "@babel/preset-env": "^7.20.0",
    "@babel/runtime": "^7.20.0",
    "@react-native/babel-preset": "0.75.4",
    "@react-native/eslint-config": "0.75.4",
    "@react-native/metro-config": "0.75.4",
    "@react-native/typescript-config": "0.75.4",
    "@types/lodash.memoize": "^4.1.9",
    "@types/lodash.merge": "^4.6.9",
    "@types/luxon": "^3.4.2",
    "@types/react": "^18.2.45",
    "@types/react-native-background-timer": "^2.0.2",
    "@types/react-native-video": "5.0.20",
    "@types/react-test-renderer": "^18.0.0",
    "@types/redux-form": "^8.3.10",
    "@types/uuid": "^9.0.8",
    "@types/webpack-env": "^1.18.4",
    "@typescript-eslint/eslint-plugin": "^5.62.0",
    "@typescript-eslint/parser": "^5.62.0",
    "babel-eslint": "^10.1.0",
    "babel-jest": "^29.6.3",
    "babel-plugin-dotenv-import": "^3.0.1",
    "babel-plugin-inline-import": "^3.0.0",
    "babel-plugin-module-resolver": "^5.0.0",
    "babel-plugin-transform-remove-console": "^6.9.4",
    "eslint": "^8.19.0",
    "eslint-config-airbnb": "^19.0.4",
    "eslint-config-airbnb-typescript": "^17.1.0",
    "eslint-config-eslint": "^9.0.0",
    "eslint-plugin-array-func": "^4.0.0",
    "eslint-plugin-import": "^2.29.0",
    "eslint-plugin-jsx-a11y": "^6.8.0",
    "eslint-plugin-optimize-regex": "^1.2.1",
    "eslint-plugin-react": "^7.33.2",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-native": "^4.1.0",
    "jest": "^29.2.1",
    "patch-package": "^8.0.0",
    "prettier": "2.8.8",
    "react-native-asset": "^2.1.1",
    "react-test-renderer": "18.3.1",
    "typescript": "5.0.4"
  },
  "engines": {
    "node": ">=18"
  },
  "packageManager": "yarn@3.6.4"
}

firebase.json for react-native-firebase v6:

{
  "react-native": {
    "messaging_auto_init_enabled": true,
    "analytics_auto_collection_enabled": false,
    "messaging_android_headless_task_timeout": 60000,
    "messaging_ios_auto_register_for_remote_messages": true,
    "messaging_android_notification_channel_id": "high-priority"
  }
}

iOS

Click To Expand

ios/Podfile:

  • I'm not using Pods
  • I'm using Pods and my Podfile looks like:
# Resolve react_native_pods.rb with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
  'require.resolve(
    "react-native/scripts/react_native_pods.rb",
    {paths: [process.argv[1]]},
  )', __dir__]).strip

platform :ios, min_ios_version_supported
prepare_react_native_project!

linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
  Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
  use_frameworks! :linkage => linkage.to_sym
end

target 'Nexops' do
  config = use_native_modules!
  use_frameworks! :linkage => :dynamic
  $RNFirebaseAsStaticFramework = true
  
  use_react_native!(
    :path => config[:reactNativePath],
   
    # An absolute path to your application root.
    :app_path => "#{Pod::Config.instance.installation_root}/.."
  )

  target 'NexopsTests' do
    inherit! :complete
    # Pods for testing
  end

  pre_install do |installer|
    $RNMapboxMaps.pre_install(installer)

    installer.pod_targets.each do |pod|
      if pod.name.eql?('RNReanimated')
        def pod.build_type
          Pod::BuildType.static_library
        end
      end

      if pod.name.eql?('react-native-video')
        def pod.build_type
          Pod::BuildType.static_library
        end
      end
    end
  end

  post_install do |installer|
    $RNMapboxMaps.post_install(installer)
    # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
    react_native_post_install(
      installer,
      config[:reactNativePath],
      :mac_catalyst_enabled => false,
      # :ccache_enabled => true
    )
  end
end
# N/A

AppDelegate.m:

#import "AppDelegate.h"
#import <Firebase.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTLinkingManager.h>

#import <AVFoundation/AVFoundation.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  self.moduleName = @"Nexops";
  // You can add your custom initial props in the dictionary below.
  // They will be passed down to the ViewController used by React Native.
  self.initialProps = @{};

  [FIRApp configure];

  AVAudioSession *session = AVAudioSession.sharedInstance;
  NSError *error = nil;

  if (@available(iOS 10.0, *)) {
      [session
        setCategory:AVAudioSessionCategoryPlayAndRecord
        mode:AVAudioSessionModeVoiceChat
        options:AVAudioSessionCategoryOptionDefaultToSpeaker|AVAudioSessionCategoryOptionAllowBluetooth
        error:&error];
  } else {
    SEL selector = NSSelectorFromString(@"setCategory:withOptions:error:");
    
    NSArray * optionsArray =
        [NSArray arrayWithObjects:
          [NSNumber numberWithInteger:AVAudioSessionCategoryOptionAllowBluetooth],
          [NSNumber numberWithInteger:AVAudioSessionCategoryOptionDefaultToSpeaker], nil];
    
    [session
      performSelector:selector
      withObject: AVAudioSessionCategoryPlayAndRecord
      withObject: optionsArray
    ];
    
    [session 
      setMode:AVAudioSessionModeVoiceChat 
      error:&error
    ];
  }
  
  [session 
    setActive:YES 
    error:&error
  ];

  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

// - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
//   NSLog(@"DEVICE TOKEN: %@", deviceToken.description);
// }

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
  return [self bundleURL];
}

- (NSURL *)bundleURL
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
{
  return [RCTLinkingManager application:app openURL:url options:options];
}

@end

// 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:

// N/A

android/app/build.gradle:

// N/A

android/settings.gradle:

// N/A

MainApplication.java:

// N/A

AndroidManifest.xml:

<!-- N/A -->


Environment

Click To Expand

react-native info output:

 System:
  OS: macOS 15.2
  CPU: (10) arm64 Apple M1 Pro
  Memory: 98.36 MB / 16.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 18.20.4
    path: ~/.nvm/versions/node/v18.20.4/bin/node
  Yarn: Not Found
  npm:
    version: 10.7.0
    path: ~/.nvm/versions/node/v18.20.4/bin/npm
  Watchman:
    version: 2022.11.28.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.14.3
    path: /Users/dev/.rvm/gems/ruby-2.7.5/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 24.2
      - iOS 18.2
      - macOS 15.2
      - tvOS 18.2
      - visionOS 2.2
      - watchOS 11.2
  Android SDK:
    API Levels:
      - "28"
      - "30"
      - "31"
      - "32"
      - "33"
      - "34"
    Build Tools:
      - 29.0.2
      - 29.0.3
      - 30.0.2
      - 31.0.0
      - 32.0.0
      - 33.0.0
      - 33.0.1
      - 33.0.2
      - 34.0.0
    System Images:
      - android-32 | Desktop ARM 64 v8a
      - android-32 | Desktop Intel x86 Atom_64
      - android-32 | Google APIs Intel x86 Atom_64
      - android-33 | Google APIs ARM 64 v8a
      - android-34 | Google Play ARM 64 v8a
    Android NDK: Not Found
IDEs:
  Android Studio: 2022.1 AI-221.6008.13.2211.9514443
  Xcode:
    version: 16.2/16C5032a
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.9
    path: /usr/bin/javac
  Ruby:
    version: 2.7.5
    path: /Users/dev/.rvm/rubies/ruby-2.7.5/bin/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.3.1
    wanted: 18.3.1
  react-native:
    installed: 0.75.4
    wanted: 0.75.4
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: true
  newArchEnabled: false
  • 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:
    • 21.12.3
  • Firebase module(s) you're using that has the issue:
    • messaging
  • Are you using TypeScript?
    • Y & 5.0.4


Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions