Closed MahmudHasanMenon closed 3 years ago
App.js first register call does not appear to be async and awaiting, so it will just return right?
It will be something like that - order of operations / race conditions related to incorrect async usage - you'll have to play around with the code and that idea to get it correct
This is project-specific, the module works correctly in this area
@mikehardy i have played with my code and changed it as you proposed but the same error occur in my FCM-service.js
class FcmService {
// we use this method to register notification service in our app.
// we call this method in componetDidMount() so, we app load we get permission to
// display notification.
register = (onNotification, onOpenNotification) =>{
this.checkPermission(onNotification, onOpenNotification)
// when register function call that time we create notification listener
//this.createNoitificationListeners(onRegister, onNotification, onOpenNotification)
}
registerAppWithFCM = (onNotification, onOpenNotification) => {
if(Platform.OS === 'ios') {
messaging().registerDeviceForRemoteMessages()
.then( (register) => {
this.getToken(onNotification, onOpenNotification)
});
//await messaging().setAutoInitEnabled(true);
}
else {
this.getToken(onNotification, onOpenNotification)
}
}
checkPermission = (onNotification, onOpenNotification) => {
messaging().hasPermission()
.then(enabled => {
if (enabled) {
this.registerAppWithFCM(onNotification, onOpenNotification)
//user has permission
} else {
//user don't have permission
this.requestPermission(onNotification, onOpenNotification)
}
}).catch(error => {
this.requestPermission(onNotification, onOpenNotification)
let err = `check permission error${error}`
Alert.alert(err)
// console.log("[FCMService] Permission rejected", error)
})
}
getToken = async (onNotification, onOpenNotification) => {
let fcmToken = await AsyncStorage.getItem(Constants.FCM_TOKEN);
if(!fcmToken) {
messaging().getToken()
.then(fcmToken => {
Alert.alert(fcmToken)
if (fcmToken) {
this.setToken(fcmToken)
this.createNoitificationListeners(onNotification, onOpenNotification)
//onRegister(fcmToken)
} else {
Alert.alert("[FCMService] User does not have a device token")
// console.log("[FCMService] User does not have a device token")
}
}).catch(error => {
let err = `FCm token get error${error}`
Alert.alert(err)
// console.log("[FCMService] getToken rejected ", error)
})
}
else {
this.createNoitificationListeners(onNotification, onOpenNotification)
}
}
async setToken(token) {
await AsyncStorage.setItem(Constants.FCM_TOKEN, token);
}
requestPermission = (onNotification, onOpenNotification) => {
messaging().requestPermission().then(() => {
this.registerAppWithFCM(onNotification, onOpenNotification)
}).catch(error => {
// console.log("[FCMService] Requested persmission rejected ", error)
})
}
deletedToken = async () => {
await messaging().deleteToken()
.catch(error => {
// console.log("Delected token error ", error)
})
}
createNoitificationListeners = (onNotification, onOpenNotification) => {
messaging().onNotificationOpenedApp(remoteMessage => {
Alert.alert(remoteMessage)
// console.log("[FCMService] onNotificationOpenedApp Notification caused app to open from background state:", remoteMessage);
if(remoteMessage) {
onOpenNotification(remoteMessage)
}
});
// when the application is opened form a quit state
messaging()
.getInitialNotification()
.then(remoteMessage => {
Alert.alert(remoteMessage)
// console.log('[FCMService] getInitialNotification Notification caused app to open from quit state:', remoteMessage);
if (remoteMessage) {
onOpenNotification(remoteMessage)
}
}
);
// Foreground state messages
this.messageListener = messaging().onMessage(async remoteMessage => {
Alert.alert(remoteMessage)
//console.log("[FCMService] A new FCM message arrived", remoteMessage);
if(remoteMessage) {
let notification = null;
if(Platform.OS === 'ios') {
notification = remoteMessage
} else {
notification = remoteMessage
}
onNotification(notification);
}
});
// Triggered when have new token
messaging().onTokenRefresh(fcmToken => {
// console.log("New token refresh: ", fcmToken)
this.setToken(fcmToken)
})
}
unRegister = () => {
this.messageListener()
}
}
in App.js
componentDidMount() {
this._isMounted = true;
if (Platform.OS === 'android') {
setTimeout(() => SplashScreen.hide(), 200);
}
if (Platform.OS === 'ios') {
SplashScreen.hide()
}
fcmService.register(this.onNotification, this.onOpenNotification);
}
@mikehardy why this issue is closed? I couldn't resolve it yet. In ios simulator it gets FCM Token but in ios real device same problem occur again.
@mikehardy this problem is only happening when i upgrade my react-native version from 0.61.0 to 0.61.2.
I was sure that was going to be it. You were calling an async function without an await and suffering from what seemed like a race condition...I'm surprised there was no effect. I'll have a look at the code when I can get a chance (warning: it won't be for a day or two earliest) but if you're still having the problem we can certainly reopen.
@mikehardy i have provided my fcm-service file above, please going through it, help me where i should change my code. I am still facing this issue. i can not get device token and the same error occur
@MahmudHasanMenon
1- formatting of code blocks is with triple-backticks enclosing, and an optional language specifier, I fixed your code blocks so they are readable 2- your use of asynchronous code here is very hard to follow. It still just does not look correct here
I want to emphasize that this is one of the most important features of the library and has been for years, and no one else is reporting this. The problem is in your usage of the API, not the API.
I'm not sure exactly what's going on with your code, but if App.js looked more like this:
import messaging from '@react-native-firebase/messaging';
async componentDidMount() {
try {
// Ignore all that permission request stuff. You need to do it but it is UNRELATED to tokens.
// Handle your permissions separately. Ideally with react-native-permissions
// From the example https://rnfirebase.io/messaging/server-integration#saving-tokens
const token = await messaging().getToken();
console.log('we have a token and should do something with it: ' + token);
// Listen to whether the token changes
let tokenRefreshListenerUnsubscriber = messaging().onTokenRefresh(token => {
console.log('we have a refreshed token and should do something with it: ' + token);
});
} catch (e) {
console.error('token registration failed?', e);
}
}
...and then you implemented the handlers as described here https://rnfirebase.io/messaging/usage#receiving-messages and registered them before your App is registered, it would work.
I don't believe anything else you are doing is necessary, and worse, it's incorrect code and harmful, leading to your issues.
The upgrade from react-native versions is I think unrelated.
@mikehardy thanks for helping and sharing code. I have implemented your code and listen your instruction but although i can't get token.Here is some screenshot and code.
App.js file
async componentDidMount() {
this._isMounted = true;
//this.checkPermission();
try {
// Ignore all that permission request stuff. You need to do it but it is UNRELATED to tokens.
// Handle your permissions separately. Ideally with react-native-permissions
// From the example https://rnfirebase.io/messaging/server-integration#saving-tokens
const token = await messaging().getToken();
console.log('we have a token and should do something with it: ' + token);
Alert.alert(token)
if(token) {
await AsyncStorage.setItem(Constants.FCM_TOKEN, token);
}
// Listen to whether the token changes
let tokenRefreshListenerUnsubscriber = messaging().onTokenRefresh(token => {
console.log('we have a refreshed token and should do something with it: ' + token);
});
} catch (e) {
let error = `token registration failed? ${e}`
Alert.alert(error)
console.error('token registration failed?', e);
}
this.createNoitificationListeners()
}
triple backticks to format code. I fixed your comment https://www.markdownguide.org/extended-syntax/#syntax-highlighting
text is strongly preferred over images (I'm on mobile, it's hard to do images etc)
So you're not registered for remote messages. Did you investigate how remote message registration happens?
You'll note the phrase here: https://rnfirebase.io/reference/messaging#registerDeviceForRemoteMessages
On iOS, if your app wants to receive remote messages from FCM (via APNs), you must explicitly register with APNs if auto-registration has been disabled.
Have you disabled auto-registration? Something about your project-specific implementation or configuration may have done that?
If not, this would be called: https://github.com/invertase/react-native-firebase/blob/791bc9a7faa17b05845865ec099e1deb64780feb/packages/messaging/ios/RNFBMessaging/RNFBMessaging%2BNSNotificationCenter.m#L129-L132
And it should work, unless you are missing something here:
https://rnfirebase.io/messaging/usage/ios-setup
Now that you've got a async/try/await/catch code block working correctly you can try adding a manual messaging().registerForRemoteMessages() call to see what error pops out maybe
But I will emphasize that it works, all of it works if a project is integrated and configured according to the docs. I spent most of yesterday implementing some remote messaging features on my work project where device-specific (token-based) messaging is critical. Something is wrong with your specific project
@mikehardy i didn't do anything. I just downgrade my version from 0.63 to 0.61.0. Everything works fine on 0.63 version but when i downgrade it throws that error.
@mikehardy where this file exists?
react-native-firebase/packages/messaging/ios/RNFBMessaging/RNFBMessaging+NSNotificationCenter.m
@MahmudHasanMenon It's open source, so you can find it in the repository, right where I linked it. It'll be in your node_modules once you install the messaging module.
@mikehardy i found that in my code-base
#if !(TARGET_IPHONE_SIMULATOR)
if ([[RNFBJSON shared] getBooleanValue:@"messaging_ios_auto_register_for_remote_messages" defaultValue:YES]) {
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
Triple backticks for code formatting.
@mikehardy how can i ensure that i am or my project configuration disable auto-registration?
I don't know. You might try launching the app from Xcode on a real device and setting breakpoints during messaging initialization to see? It has always just worked for me.
I imagine if you make a demo / throwaway project from https://github.com/mikehardy/rnfbdemo/blob/master/make-demo.sh it will work as well
@mikehardy actually i create a relaese API build and also connect my device with debug build. every times i see this exception throws.
What did the breakpoints tell you?
@mikehardy
in App.js file
let remoteRegister = await messaging().registerForRemoteMessages()
Alert.alert(remoteRegister)
sorry for bad image quality
@mikehardy
my AppDelegate.m
file
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* 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/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <Firebase.h>
#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>
#import <GoogleMaps/GoogleMaps.h>
#import "RNSplashScreen.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[GMSServices provideAPIKey:@"AIzaSyBALbK0zTosrX4J1sl9-k1wJt14Zuwk37M"];
if ([FIRApp defaultApp] == nil) {
[FIRApp configure];
}
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"APPBusinessPlaza63"
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];
// Define UNUserNotificationCenter
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[RNSplashScreen show];
return YES;
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}
// Required to register for notifications
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
[RNCPushNotificationIOS didRegisterUserNotificationSettings:notificationSettings];
}
// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
[RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
[RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}
// IOS 10+ Required for localNotification event
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler
{
[RNCPushNotificationIOS didReceiveNotificationResponse:response];
completionHandler();
}
// IOS 4-10 Required for the localNotification event.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
[RNCPushNotificationIOS didReceiveLocalNotification:notification];
}
//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
}
@end
my Info.plist
file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>Bundle ID</string>
<key>CFBundleURLSchemes</key>
<array>
<string>com.webmascot.bp</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>com.googleusercontent.apps.558394662083-po8okplh2v0cvc91r76rkau73tddkpj7</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>fb469065720287765</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>UIAppFonts</key>
<array>
<string>Axiforma_Bold.ttf</string>
<string>Axiforma_Book.ttf</string>
<string>Axiforma_Light.ttf</string>
<string>Axiforma_Medium.ttf</string>
<string>Axiforma_Regular.ttf</string>
<string>MaterialIcons.ttf</string>
<string>MaterialCommunityIcons.ttf</string>
<string>Poppins-Black.ttf</string>
<string>Poppins-BlackItalic.ttf</string>
<string>Poppins-Bold.ttf</string>
<string>Poppins-BoldItalic.ttf</string>
<string>Poppins-ExtraBold.ttf</string>
<string>Poppins-ExtraBoldItalic.ttf</string>
<string>Poppins-ExtraLight.ttf</string>
<string>Poppins-ExtraLightItalic.ttf</string>
<string>Poppins-Italic.ttf</string>
<string>Poppins-Light.ttf</string>
<string>Poppins-LightItalic.ttf</string>
<string>Poppins-Medium.ttf</string>
<string>Poppins-MediumItalic.ttf</string>
<string>Poppins-Regular.ttf</string>
<string>Poppins-SemiBold.ttf</string>
<string>Poppins-SemiBoldItalic.ttf</string>
<string>Poppins-Thin.ttf</string>
<string>Poppins-ThinItalic.ttf</string>
<string>Roboto-Black.ttf</string>
<string>Roboto-BlackItalic.ttf</string>
<string>Roboto-Bold.ttf</string>
<string>Roboto-BoldItalic.ttf</string>
<string>Roboto-Italic.ttf</string>
<string>Roboto-Light.ttf</string>
<string>Roboto-Medium.ttf</string>
<string>Roboto-Regular.ttf</string>
<string>Roboto-Thin.ttf</string>
<string>Roboto_medium.ttf</string>
<string>Roboto.ttf</string>
<string>rubicon-icon-font.ttf</string>
</array>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>remote-notification</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
What did the breakpoints tell you?
@mikehardy actually i set alert when registerForRemoteMessages() and getToken() and give those screenshot above. Ok i will see the breakpoints in xcode console what it says. now i have no real device to test, i just make a IPA file and test it on Browser Stack, so i use Alert to show the error.
You will not be able to effectively develop an ios app with messaging without a real device. I wouldn't spend the time trying personally. I scrounged up a crappy iPhone SE (the old one!) to test, for instance.
@mikehardy actually i am testing on iphone also by my office collegue. As i am working remotely so i can't connect the device with my pc but i gave my collegue those instruction and he gave me those errors in by Alert. I will tell you tomorrow what you want to know.
Just to be clear, you're looking for information because you want to know it. You want this info to follow the path so you can fix your own problem. I'm just some guy on the internet right? Not to trying to be rude but mentally you need to take ownership of this problem, because you're the only one having it. Any answer I give is just meant to be a guide
@mikehardy i got a log
The default Firebase app has not yet been configured. Add `[FIRApp configure];` (`FirebaseApp.configure()` in Swift) to your application initialization
Why do you continue using the simulator for messaging testing? Please stop. What did the breakpoints tell you? You need to own this problem. Dig in hard, I do not have the time to lead you through it, I am sorry
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.
I'm facing same issue. How come no-one has faced this issue yet?
I've followed the instruction what is mentioned on firebase documentation.
Error: [messaging/unregistered] You must be registered for remote messages before calling getToken, see messaging().registerDeviceForRemoteMessages(). NativeFirebaseError: [messaging/unregistered] You must be registered for remote messages before calling getToken, see messaging().registerDeviceForRemoteMessages().
I'm facing same issue. How come no-one has faced this issue yet?
I've followed the instruction what is mentioned on firebase documentation.
Error: [messaging/unregistered] You must be registered for remote messages before calling getToken, see messaging().registerDeviceForRemoteMessages(). NativeFirebaseError: [messaging/unregistered] You must be registered for remote messages before calling getToken, see messaging().registerDeviceForRemoteMessages().
You have to enable push notification on signing & Capabilities ....
@MahmudHasanMenon Did you solve it?
For me, You have to enable push notification on signing & Capabilities
was enabled, but it did say (release)
in brackets. Re-adding this from + Capability
fixed the error
I have the same problem but when I completed these steps https://rnfirebase.io/messaging/usage/ios-setup#1-registering-a-key it's working fine now
For me, You have to enable push notification on signing & Capabilities was enabled, but it did say (release) in brackets. Re-adding this from + Capability fixed the error
This really worked!! I have been stuck for half day because it. Checking everything else but not working. Only this one works!
@mikehardy I think when users decline the push permission we also get this error
Found this thread from https://github.com/invertase/react-native-firebase/issues/4788 which is locked already.
I ended up with this issue(4788 "You must be registered for remote messages before calling getToken" on iOS) when there was a merging conflict and my coworker accidentally deleted aps-environment from entitlement file.
I added these lines back to the [TARGET].entitlements files.
<key>aps-environment</key>
<string>development</string>
It is working for me again.
A bit offtopic but I have to say this - reading this, I can't believe how patient you are @mikehardy. Even while reading the conversation my stomach got tense. I don't know you, but thank you :)
I solved the problem in this article have a look https://medium.com/@saadkhalil773/react-native-push-notification-0381af2252d2
Please check carefully in the Signing & Capability
section. It should be set to Push Notification
only, not Push Notification (Debug)
, and should also include Background Modes
. Hope this helps!
I am using react-native-firebase v8 and react-native v0.61.2. I have recently upgraded my react-native version from 0.61.0 to 0.61.2. In android everything works perfect but in ios real device messaging.getToken() throw error in catch block, not getting any token. said that your device is not registered. Error:-
my FCM-service file
in
App.js
file i called that methodmy
AppDelegate.m
file