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

getCurrentActivity sometimes null inside componentDidMount #18345

Closed
esprehn opened this issue Mar 13, 2018 · 28 comments
Closed

getCurrentActivity sometimes null inside componentDidMount #18345

esprehn opened this issue Mar 13, 2018 · 28 comments
Labels
Bug Ran Commands One of our bots successfully processed a command. Stale There has been a lack of activity on this issue and it may be closed soon.

Comments

@esprehn
Copy link
Contributor

esprehn commented Mar 13, 2018

We're seeing a lot of users experience "no activity" errors from react-native-google-signin:
https://github.com/devfd/react-native-google-signin/blob/9336cc410ad3b939d0d9637d851311c33dbf3920/android/src/main/java/co/apptailor/googlesignin/RNGoogleSigninModule.java#L82

Our code does:
GoogleSignin.hasPlayServices({ autoResolve: true }) which calls that method.

We do that inside componentDidMount:

  private onAppStateChange = (nextAppState: AppStateStatus) => {
    if (nextAppState === 'active') {
      this.initializeApp(); // <--  called here.
    }
  }

  componentDidMount() {
    if (AppState.currentState === 'active') {
      this.initializeApp(); // <-- called here.
    }
    AppState.addEventListener('change', this.onAppStateChange);
}

and that calls into react-native-google-signin:

    public void playServicesAvailable(boolean autoresolve, Promise promise) {
        final Activity activity = getCurrentActivity();

        if (activity == null) {
            promise.reject("NO_ACTIVITY", "no activity");
            return;
        }
       // ...
    }

Originally we just called initializeApp() directly and were experiencing this error. I tried switching to checking the AppState and doing it there just in case, but that still doesn't appear to be working.

What's extra confusing about this is that the user sees the loading spinner first, so there's some activity displayed, and then the error comes back from react-native-google-signin and we show them the error message as well.

So there's both a rendered activity on the screen and somehow getCurrentActivity returning null at the same time?

Environment

We're seeing this on Android 23-27.

Environment:
OS: macOS High Sierra 10.13.3
Node: 8.9.4
Yarn: 1.5.1
npm: 5.6.0
Watchman: 4.7.0
Xcode: Xcode 9.2 Build version 9C40b
Android Studio: 3.0 AI-171.4443003

Packages: (wanted => installed)
react: 16.2.0 => 16.2.0
react-native: 0.52.2 => 0.52.2

Expected Behavior

Calling a native method that uses getCurrentActivity from a lifecycle method should always work.

Actual Behavior

It seems to work fine in the android emulator and on all the test devices we have locally, unfortunately we're getting lots of errors in the wild about it.

Steps to Reproduce

Not sure how... how can getCurrentActivity be null inside componentDidMount?

@vovkasm
Copy link
Contributor

vovkasm commented Mar 13, 2018

Preface: I do not know how to solve this issue, but can give additional information to improve understanding of RN behavior.

Your expectations are incorrect, it is not possible to such behavior as "Calling a native method that uses getCurrentActivity from a lifecycle method should always work" because it is totally unrelated things.

componentDidMount is JS method and executed on JS thread in context of JSC. When it directly or indirectly "call" native code, it actually not call anything, it serialize request and schedule native code execution. Native code will run on another thread. So whole process is asynchronous. And native code have no any guaranties that at execution time application will be in active state, also no guaranties that ReactContext will be attached to any activity.

Same applicable in reverse direction, native code can't call anything in JS "world", it can only schedule JS execution.

Moreover, strictly speaking, when AppState's event executed in JS, real application state can be already different. This effects will be more visible on slow devices.

I can be wrong (actually, I hope that I'm wrong) and RN can have some synchronization mechanisms, but until today I didn't seen any.

@react-native-bot
Copy link
Collaborator

Thanks for posting this! It looks like your issue may refer to an older version of React Native. Can you reproduce the issue on the latest stable release?

Thank you for your contributions.

How to ContributeWhat to Expect from Maintainers

@react-native-bot react-native-bot added Old Version ⏪ Ran Commands One of our bots successfully processed a command. labels Mar 13, 2018
@esprehn
Copy link
Contributor Author

esprehn commented Mar 14, 2018

We can't reproduce this, but I can report back after we upgrade and ship a new version of our app and get crash metrics. That said help understanding how this could have happened in an older version or the new one would be helpful as well.

@esprehn
Copy link
Contributor Author

esprehn commented Mar 15, 2018

@vovkasm I understand how the bridge works, what's not clear is why react would be mounting components on startup when getCurrentActivity is null.

See ex. #9310

fwiw there's an internal team here that has a whole helper class that you pass callbacks into which calls you immediately if getCurrentActivity is non-null, and waits for it to become non-null otherwise. What does Facebook do internally to handle this situation? It seems like calling getCurrentActivity inside a @ReactMethod is never safe. Are you supposed to just retry all calls from JS?

@react-native-bot react-native-bot added the Platform: macOS Building on macOS. label Mar 20, 2018
@hramos hramos removed the Platform: macOS Building on macOS. label Mar 29, 2018
@SirNeuman
Copy link

I am also trying to figure how to handle this. In my case when my app is in the background (specifically when the device is asleep)getCurrentActivity() appears to return null in my custom native android component. If the device is awake when i call getCurrentActivity() it does return the current activity. The funny thing is that the method I'm trying to implement is to turn on the screen and keep it awake, so if it happens to be asleep when i try to turn the screen on my method for doing that does not work. since i need to run activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)

@wildseansy
Copy link
Contributor

@esprehn, I'm having the same problem with a native module we have built for Google Pay with React Native 0.55.3. We can't reproduce in when testing, but we are seeing crashes in production happening where getCurrentActivity is returning null

@esprehn
Copy link
Contributor Author

esprehn commented May 15, 2018

We ended up adding retry logic in JS to compensate, but it's really unfortunate. The bug has persisted through all versions of RN as we've upgraded. I'd be great if FB would comment on how you're supposed to use this API properly.

@smathson
Copy link

smathson commented May 29, 2018

@esprehn Is that helper class you mention (to execute a callback when getActivity is available) something that you are able to put in a gist by any chance? That seems to be the way I'd prefer to solve the issue for my use-case (as opposed to retrying on the JS side) since I can safely wait for the Activity to become available and this is an Android-specific issue.

@RangerMauve
Copy link

@SirNeuman Having the exact same problem. Did you end up figuring out what to do? So far we're planning on trying to add retry-logic on the JS side.

@SirNeuman
Copy link

SirNeuman commented Jun 25, 2018

@RangerMauve Yeah. In my case I just found a workaround that is supposed to be deprecated but appears to work (on at least Android 7.0). Instead of:

activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)

I went with:

pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "NameOfLock");
wl.acquire();

which avoids needing to get the current activity.

@esprehn
Copy link
Contributor Author

esprehn commented Jul 18, 2018

The internal code does this by checking if the current activity is null, and if it is then adding a callback to a queue. Inside both onHostResume and onNewIntent it drains the queue if the activity is non null now, otherwise it waits again.

I think the problem here is that RN is calling into JS and starting up the app/doing renders and such before onHostResume/onNewIntent in some situations when it should be waiting.

@thefallenangel
Copy link

I have to make sure my application is in foreground before use function that have getCurrentActivity() in Java code. This thing happens when I upgrade react-native to version 0.55.4
so weird! (-_- ")

@karthikpala
Copy link

@esprehn I am also facing this issue in android 4.2 version only. Was there any solution to this problem?

@rajsuvariya
Copy link
Contributor

Something weird going on, we are observing crash reports of production apk and found out that getCurrentActivity() results into null for some specific brand devices, like Asus, Wiko and few models of Samsung. But it works perfectly fine for the rest of the devices even we can't reproduce this issues at our end.

@sayurimizuguchi
Copy link

Any solution for getCurrentActivity() returning null?
I have the same problem in production reported on my crash list, mainly with Samsung devices.

@smathson
Copy link

Has anyone else who is experiencing this issue been able to reproduce it in a development environment? There are a handful of places that I need the current Activity where implementing some kind of asynchronous solution is problematic, but I am unable to reproduce a scenario in testing to try and implement an alternative solution.

@john1jan
Copy link

john1jan commented Feb 7, 2019

I am also facing the same issue where getCurrentActivity

@vovkasm
Copy link
Contributor

vovkasm commented Feb 7, 2019

@john1jan Can you share minimal repo that reproduces issue on github?

@john1jan
Copy link

john1jan commented Feb 7, 2019

@vovkasm i am using https://github.com/thebylito/react-native-navigation-bar-color for changing my navigation bar color in my app, some times this crashing giving me this stacktrace

java.lang.NullPointerException: 
  at com.thebylito.navigationbarcolor.NavigationBarColorModule$1.run (NavigationBarColorModule.java:86)
  at android.os.Handler.handleCallback (Handler.java:815)
  at android.os.Handler.dispatchMessage (Handler.java:104)
  at android.os.Looper.loop (Looper.java:210)
  at android.app.ActivityThread.main (ActivityThread.java:5839)
  at java.lang.reflect.Method.invoke (Native Method)
  at java.lang.reflect.Method.invoke (Method.java:372)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1113)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:879) 

And the code at this line in Android NavigationBarColorModule.java

final Window window = getCurrentActivity().getWindow();

@john1jan
Copy link

john1jan commented Feb 7, 2019

check out this thebylito/react-native-navigation-bar-color#10

@vovkasm
Copy link
Contributor

vovkasm commented Feb 7, 2019

I'm personally not seen this problem in my projects. And I can help, but only if I can simple checkout project that demonstrate the issue from github and debug it.

@john1jan
Copy link

john1jan commented Feb 7, 2019

it doesn't happen for me either, I got it from my crash reporting tool

@levynir
Copy link

levynir commented Feb 26, 2019

This happens to us as well using react-native: ~0.57.8, only on some devices and some times. Mostly on newer (faster?) devices.

@thymikee
Copy link
Contributor

Is anybody able to provide a minimal repro using latest RN?

@stale
Copy link

stale bot commented Aug 2, 2019

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions.

@stale stale bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Aug 2, 2019
@JJMoon
Copy link

JJMoon commented Aug 8, 2019

I have same issue, but my case is in ComponentWillMount of first screen. I guess I might use settimeout for delaying calling method.
I have issue when I login via Naver login (Korean SMS), with react-native-naver-login module.

I found some documents to use ActivityLifecycleCallbacks, instead of deprecated getCurrentActivity, but spent several hours in vain.
Some tutorial guides to implement these callbacks in my application class and store activity object to static variable.
It can be a solution when you use it in your app, but the classes of npm modules cannot refer that object.
I am working on the module (react-native-naver-login), but didn't find the solution yet.

@stale stale bot removed the Stale There has been a lack of activity on this issue and it may be closed soon. label Aug 8, 2019
@stale
Copy link

stale bot commented Nov 6, 2019

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions.

@stale stale bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Nov 6, 2019
@stale
Copy link

stale bot commented Nov 13, 2019

Closing this issue after a prolonged period of inactivity. If this issue 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 Nov 13, 2019
@facebook facebook locked as resolved and limited conversation to collaborators Nov 14, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug Ran Commands One of our bots successfully processed a command. Stale There has been a lack of activity on this issue and it may be closed soon.
Projects
None yet
Development

No branches or pull requests