On the server side we are using amazon sns service for the fcm communication with the devices, so the token returned from
firebase.messaging().getToken()
is just too long.
So we've figured we should get the token with getAPNStoken call
import firebase from 'react-native-firebase'
const token = await firebase.messaging().ios.getAPNSToken() // null
only that this call returns null no matter what I try, the documentation isn't very clear about how to use and use cases, but I guess that it should be inferred from the name.
anyhow, I've also tried to register first using
firebase.messaging().ios.registerForRemoteNotifications().then(() =>
const token = firebase.messaging().ios.getAPNSToken()) // null
still no success.
ios/Podfile
:# Uncomment the next line to define a global platform for your project
platform :ios, '10.0'
require_relative '../node_modules/@unimodules/core/podfile-macro'
# The target name is most likely the name of your project.
target 'broadcaster' do
# Your 'node_modules' directory is probably in the root of your project,
# but if not, adjust the `:path` accordingly
pod 'React', :path => '../node_modules/react-native', :subspecs => [
'Core',
'CxxBridge', # Include this for RN >= 0.47
'DevSupport', # Include this to enable In-App Devmenu if RN >= 0.43
'RCTText',
'RCTNetwork',
'RCTWebSocket', # Needed for debugging
'RCTAnimation', # Needed for FlatList and animations running on native UI thread
'RCTImage'
# Add any other subspecs you want to use in your project
]
# Explicitly include Yoga if you are using RN >= 0.42.0
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
# Third party deps podspec link
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
pod 'RNVectorIcons', :path => '../node_modules/react-native-vector-icons'
pod 'EXFont', path: '../node_modules/expo-font/ios'
pod 'EXImagePicker', path: '../node_modules/expo-image-picker/ios'
pod 'react-native-orientation-locker', :path => '../node_modules/react-native-orientation-locker/react-native-orientation-locker.podspec'
pod 'EXAV', path: '../node_modules/expo-av/ios'
pod 'RNImageCropPicker', :path => '../node_modules/react-native-image-crop-picker'
pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
pod 'Firebase/Core', '~> 5.15.0'
pod 'Firebase/Messaging', '~> 5.15.0'
use_unimodules!
end
AppDelegate.m
:/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "AppDelegate.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <EXCore/EXModuleRegistry.h>
#import <EXReactNativeAdapter/EXNativeModulesProxy.h>
#import <EXReactNativeAdapter/EXModuleRegistryAdapter.h>
#import "Orientation.h"
#import <Firebase.h>
#import "RNFirebaseNotifications.h"
#import "RNFirebaseMessaging.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[FIRApp configure];
[RNFirebaseNotifications configure];
self.moduleRegistryAdapter = [[EXModuleRegistryAdapter alloc] initWithModuleRegistryProvider:[[EXModuleRegistryProvider alloc] init]];
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"broadcaster" initialProperties:nil];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
[[RNFirebaseNotifications instance] didReceiveLocalNotification:notification];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo
fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
[[RNFirebaseNotifications instance] didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
[[RNFirebaseMessaging instance] didRegisterUserNotificationSettings:notificationSettings];
}
- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge
{
NSArray<id<RCTBridgeModule>> *extraModules = [_moduleRegistryAdapter extraModulesForBridge:bridge andExperience:nil];
// If you'd like to export some custom RCTBridgeModules that are not Expo modules, add them here!
return extraModules;
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge {
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
}
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return [Orientation getOrientation];
}
@end
ADD_SOMETHING_HERE
e.g. iOS 10 or Android API 28N/A
N/A
N/A
React Native
version:0.57.3
React Native Firebase
library version:5.2.3
Firebase
module(s) you're using that has the issue:TypeScript
?N/A
ExpoKit
?ExpoKit
I have seen the same issue. I was able to get the APNs token only on first launch though.
@nigel-smk the first launch of the app? cause I didn't managed to even make that happen
@naorzr I think I have solved this.
I found this issue for a competing library that had the same issue
I don't understand it entirely but it seems that we need to registerForRemoteNotifications first.
The react-native-firebase
messaging reference docs are currently broken. But if we dig into the docs in the repo we find that react-native-firebase
has the registerForRemoteNotifications
method as well.
This reliably got me the APNs Token:
firebase.messaging().ios.registerForRemoteNotifications().then(() => {
firebase.messaging().ios.getAPNSToken().then(token => {
// token not null
});
})
While this did not:
firebase.messaging().ios.getAPNSToken().then(token => {
// token always null
});
Based on my reading of the solution to https://github.com/evollu/react-native-fcm/issues/510 I think that this issue is a bug with react-native-firebase
@nigel-smk thanks for taking your time with the comment
though I have done it, and still getting null..(as written in the original post)
is the token not being null behaviour persistent for you?
@naorzr Are you using a real device? The simulator will never get and APNs token
When running on a real device I get the above described behaviour every time. I have switched between the two appraoches 3-4 times now and without the register call I always get null.
@nigel-smk yea I am
@nigel-smk any chance you could please post here your AppDelegate.m and Podfile?
Can't get this to work no matter what, reinstalled and refollowed the tutorials over and over.
well in the end i've reinstalled, reconfiged everything from scratch and it was resolved.
I'm having the same issue
Add this function to AppDelegate.m:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[FIRMessaging messaging].APNSToken = deviceToken;
}
Hope this will be helpful.
I was having the same issue for days and nothing from the above helped, but I got it working myself.
I just added this to didFinishLaunchingWithOptions
method in AppDelegate.m
:
[[UIApplication sharedApplication] registerForRemoteNotifications];
This is kind of strange, but for me this was behavior on ios device:
console.log(await firebase.messaging().hasPermission()) // false
console.log(await firebase.messaging().getToken()) // got FCM token
console.log(await firebase.messaging().ios.getAPNSToken()) // null
When I requested permissions:
console.log(await firebase.messaging().hasPermission()) // false
console.log(await firebase.messaging().requestPermission()) // allow on popup
console.log(await firebase.messaging().getToken()) // got FCM token
console.log(await firebase.messaging().ios.getAPNSToken()) // got APNS token
So also try to check permissions 馃槃 It is kind of weird that you will get FCM token but no APNS I would expect the same behavior for both
The point here seems to be that even if method hasPermission() returns true, you need to call requestPermission() in order to get the APNS token
I was running into this issue despite trying everything above until just recently.
Turns out my GoogleService-Info.plist
file was not correctly added to my ios
project folder. Once I added it at the same level as AppDelegate.m
in XCode firebase.messaging().ios.getAPNSToken()
returned an actual APNS token instead of null
.
This helped me get the APNS token:
firebase
.messaging()
.ios.registerForRemoteNotifications()
.then(() => {
console.log('REGISTER FOR REMOTE NOTIFICATIONS');
firebase
.messaging()
.ios.getAPNSToken()
.then(token => {
console.log(
'APNS TOKEN AFTER REGISTRATION FOR BACKGROUND',
token,
);
});
});
In my case, calling ios.registerForRemoteNotifications() in release build:
firebase.messaging().ios.registerForRemoteNotifications().then(() => {
firebase.messaging().ios.getAPNSToken().then((apnsToken) => {
console.log(apnsToken)
})
})
apnsToken sometime null, is this normal behavior?
I was having the same issue for days and nothing from the above helped, but I got it working myself.
I just added this todidFinishLaunchingWithOptions
method inAppDelegate.m
:
[[UIApplication sharedApplication] registerForRemoteNotifications];
This really helped me! Thank you so much buddy!
Even using registerForRemoteNotifications
before calling getAPNSToken
I get null the first time after the app launches.
await firebase.messaging().ios.registerForRemoteNotifications();
const apnsToken = await firebase.messaging().ios.getAPNSToken();
apnsToken === null
Then when calling getAPNSToken
again later, it correctly returns the token.
I'm suspecting that the promise returned from registerForRemoteNotifications
does not wait for the token to be registered before resolving, so I think it shouldn't be returning a promise at all.
I think adding a registerForRemoteNotifications
or didRegisterForRemoteNotificationsWithDeviceToken
in AppDelegate.m
is not a solid solution because it may still cause a race condition where the token has not been registered before getAPNSToken
is called. (if registering for token takes longer than the JS code takes to call getAPNSToken
). This is probably why people are seeing that it works sometimes and other times not.
Although very hacky, this seems to work and will never return null:
async function getAPNSToken() {
while (true) {
const apnsToken = await firebase.messaging().ios.getAPNSToken();
if (apnsToken !== null) return apnsToken;
await new Promise((resolve) => setTimeout(resolve, 1000));
}
}
await firebase.messaging().ios.registerForRemoteNotifications();
const apnsToken = await getAPNSToken();
Most helpful comment
Add this function to AppDelegate.m:
Hope this will be helpful.