Skip to content
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

🔥 [🐛] isHeadless flag on iOS unreliable #5388

Closed
1 of 9 tasks
helenaford opened this issue Jun 3, 2021 · 17 comments
Closed
1 of 9 tasks

🔥 [🐛] isHeadless flag on iOS unreliable #5388

helenaford opened this issue Jun 3, 2021 · 17 comments
Labels
help: needs-triage Issue needs additional investigation/triaging. platform: ios type: bug New bug report Type: Stale Issue has become stale - automatically added by Stale bot Workflow: Needs Review Pending feedback or review from a maintainer.

Comments

@helenaford
Copy link
Member

helenaford commented Jun 3, 2021

The issue is that the isHeadless flag included in @react-native-firebase/messaging is unreliable and causes the app to render null when the app is opened. The flag can be true initially when the app is launching but does not update to false when the app is in the foreground.

Please see this code snippet which is taken from the docs:

// index.js
import { AppRegistry } from 'react-native';
import messaging from '@react-native-firebase/messaging';

messaging().setBackgroundMessageHandler(async remoteMessage => {
  console.log('Message handled in the background!', remoteMessage);
});

function HeadlessCheck({ isHeadless }) {
  if (isHeadless) {
    // App has been launched in the background by iOS, ignore
    return null;
  }

  return <App />;
}

function App() {
  // Your application
}

AppRegistry.registerComponent('app', () => HeadlessCheck);

There have been previous discussions around the usage of this flag:
#4163
#4304

Some suggestions to listen to AppState rather than use the isHeadless flag but it's unclear what the best solution is to prevent the app from rendering when it's in a headless state.

From reading the discussions, it's clear the isHeadless flag causes unpredictable results, is there anything that can be done in the library to fix the flag?

Or, can the docs be updated to show a recommended solution?


Project Files

Javascript

Click To Expand

package.json:

# N/A

firebase.json for react-native-firebase v6:

# N/A

iOS

Click To Expand

ios/Podfile:

  • I'm not using Pods
  • I'm using Pods and my Podfile looks like:
# N/A

AppDelegate.m:

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    ...
    if ([FIRApp defaultApp] == nil) {
        [FIRApp configure];
    }
    ...

    NSDictionary *appProperties = [RNFBMessagingModule addCustomPropsToUserProps:nil withLaunchOptions:launchOptions];

    RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                     moduleName:@"xxx"
                                              initialProperties:appProperties];

    ...

    [RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView];

    return YES;
}


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:

 OUTPUT GOES HERE
  • Platform that you're experiencing the issue on:
    • [ x] 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:
    • e.g. 5.4.3
  • Firebase module(s) you're using that has the issue:
    • e.g. Instance ID Messaging
  • Are you using TypeScript?
    • Y/N & VERSION Y


@miallo
Copy link

miallo commented Jul 7, 2021

Is there a place where I can look into this thing and see if I can find the problem? This bug is causing us quite some troubles...

@mikehardy
Copy link
Collaborator

mikehardy commented Jul 7, 2021

This is an area of some pain that I've looked into a bit yes. We use detox as our testing solution in the e2e app and unfortunately it does not allow for running on-device on iOS devices, so near as I can tell there is no way to make an automated test for it.

So I think the best path is actually to carefully (that is, take care not to npm/yarn install as it will potentially blow away your changes) reach right into node_modules and then roll up the sleeves and get dirty with the .m and .js files directly in the messaging module

It appears based on my understanding of the problem that there are a couple of things:

This may actually fail if used on android? There is no android implementation - but this is a tangent:

getIsHeadless() {
return this.native.getIsHeadless();
}

This implementation which is checking for foreground or background:

if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
appProperties[@"isHeadless"] = @([RCTConvert BOOL:@(YES)]);
}

Is probably best not as a property that is accessed but as something that is determined each time here:

RCT_EXPORT_METHOD(getIsHeadless
:(RCTPromiseResolveBlock) resolve
:(RCTPromiseRejectBlock) reject
) {
RNFBMessagingNSNotificationCenter* notifCenter = [RNFBMessagingNSNotificationCenter sharedInstance];
return resolve(@([RCTConvert BOOL:@(notifCenter.isHeadless)]));
}

Then it would accurately reflect whether the app is in the background or not?

@mikehardy
Copy link
Collaborator

(hit enter too soon, updated comment above - https://github.com/ds300/patch-package may be used to test your changes more reliably, and then the same work can be proposed as a PR here?)

@miallo
Copy link

miallo commented Jul 8, 2021

A bit of debugging later...
Here we successfully register the listener for getting into foreground

[[NSNotificationCenter defaultCenter] addObserver:strongSelf selector:@selector(application_onDidEnterForeground) name:UIApplicationWillEnterForegroundNotification object:nil];

The docs say that the selector function

must have one and only one argument

but even if we add that, it does not change that this function is never called


So here we never set the isHeadless to false
appPropertiesDict[@"isHeadless"] = @([RCTConvert BOOL:@(isHeadless)]);

The default YES value is also never called and the only reference we could find for the addCustomPropsToUserProps function is in the respective .h file.

+ (NSDictionary *)addCustomPropsToUserProps:(NSDictionary *_Nullable)userProps withLaunchOptions:(NSDictionary *_Nullable)launchOptions {

I have to say my knowledge about how RN works is even less than how ObjC is working but maybe this is a first hint?

@miallo
Copy link

miallo commented Jul 8, 2021

Right... If I only followed the instructions to update the AppDelegate.m I would have called the addCustomPropsToUserProps myself... Sorry for my stupidity...

@ease-space
Copy link

This code fixed bug
Снимок экрана 2021-09-18 в 17 20 25

@mym0404
Copy link

mym0404 commented Feb 17, 2022

if i send message with content-available in quit state, isHeadless is true during next app open time

@stale
Copy link

stale bot commented Apr 16, 2022

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.

@stale stale bot added the Type: Stale Issue has become stale - automatically added by Stale bot label Apr 16, 2022
@stale
Copy link

stale bot commented May 1, 2022

Closing this issue after a prolonged period of inactivity. If this is still present in the latest release, please feel free to create a new issue with up-to-date information.

@stale stale bot closed this as completed May 1, 2022
@patissier-boulanger
Copy link

if i send message with content-available in quit state, isHeadless is true during next app open time

Same here. If i remove content-available in json, isHeadless works fine.

@yuvraj-scalex
Copy link

This issue is surfacing in our production app and redirects users to the blank screen as isHeadless is true when the app is launched from the quit state. Even though we return <App /> component when isHeadless is true, it is completely messing up with the navigation of the App.
Is there any way we can fix this?
RN version: 0.68.5
react-native-firebase: 17.4.1
react: 17.0.2

@yuvraj-scalex
Copy link

Hello @mikehardy, can you pl suggest something to get rid of this issue?
We've upgraded the react-native-firebase packages but still have no luck with this issue, should we upgrade the react-native version as well?

@mikehardy mikehardy reopened this Apr 14, 2023
@mikehardy mikehardy added platform: ios Workflow: Needs Review Pending feedback or review from a maintainer. labels Apr 14, 2023
@github-actions github-actions bot removed the Type: Stale Issue has become stale - automatically added by Stale bot label Apr 14, 2023
@github-actions
Copy link

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.

@github-actions github-actions bot added the Type: Stale Issue has become stale - automatically added by Stale bot label May 12, 2023
@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale May 27, 2023
@miladdev85
Copy link

Is there any progress here? This issue should not be closed.
isHeadless does not change or get updated.

@Alex1899
Copy link

I am experiencing the same issue. When the app opens from pressing the background notification, isHeadless stays true

@humaidk2
Copy link

humaidk2 commented Nov 29, 2023

Hi,

I spent some time investigating this issue and found the solution.

The problem comes from updating app properties while the bridge has not been loaded.

It's an issue that comes from react native, facebook/react-native#20115

but react-native suggested that they won't be solving it,

Screenshot 2023-11-29 at 7 58 27 AM

There's 2 suggested solutions:

1 is to wait for js to load then set the props, but this didn't work for us

[[NSNotificationCenter defaultCenter] addObserverForName:RCTJavaScriptDidLoadNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
 
}];

2 is to patch react native, which did work for us

https://github.com/facebook/react-native/pull/20116/files

@mikehardy
Copy link
Collaborator

@humaidk2 react-native-firebase definitely has some things that only load after the javascript environment comes up and to my knowledge it has been working reliably. Patching react-native in those files implies a local fork / build of react-native is very painful from a maintenance perspective making a javascript observer a strong preference

This notification is used internally in react-native I'm surprised it's not working, they appear to be specifying the bridge as the object to observe though, I wonder if you follow their addObserver pattern it might work better? Examples:

https://github.com/search?q=repo%3Afacebook%2Freact-native+RCTJavaScriptDidLoadNotification&type=code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help: needs-triage Issue needs additional investigation/triaging. platform: ios type: bug New bug report Type: Stale Issue has become stale - automatically added by Stale bot Workflow: Needs Review Pending feedback or review from a maintainer.
Projects
None yet
Development

No branches or pull requests

10 participants