ocetnik / react-native-background-timer

Emit event periodically (even when app is in the background)
MIT License
1.61k stars 228 forks source link

Timer stop after couple of minutes #22

Open aamir-munir opened 7 years ago

aamir-munir commented 7 years ago

I am starting the timer on state change:

_handleAppStateChange(currentAppState) { var me = this; var str = me.currentAppState.currentState if (currentAppState == 'background') { intervalId = BackgroundTimer.setInterval(() => { me.sendCallToAPI(str); console.log('tic'); }, 60000); }

}

but what I notice it stops after couple of minutes, while in background, I am storing data in a DB on API call and after couple of entries it stop it.

aamir-munir commented 7 years ago

my code: if (currentAppState == 'background') { intervalId = BackgroundTimer.setInterval(() => { console.log(currentAppState + ' > ' + new Date()); }, 10000); }

this is my log from debugger:

background > Thu Jan 26 2017 19:19:19 GMT-0500 (EST) background > Thu Jan 26 2017 19:19:29 GMT-0500 (EST) background > Thu Jan 26 2017 19:19:39 GMT-0500 (EST) background > Thu Jan 26 2017 19:19:51 GMT-0500 (EST) background > Thu Jan 26 2017 19:20:01 GMT-0500 (EST) background > Thu Jan 26 2017 19:20:12 GMT-0500 (EST) background > Thu Jan 26 2017 19:20:23 GMT-0500 (EST) background > Thu Jan 26 2017 19:20:34 GMT-0500 (EST) background > Thu Jan 26 2017 19:20:45 GMT-0500 (EST) background > Thu Jan 26 2017 19:20:56 GMT-0500 (EST) background > Thu Jan 26 2017 19:21:06 GMT-0500 (EST) background > Thu Jan 26 2017 19:21:17 GMT-0500 (EST) background > Thu Jan 26 2017 19:21:28 GMT-0500 (EST) background > Thu Jan 26 2017 19:21:39 GMT-0500 (EST) background > Thu Jan 26 2017 19:21:50 GMT-0500 (EST) background > Thu Jan 26 2017 19:22:01 GMT-0500 (EST)

stops after 2-3 mins and I am testing it on iPhone not even the device locked.

any suggestion?

aamir-munir commented 7 years ago

anyone having the same issue this really help me to resolve: https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html

I was really missing to allow my app permissions to run in the background.

atlanteh commented 7 years ago

Did it actually work for you? I added Background fetch (and already had Remote notifications), but after about 3-4 mins the app stopped and the timer was killed with it.

swhamilton commented 7 years ago

@itcurves I also have this same question! I experienced the same issue (on iOS 10.3) with the background timer stopping after about 180 seconds (3 minutes).

I have background fetch enabled for Remote Notifications.

To further prove it doesn't work after 3 minutes, I implemented code that triggered a print job from the background using Push Notification onReceived() handler. It works until around 180 seconds have passed since the app when in the background, then the print function no longer gets executed and XCode throws an error.

I am pretty convinced that 3 minutes is the iOS native "buffer" time to allow for any processes to complete in the background before completely shutting them down.

Would love any additional insight to see if this is a valid theory and if there is Apple documentation that describes this behavior.

aamir-munir commented 7 years ago

All, it took me weeks to go deep down the issue and lots of effort and communication with many developers. But no one has a good solution, but there is a way to do this, and my working fine now. But for sure this component will not help you a lot. This is good but will not work in background, specially when phone is locked.

swhamilton commented 7 years ago

@itcurves thanks for the insight! Assuming everything was written with native code (no React Native), is it possible to execute functions after 3 minutes while the app is unlocked but in background mode? I am triggering using Push Notifications. Nobody seems to have any solution on how to do this or if it's possible in iOS. You are the first to express any success doing this after 3 minutes!

This article states that you can use Push Notifications to execute functions, but doesn't say anything about the 3 minute limit I experienced. https://developer.apple.com/reference/uikit/uiapplicationdelegate/1623013-application

I did find this method to get time remaining for (some or all) background tasks to run, which indicates there is a limit when going into the background mode.

var backgroundTimeRemaining: TimeInterval { get }

"This property contains the amount of time the app has to run in the background before it may be forcibly killed by the system." https://developer.apple.com/reference/uikit/uiapplication/1623029-backgroundtimeremaining

My flow looks look like this:

  1. App goes in background
  2. User receives push notification (with content_available=1), handled in application:didReceiveRemoteNotification:fetchCompletionHandler:
  3. The fetchCompletionHandler executes a print function, which silently prints using a saved printer location (doesn't use printer selection screen).

Any insight would be great.

swhamilton commented 7 years ago

Another update from Ray Wenderlich tutorial: https://www.raywenderlich.com/143128/background-modes-tutorial-getting-started

"How much time you get after your app gets backgrounded is determined by iOS. There are no guarantees on the time you’re granted, but you can always check backgroundTimeRemaining on UIApplication. This will tell you how much time you have left.

The general, observation-based consensus is that you get three minutes. Again, there are no guarantees and the API documentation doesn’t even give a ballpark number – so don’t rely on this number. You might get 5 minutes or 5 seconds, so your app needs to be prepared for… whatever!"

Seems like this is what I am experiencing.

aamir-munir commented 7 years ago

@swhamilton I do understand your frustration, because we did complete an application and that app really need to run all the time, even in the background (phone is locked, or sitting on a table, or user using any other application). once we complete and push it then realize we are far behind from the solution, but after 3-4 weeks of research and some good help from online people we were able to achieve it without using push notification and using a react native module.

Please check: react-native-background-geolocation I use this component and it really worked for me.

And this is my app flow (alomost same as yours):

  1. App goes in background
  2. run a process every minute (in my case I have to run every minute), do whatever you want to do in that process and you should be good.

Please let me know if you need any help I would love to do that.

swhamilton commented 7 years ago

Thanks @itcurves! I may have further questions with this and really appreciate any help.

One question: Do you set a timer once with an interval of 1 minute, or do you set one background function that recursively calls itself every minute?

aamir-munir commented 7 years ago

@swhamilton in my case I do need recursive calls, because I have to fetch some information every minute from a server, and based on result it calls the same function again and response normally take about a minute from server.

swhamilton commented 7 years ago

Getting there! Seems like this might be the answer where I could ping my server every x seconds from the background: https://github.com/transistorsoft/react-native-background-geolocation/wiki/Philosophy-of-Operation#ios-heartbeat-event Thanks for the pointer!

aamir-munir commented 7 years ago

@swhamilton please check below (this is all my discussion on this thing): https://github.com/transistorsoft/react-native-background-geolocation/issues/204

Let me know if you need more.

qingtian5266 commented 7 years ago

+1