-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
🔥 [🐛] getAPNSToken() just hangs #7272
Comments
Update: I found this in the docs
Though, its the FCM token, and not the APNs token. Is there an equivalent method for that? From the docs
|
Update 🎉 : There seems to be a difference with requesting permissions Because of Android 13, we recently changed to using Here's what made getting the token work again (by using the different permission requests per platform) requestPlatformPermission = async (): Promise<boolean> => {
let status
let isGranted = false
if (isIOS()) {
status = await messaging().requestPermission({
alert: true,
sound: true,
badge: true,
})
isGranted = status === messaging.AuthorizationStatus.AUTHORIZED
} else {
status = await requestNotifications(['alert', 'sound', 'badge'])
isGranted = status.status === RESULTS.GRANTED
}
return new Promise((resolve) => {
resolve(isGranted)
})
} and then using this instead before registering the device: const isGranted = await this.requestPlatformPermission()
if (!isGranted) {
return
}
messaging()
.registerDeviceForRemoteMessages().then(
... getAPNSToken() etc .. any idea why
or are there any other details that I'm missing perhaps? |
I'm having the same issue. @kg-currenxie I'm trying to understand why this issue may be related to requestPermission(), I think the token should be obtain even without calling requestPermission() because you can use the messaging service as data only without notifications and you still need to have a valid token. The same in our case, I'm pretty sure this worked before and returned null instead, I even created an issue here #6464 that the method returned null except the first time it registers for remote messages. The same seems to happen here, first time the app is installed it seems to return a valid token, the following calls (after the app is restarted) seem to hang (a few months before at least returned null instead) |
I couldn't tell you why, just that it worked 😅 with the wrong permission call, getting the token always hung, and changing it made it work 🤷♂️
well that makes sense too :) |
this is critical bug I think specially for apps trying to get the APNS token (after this being a requirement) and the app is live already and has user logged in and registered their devices for me this is happening on version 18.3.1 |
How can an app even function with this bug? I'm at the point where I can better use the native iOS and Android libraries and go with that. EDIT: I misread the documentation and missed the point where it tells to add the |
add this line to node_modules/@react-native-firebase/messaging/ios/RNFBMessaging/RNFBMessagingModule.m! RCT_EXPORT_METHOD(getAPNSToken : (RCTPromiseResolveBlock)resolve : (RCTPromiseRejectBlock)reject) {
NSData *apnsToken = [FIRMessaging messaging].APNSToken;
if (apnsToken) {
resolve([RNFBMessagingSerializer APNSTokenFromNSData:apnsToken]);
} else {
#if TARGET_IPHONE_SIMULATOR
#if !TARGET_CPU_ARM64
DLog(@"RNFBMessaging getAPNSToken - Simulator without APNS support detected, with no token "
@"set. Use setAPNSToken with an arbitrary string if needed for testing.")
resolve([NSNull null]);
return;
#endif
DLog(@"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.");
#endif
if ([UIApplication sharedApplication].isRegisteredForRemoteNotifications == NO) {
[RNFBSharedUtils
rejectPromiseWithUserInfo:reject
userInfo:(NSMutableDictionary *)@{
@"code" : @"unregistered",
@"message" : @"You must be registered for remote messages before "
@"calling getAPNSToken, see "
@"messaging().registerDeviceForRemoteMessages().",
}];
return;
}
// -----> this line
resolve([NSNull null]);
// <-------------
}
}
this is work for me! |
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 attention?
Thank you for your contributions. |
still require attention
…On Mon, 23 Oct 2023 at 04:51, github-actions[bot] ***@***.***> wrote:
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 attention?
This issue will be closed in 15 days if no further activity occurs.
Thank you for your contributions.
—
Reply to this email directly, view it on GitHub
<#7272 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAXWQKHXFWYOW6J7LGRKEP3YAXERPAVCNFSM6AAAAAA3BBI6DGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONZUGMYDSMZUGI>
.
You are receiving this because you commented.Message ID:
***@***.***>
--
*בברכה*
*סאמח אבועואד*
*0527362003*
|
Still needs to be fixed, @appa-gomi 's solution works for us |
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 attention?
Thank you for your contributions. |
Hey, is there any progress on this? I started experiencing this issue after upgrading RN Firebase from v14 to v18.6.2. It doesn't happen always, but from time to time. I am using RN v0.72.7. |
That means the code is functional or it would never work. In the following comment I look more closely at the network failure case, I think that might be the key |
@appa-gomi in your comment #7272 (comment) it does look like you've found a resolution for the method call simply hanging. There appears to be a combination of conditionals where no expected case is hit and the method falls through to the end but without resolving, which would explain the symptoms. Your proposed resolution of the promise with null even seems correct for this case. The only addition might be to add some more DLogs, for example, to resolve with null as you propose, but immediately after the DLog indicating that it is a simulator that should be capable of getting an APNS token, but didn't. Then have another DLog after the check for remote message registration where we note to developers that we are on a real device here and are registered, so we should have gotten a token but perhaps there was a network failure and they should retry. Then resolve with null What do you think? @hollanderbart and @vid3v - you reacted with a thumbs-down on the @appa-gomi proposed change. Is there a technical reason for that? Did you try it and it did not work? I would love to know if that was the case as it seems that change (or something functionally equivalent but just with more developer messaging) should work |
Fixes #7272 with thanks to @appa-gomi !
Fixes #7272 with thanks to @appa-gomi !
Fixes #7272 with thanks to @appa-gomi !
@mikehardy shouldn't we also add |
I do not believe so. This shared utils function takes the reject block as a parameter and calls it, in order to meet it's named purpose of react-native-firebase/packages/messaging/ios/RNFBMessaging/RNFBMessagingModule.m Line 183 in b30eee1
|
@mikehardy sorry to tag you but I'm wondering whether there's still weight to this issue - I think I'm experiencing it. package versions"react-native": "0.72.6", "@react-native-firebase/analytics": "19.2.2", "@react-native-firebase/app": "19.2.2", "@react-native-firebase/messaging": "19.2.2", "expo": "49.0.13", "expo-build-properties": "0.11.1",AppDelegate.mm (auto-generated)#import "AppDelegate.h"
// @generated begin react-native-maps-import - expo prebuild (DO NOT MODIFY) sync-f2f83125c99c0d74b42a2612947510c4e08c423a
#if __has_include(<GoogleMaps/GoogleMaps.h>)
#import <GoogleMaps/GoogleMaps.h>
#endif
// @generated end react-native-maps-import
#import <Firebase/Firebase.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTLinkingManager.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// @generated begin react-native-maps-init - expo prebuild (DO NOT MODIFY) sync-ba3e6dd042f7fe1b7ac3c7cee5c8029c482c489a
#if __has_include(<GoogleMaps/GoogleMaps.h>)
[GMSServices provideAPIKey:@"AIzaSyD8W8_fRaK2QvPeaXDYdak6lyWyHnkB6Qk"];
#endif
// @generated end react-native-maps-init
// @generated begin @react-native-firebase/app-didFinishLaunchingWithOptions - expo prebuild (DO NOT MODIFY) sync-ecd111c37e49fdd1ed6354203cd6b1e2a38cccda
[FIRApp configure];
// @generated end @react-native-firebase/app-didFinishLaunchingWithOptions
self.moduleName = @"main";
// 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 = @{};
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@".expo/.virtual-metro-entry"];
#else
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}
// Linking API
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
return [super application:application openURL:url options:options] || [RCTLinkingManager application:application openURL:url options:options];
}
// Universal Links
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
BOOL result = [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
return [super application:application continueUserActivity:userActivity restorationHandler:restorationHandler] || result;
}
// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
return [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
return [super application:application didFailToRegisterForRemoteNotificationsWithError:error];
}
// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
return [super application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
@end We're experiencing this while using expo managed project setup for firebase, we have auto register set to false in our firebase.json, and have a setup like this: const status = await messaging().hasPermission(); then register for remote notifications: await messaging().registerDeviceForRemoteMessages(); At this point, isDeviceRegisteredForRemoteNotifications returns 'true' but calling const tokenAPNS = await messaging().getAPNSToken();
await messaging().setAPNSToken(tokenAPNS); However, getAPNSToken hangs when i've asked for permission with messaging.requestPermission(), but not react-native-permissions' |
I believe I am currently experiencing the same thing as a regression somehow, as I attempt to run e2e tests locally (and in CI) - but I haven't pinned it down yet. something is not working correctly, but it used to work 100% for me. |
Previously there were cases where notification registration requests would wait indefinitely for the choreography of "request registration from system", "wait for system to respond" completed. There are cases (specifically if you are missing permissions...) where this choreography will never complete. Now we have a delayed async task that waits (for 10 seconds currently) and if it runs and sees that the choreography wasn't complete it cleans up and rejects so you avoid infinite hangs See #7272
Related #7272 - the only difference between react-native-permissions and our requestPermission implementation was an immediate registration for notifications after a successful grant Assuming you would never request permission if you did not want to receive notifications, we now copy this behavior This allows messaging registration and APNS token tests to pass again on capable simulators (after altering tests to use the new permission behavior)
This was extremely frustrating! The details provided here - specifically everyone figuring out that permissions was the difference and that react-native-permissions in particular worked, meant I could find my way to a fix though. The APIs should no longer hang indefinitely no matter what, and our requestPermission method will mirror what react-native-permissions does (an immediate notification registration on successful grant, basically) This should work once #7797 is merged and released Thanks @kg-currenxie @Alex-Whyatt et all, very helpful. |
Previously there were cases where notification registration requests would wait indefinitely for the choreography of "request registration from system", "wait for system to respond" completed. There are cases (specifically if you are missing permissions...) where this choreography will never complete. Now we have a delayed async task that waits (for 10 seconds currently) and if it runs and sees that the choreography wasn't complete it cleans up and rejects so you avoid infinite hangs See #7272
Related #7272 - the only difference between react-native-permissions and our requestPermission implementation was an immediate registration for notifications after a successful grant Assuming you would never request permission if you did not want to receive notifications, we now copy this behavior This allows messaging registration and APNS token tests to pass again on capable simulators (after altering tests to use the new permission behavior)
Previously there were cases where notification registration requests would wait indefinitely for the choreography of "request registration from system", "wait for system to respond" completed. There are cases (specifically if you are missing permissions...) where this choreography will never complete. Now we have a delayed async task that waits (for 10 seconds currently) and if it runs and sees that the choreography wasn't complete it cleans up and rejects so you avoid infinite hangs See #7272
Related #7272 - the only difference between react-native-permissions and our requestPermission implementation was an immediate registration for notifications after a successful grant Assuming you would never request permission if you did not want to receive notifications, we now copy this behavior This allows messaging registration and APNS token tests to pass again on capable simulators (after altering tests to use the new permission behavior)
@mikehardy awesome! |
@mikehardy thanks for looking into this! |
Issue
Hi. For some reason,
messaging().getAPNSToken()
just hangs forever.Yes I'm using a real device.
(Auto init is off, swizzling is on)
I have tried adding
but I'm not sure if that's enough, or if they would actually be called? Though, they don't log anything at all (XCode debugger while having a device connected in release mode)
getAPNSToken()
in a try/catch, but it doesn't seem to throwmessaging().unregisterDeviceFromRemoteMessaging()
before registering, to see if there's some sort of cache or somethingFor the strange part; this has worked before, and no code has changed since (i know i know, sounds like BS) 😄 but i even went back a few commits, to where our QA team successfully tested a whole flow.
Would there be any possibility of Apple having intermittent issues? Seems unlikely.
So the question is, what are the things that could make this function call just hang, without any error logs or warnings? For example, if i call
getToken()
without first callinggetAPNSToken()
, the library does a good job at printing warnings or errors with short explanations. But at this moment, there's just nothing :) Would love more insight from people with a deeper understanding of this 🙏Project Files
Javascript
Click To Expand
package.json
:firebase.json
for react-native-firebase v6:iOS
Click To Expand
ios/Podfile
:AppDelegate.mm
:Environment
Click To Expand
react-native info
output:react-native-firebase
version you're using that has this issue:Firebase
module(s) you're using that has the issue:TypeScript
?React Native Firebase
andInvertase
on Twitter for updates on the library.The text was updated successfully, but these errors were encountered: