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

Add support for AlarmManager in Timing to allow proper handling of long timers #12981

Open
astreet opened this Issue Mar 16, 2017 · 103 comments

Comments

Projects
None yet
@astreet
Contributor

astreet commented Mar 16, 2017

Setting timers for multiple minutes isn't handled properly in React Native on Android: it keeps the Timing module awake instead of relying on the system waking us up when the timer should go off.

We should explore setting a cut off at which we delegate to AlarmManager and Handler.postDelayed instead of handling the timers using framecallbacks.

@astreet astreet added the Android label Mar 16, 2017

@ptomasroos

This comment has been minimized.

Contributor

ptomasroos commented Apr 10, 2017

Great improvement!

@chirag04

This comment has been minimized.

Collaborator

chirag04 commented Apr 10, 2017

this would help with socket.io which keeps a timer of 85000ms by default. On RN master the threshold is 60000ms.

@skv-headless

This comment has been minimized.

Contributor

skv-headless commented Apr 10, 2017

And Firebase which is also using long timers.

@coder4affine

This comment has been minimized.

coder4affine commented May 14, 2017

I am getting following warning while using firebase library

Setting a timer for a long period of time, i.e. multiple minutes, is a performance and correctness issue on Android as it keeps the timer module awake, and timers can only be called when the app is in the foreground. See https://github.com/facebook/react-native/issues/12981 for more info. (Saw setTimeout with duration 111862ms)

How to get rid of this warning...

@oky1

This comment has been minimized.

oky1 commented May 15, 2017

I am getting following warning while using firebase library too. Somebody know how to solve this problem?

@VickyKoblinski

This comment has been minimized.

VickyKoblinski commented May 15, 2017

I am also getting this warning with firebase.

"firebase": "^3.9.0",
"react-native": "0.44.0"
@imamatory

This comment has been minimized.

imamatory commented May 16, 2017

Same issue (85000ms) but without firebase. My list of packages:

  "dependencies": {
    "apisauce": "0.11.0",
    "format-json": "1.0.3",
    "lodash": "4.17.4",
    "markdown-it": "^8.3.1",
    "native-base": "^2.1.3",
    "normalizr": "^3.2.2",
    "prop-types": "^15.5.10",
    "querystringify": "1.0.0",
    "ramda": "0.23.0",
    "react": "16.0.0-alpha.6",
    "react-markdown": "^2.5.0",
    "react-native": "0.44.0",
    "react-native-animatable": "1.2.0",
    "react-native-config": "0.4.2",
    "react-native-device-info": "0.10.2",
    "react-native-drawer": "2.3.0",
    "react-native-htmlview": "0.9.0",
    "react-native-i18n": "1.0.0",
    "react-native-linear-gradient": "^2.0.0",
    "react-native-photo-view": "^1.2.0",
    "react-native-router-flux": "3.39.1",
    "react-native-scrollable-tab-view": "*",
    "react-native-share": "^1.0.20",
    "react-native-vector-icons": "4.1.1",
    "react-navigation": "^1.0.0-beta.9",
    "react-redux": "5.0.4",
    "redux": "3.6.0",
    "redux-persist": "4.6.0",
    "redux-saga": "0.15.3",
    "reduxsauce": "0.4.1",
    "seamless-immutable": "7.1.2"
  },
  "devDependencies": {
    "ava": "^0.18.2",
    "babel-eslint": "^7.1.1",
    "babel-preset-es2015": "^6.18.0",
    "enzyme": "^2.6.0",
    "husky": "^0.13.1",
    "ignite-animatable": "^0.3.1",
    "ignite-dev-screens": "^2.0.0-beta.9",
    "ignite-i18n": "^0.1.1",
    "ignite-ir-boilerplate-2016": "^0.2.2",
    "ignite-vector-icons": "^0.2.1",
    "mockery": "^2.0.0",
    "nyc": "^10.1.2",
    "react-addons-test-utils": "^15.3.1",
    "react-dom": "^15.4.0",
    "react-native-mock": "^0.3.1",
    "reactotron-apisauce": "^1.7.0",
    "reactotron-react-native": "^1.7.0",
    "reactotron-redux": "^1.7.0",
    "reactotron-redux-saga": "^1.7.0",
    "snazzy": "^6.0.0",
    "standard": "^8.6.0"
  }
@zibs

This comment has been minimized.

zibs commented May 16, 2017

I'm experiencing a similar issue using 0.44.0 on Android. I am also not using firebase:

Setting a timer for a long period of time, i.e. multiple minutes, is a performance and correctness issue on Android as it keeps the timer module awake, and timers can only be called when the app is in the foreground. See https://github.com/facebook/react-native/issues/12981 for more info. (Saw setTimeout with duration 85000ms)

@deejaygeroso

This comment has been minimized.

deejaygeroso commented May 17, 2017

Hi there guys.. was wondering Is there any quick work around for this. I'm using:

react-native 0.44 react 16.0.0-alpha.6 feathers-socketio 1.6.0

Its very annoying popping out while I'm developing.. is there anyway I can hide the warning for now??

@aleinnocenzi

This comment has been minimized.

aleinnocenzi commented May 17, 2017

Same issue here with firebase 3.9.0

@skv-headless

This comment has been minimized.

Contributor

skv-headless commented May 17, 2017

If it bothers you just add console.ignoredYellowBox = ['Setting a timer'];

@RWOverdijk

This comment has been minimized.

RWOverdijk commented May 17, 2017

@skv-headless Opinion incoming. :)

In my opinion that attitude towards problems needs to go away. I've been seeing it pop up more often and it's causing people to ignore warnings. They're warnings. They warn you. Don't ignore them, do something. I've seen apps where all warnings just get ignored, even deprecation notices. Then your app breaks and you're left wondering why.

In this case, you can configure these timeouts and lower them, or setup a different approach of dealing with them. Maybe even poke the maintainers of the libraries and ask them to help come up with a solution.

My advise, is to follow this thread until someone smart comes up with an actual solution, so you can then educate yourself with that answer. And then maybe, in the meantime (if you can't / don't want to teckle the issue) ignore the warnings.

TL;DR;

Yes, you can ignore the warnings temporarily. Just check in every now and then to see what the status is and if there's any action required.

@rigobcastro

This comment has been minimized.

rigobcastro commented May 19, 2017

@imamatory I think is by Rectotron

@imamatory

This comment has been minimized.

imamatory commented May 19, 2017

I think is by Rectotron

If so, this warning can be simply ignored.
...however my android emulator getting slow sometimes, maybe it is one of reasons.

@rigobcastro

This comment has been minimized.

rigobcastro commented May 20, 2017

@imamatory I hope the real solution is just as easy

@nicolasZZ

This comment has been minimized.

nicolasZZ commented May 23, 2017

Hi, I think I found the solution:
Firstly you have to find the following file in your project: libraries/Core/Timers/JSTimer;js
Open it and you just have to change this const MAX_TIMER_DURATION_MS, to increase above your duration, wrote in the end of warning !

@AmroAly

This comment has been minimized.

AmroAly commented May 23, 2017

@nicolasZZ hi, Thanks for the solution. but Is that a good practice to modify the JSTimer library rather than our own code?

@rigobcastro

This comment has been minimized.

rigobcastro commented May 23, 2017

@nicolasZZ @AmroAly In my mind this solution is not a good practice because it is very unstable, the best is ignore the alert while the official solution is released.

console.ignoredYellowBox = [
    'Setting a timer'
]

the @skv-headless's solution is good but in my case only works with "enter" between of the parenthesis

@AmroAly

This comment has been minimized.

AmroAly commented May 25, 2017

@rigobcastro Thanks that hides the annoying alerts.

@chirag04

This comment has been minimized.

Collaborator

chirag04 commented May 29, 2017

@DZuz14 it would be awesome if you could sent a PR or atleast get the conversation started. Thanks 👍

@simpleblack

This comment has been minimized.

simpleblack commented Jun 8, 2017

hi~
I used socket.io. nodejs and RN44 or RN 45
I saw warning this timers.

I found this solution
reference reactotron PR

personal server nodejs and scoket.io

const express = require('express')
const app = express()
const server = require('http').Server(app)
const io = require('socket.io')(server, {pingTimeout: 30000})

Thanks!

@saeedhei

This comment has been minimized.

saeedhei commented Jun 17, 2017

I have a simple react native project for android and I'm using firebase auth with react native for Login and Signup, but I got that yellow error, What should I do? Link of my Question in stackoverslow (https://stackoverflow.com/questions/44603362/setting-a-timer-for-a-long-period-of-time-i-e-multiple-minutes )

@saeedhei

This comment has been minimized.

saeedhei commented Jun 19, 2017

Thank You @DZuz14
I Got This Error When I run react-native run-android

D:\Projects 2016\Web\Android\mohajerkade-android\android\app\src\main\java\com\mohajerkade\AlarmManagerModule.java:40: error: cannot find symbol
       Intent intent = new Intent(context, AlarmReceiver.class);
                                           ^
  symbol:   class AlarmReceiver
  location: class AlarmManagerModule
1 error
:app:compileDebugJavaWithJavac FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.

I want to use firebase auth with react native for Login and Signup but I got That yellow error,
1: What is This Module Exactly?
2: Why My Project need This Module?

I asked stackoverflow through this link: (https://stackoverflow.com/questions/44603362/setting-a-timer-for-a-long-period-of-time-i-e-multiple-minutes)
I Reported to Google Firebase Team through this link: (firebase/firebase-js-sdk#97)

@BerndWessels

This comment has been minimized.

Contributor

BerndWessels commented Jun 21, 2017

@DZuz14 I got the same question as @saeedhei .

Basically we are using the firebase node module that uses these long period timers.

Adding your module is not enough I guess, we actually have to rewrite the code within the firebase node module to use your Alarms rather than Javascript timers, right?

@BerndWessels

This comment has been minimized.

Contributor

BerndWessels commented Jun 21, 2017

Thanks @DZuz14

So if you look into the npm package called firebase you will find that it uses setTimeout in quite a lot of places. This is OK since the library was written for websites and node.js servers. react-native is kind of a node.js server but it runs on a phone - and as the warning correctly points out - long running Javascript timers are not good in this environment and might drain the battery and have other unwanted side effects.

So I guess we have to convince the Firebase guys actually to change to your approach and distribute a package made especially for react-native.

@DZuz14

This comment has been minimized.

DZuz14 commented Jun 21, 2017

@BerndWessels https://www.npmjs.com/package/react-native-firebase Have you looked at this? Says it allows firebase to run on the native thread. Not sure how true that is, but might be worth a look. You might even be using that, I'm not sure.

@BerndWessels

This comment has been minimized.

Contributor

BerndWessels commented Jun 21, 2017

@DZuz14 Thanks, I'll check that out.

@steelx

This comment has been minimized.

steelx commented May 27, 2018

any quick fix for this issue ? I just started to use RN with Firebase.

@noahtallen

This comment has been minimized.

noahtallen commented May 27, 2018

I've tried a few different timer solutions, but haven't had any luck getting one working in the background (consistently).

@nick-michael

This comment has been minimized.

nick-michael commented May 31, 2018

I've using a setInterval to ping my server every 10 minutes - I just noticed this error message because I do a setInterval(myFunction, 60000). Is this something I need to be worried about?

My expected behaviour is that while the app is open, it can send off the requests, but after the app is suspended (single home button press) the requests should stop firing. Is this the behaviour that I can expect, and will the battery life be impacted while the app is suspended?

@esprehn

This comment has been minimized.

Contributor

esprehn commented Jun 21, 2018

There's nothing to worry about here, and the warning is incorrect and should be removed. There isn't a "Timing Module" to keep awake, there's just a Choreographer callback that checks for timers every frame (which also makes the min granularity for timers be ~16ms).

There is a correctness issue in the sense that timers won't fire in the background on either iOS or Android. This warning seems to be specifically about Android though and does not appear to be accurate. All timers should eventually fire when the app comes back into the foreground.

@MeKyleH

This comment has been minimized.

MeKyleH commented Jun 28, 2018

Any plans on having this addressed soon? The log is annoying anytime we're testing on Android phones.

@beausmith

This comment has been minimized.

Contributor

beausmith commented Jul 14, 2018

My Problem…

I was getting this error because my timeout was up to ~59 minutes. The code to call a method on the top of the hour and had a setTimeout to create a setInterval at the next top of the hour.

My Solution…

  1. update the setTimeout to start the setInterval at the top of the minute.
  2. update the function called by the setInterval to only run the function if the current minutes was 0.

This function now runs every minute instead of every hour… but since it does nothing 59 times out of 60, seems harmless.

@newah

This comment has been minimized.

newah commented Jul 19, 2018

hey @beausmith, is this really a solution to simply set 60 timers? To my understanding, it is still keeping the timerModule active for the same hour, but isn't showing the warning :)

@beausmith

This comment has been minimized.

Contributor

beausmith commented Jul 25, 2018

@newah - yeah, it's a little hacky… can you suggest a better solution?

@newah

This comment has been minimized.

newah commented Jul 25, 2018

@beausmith, I tried using https://github.com/ocetnik/react-native-background-timer which uses native timers which sounds like a solution - I've simply overwritten setTimout and setInterval with this lib's implementation.

Supporting timers in background might be a plus or minus depending on your needs :))

Seems to work fine, but didn't solve my problems though :)

@Risbot

This comment has been minimized.

Risbot commented Jul 26, 2018

I have same warning if I use react-intl FormattedRelative. Because inside component FormattedRelative is used timer:

scheduleNextUpdate(props, state) {
    // Cancel and pending update because we're scheduling a new update.
    clearTimeout(this._timer);

    const {value, units, updateInterval} = props;
    const time = new Date(value).getTime();

    // If the `updateInterval` is falsy, including `0` or we don't have a
    // valid date, then auto updates have been turned off, so we bail and
    // skip scheduling an update.
    if (!updateInterval || !isFinite(time)) {
      return;
    }

    const delta = time - state.now;
    const unitDelay = getUnitDelay(units || selectUnits(delta));
    const unitRemainder = Math.abs(delta % unitDelay);

    // We want the largest possible timer delay which will still display
    // accurate information while reducing unnecessary re-renders. The delay
    // should be until the next "interesting" moment, like a tick from
    // "1 minute ago" to "2 minutes ago" when the delta is 120,000ms.
    const delay =
      delta < 0
        ? Math.max(updateInterval, unitDelay - unitRemainder)
        : Math.max(updateInterval, unitRemainder);

    this._timer = setTimeout(() => {
      this.setState({now: this.context.intl.now()});
    }, delay);
  }

Here is example of use in my code:

<FormattedRelative value={date}>
	{(message: string) => <Text>{message}</Text>}
</FormattedRelative>

Anybody know how fix this warning?

@bernardochuecos

This comment has been minimized.

bernardochuecos commented Aug 8, 2018

This is still an issue. It's particularly annoying when using firebase services on android. Please fix.

agazso added a commit to agazso/postmodern that referenced this issue Aug 17, 2018

@vongohren

This comment has been minimized.

vongohren commented Aug 18, 2018

This is a really bad bug for firebase services and when you are dependent on third part apps. Because firebase does not work if you switch between apps to verify something to continue the process.

An example is we use a thirdparty/factor login system, and using firebase to move tokens. But since we clean up the token is gone before the person is back in our app. So I can change the cleanup mechanis, or you guys could fix this bug.

@ericketts

This comment has been minimized.

ericketts commented Aug 21, 2018

@vongohren not that I understand your use case fully, but one workaround strategy might be to store the backgrounding date within your app on entry to the background, then on return to the foreground compare the current date with the stored backgrounding date and perform some cleanup if a certain time period has elapsed...

@vongohren

This comment has been minimized.

vongohren commented Aug 21, 2018

To elaborate on my use case. Say you are dependent on saying yes in another app to accept the login. Feks switch over to facebook app to say yes to a login request in a third party. The concrete example im working with is uPort, https://www.uport.me/. Then when we rely on a way to message our app, now in the background to say that all is good, this doesnt work with firebase unless we take your approach to clean up at a later point.

I guess I was just stuck on that the clean up could happen right after emitted information, becaues then the information was already emitted, and we would not need it. But why is it so that the firebase approach does not work in react native? That it stops its background workers.

@nbennink

This comment has been minimized.

nbennink commented Aug 29, 2018

I need a 30 minutes timeout in my app. Every time the user has interaction with the screen it will reset (throw away old timeout, create new one).

Any alternative on how to do this the right way? Is it better to handle this with native code and pass something to React when finished?

@moeinrahimi

This comment has been minimized.

moeinrahimi commented Sep 12, 2018

wow, so this still an issue

@pfulop

This comment has been minimized.

Contributor

pfulop commented Sep 12, 2018

@nbennink check answer here . Currently there's no guarantee way to run task in the background since there are multiple factors in play (battery saver, user interaction etc.).

anchetaWern added a commit to anchetaWern/RNPhotoShare that referenced this issue Sep 19, 2018

@MSSPL-PiyaleeMaiti

This comment has been minimized.

MSSPL-PiyaleeMaiti commented Nov 5, 2018

I also getting same warning after using socket.io.
Warning is below:

Setting a timer for a long period of time, i.e. multiple minutes, is a performance and correctness issue on Android as it keeps the timer module awake, and timers can only be called when the app is in the foreground. See https://github.com/facebook/react-native/issues/12981 for more info.
(Saw setTimeout with duration 85000ms)

My package details is below:

  • "react": "^16.3.0-alpha.1",
  • "react-native": "0.54.4",
  • "socket.io": "^2.1.1",
  • "socket.io-client": "^2.1.1",

Any permanent solution find out?

@hlogeon

This comment has been minimized.

hlogeon commented Dec 6, 2018

I also getting same warning after using socket.io.
Warning is below:

Setting a timer for a long period of time, i.e. multiple minutes, is a performance and correctness issue on Android as it keeps the timer module awake, and timers can only be called when the app is in the foreground. See https://github.com/facebook/react-native/issues/12981 for more info.
(Saw setTimeout with duration 85000ms)

My package details is below:

"react": "^16.3.0-alpha.1",
"react-native": "0.54.4",
"socket.io": "^2.1.1",
"socket.io-client": "^2.1.1",

Any permanent solution find out?

@vongohren

This comment has been minimized.

vongohren commented Dec 7, 2018

Ditto, there is no way to go around this?

@cmacdonnacha

This comment has been minimized.

cmacdonnacha commented Dec 16, 2018

Still getting this warning on react-native 0.57, is this issue supposed to be open instead?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment