-
Notifications
You must be signed in to change notification settings - Fork 24.4k
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
[Timer] React Events not fired if the device is locked and screen turned off. #1282
Comments
cc @nicklockwood and @a2 |
I agree this is a bug. Timer events - except maybe rAF - should run in the background. |
cc @tadeuzagallo - maybe we're running the displaylink in the wrong mode? I thought it was using commonModes already, but maybe not. |
@nicklockwood the timers are also explicitly paused when the app is backgrounded #1218 (comment) Haven't explored to see if the run loop is a confounding factor but the timer code is part of the problem for sure. |
Oh, yeah. That would do it. I think timers were always envisioned as being used for animation-related purposes, but it seems like we should add an explicit "pauseInBackground" property or something rather than pausing all timers by default. |
I've experienced this via command-center generated events. However, my experience, when the device is locked, events publish fine when the phone is locked and the screen is on. However, when the phone is locked and the screen is off, events actually queue up. So, if i hit next next next, my player will move 3 songs forward in the playlist. The flow is: |
@jaygarcia If you put a NSLog in your bridge where the event is also triggered, does the output display but the event not fired if the screen is turned off? I'm not having the events queue up, they just don't fire. |
OK. @mintuz @nicklockwood @ide So in doing this testing, i can tell you that when events are generated via CommandCenter, they queue up. The runloop seems to freeze (to be expected) when the phone sleeps. Command center implementation: https://github.com/ModusCreateOrg/react-native-mod-player/blob/master/kgmp/iOS/ModusCreate/MCModPlayerInterface.m#L196 Event listener: https://github.com/ModusCreateOrg/react-native-mod-player/blob/master/kgmp/jsx/player/RandomPlayer.js#L287 Examples below registering the event handler (JS)
onCommandCenterEvent
XCode console phone is awake
XCode console phone is sleeping
|
Here's why this is an issue for the type of app I'm currently writing: Audio applications need to be able to:
This application was designed, like many (if not all) RN applications, to have the controller logic inside of the JSX/JSCore layer. Correct me if i'm wrong, but I think unless this specific issue can get resolved, then any type of application that requires background responsiveness cannot use React Native unless the controller logic is duplicated in the Objective C layer. =) |
Lastly, if anyone plans on cloning that repo, know that it's HUGE atm. It's got > 4.3K Mod files, which will be removed once i configure the code to auto-download a zip file. |
A quick bump. this is still an issue. |
I'll do a minor refactor on timers soon(ish) to address #1539, I'll try to look into it as well. |
👍 |
Hi @tadeuzagallo curious if there is any update/timeline on this issue? Thanks! |
I have just run into this issue attempting to use beacon region monitoring. When the app is open I receive the event and I post a local notification to the user, when the app is in the background nothing happens until the screen come back on and all the notifications get fired. Is there a work around for this, or is there a better way of doing this? |
I believe #1660 is related |
Any update on this, sorry for the spam. Just seems to have gone quiet. |
@dalejefferson I think beacon monitoring is a bit different. See #1660 |
After doing some research, I've determined that I needed to move core controller logic for my music app to the ObjC layer. Things like the RN runloop sleeping and queueing events was breaking things. I couldn't figure out if there was a way to signal the Runloop to awaken from suspension. I'm happy w/ these changes and have realized that this isn't an issue with React Native, but just the way iOS handles runloops that aren't required for background processing. |
@jaygarcia Do you think it's possible to create a short-lived JSC context with react-native modules to run the logic in JavaScript? |
Has there been any more thinking on this? I'm trying to decide if I need to build the Obj-C controller logic for my app. |
+1 |
@timfpark I did got hold of the JSC context and ran my javascript logic directly while React was asleep. It was a messy hack but it allow me to keep all my code in js land. |
Interesting! Do you happen to have a gist for how you did that for folks on On Thu, Oct 22, 2015 at 12:04 PM, Dale Jefferson [email protected]
|
@timfpark Here is my a Gist of the important code. I have not tried this with anything newer than React Native 0.8.0, but in theory it should still work. |
@dalejefferson Do you mind giving an overview of how the code in that gist works and fixes the problem? Thanks :) |
@toblux Good catch, I updated the title to correctly reflect the issue, and that changed the slug of the URL without redirecting (bad! :p) |
Trying to understands some context: Why do you need this? What work do you want to do in the background? Can you use AppStateIOS to do the work once the app comes to foreground again?
I don't think we do that on Android. |
@mkonicek I think the beacon example mentioned above by @dalejefferson is a prime example of where the processing would need to be done in the background. Preferred behaviour: Delayed processing would result in: |
@mkonicek My use case, sorry if it's unrelated:
I did this in Obj-C on iOS with an AWS Obj-C SDK, but it would be much more convenient to do it in JavaScript where all the other code is. |
@mkonicek I had to use my hack (in the gist above) on several projects now. Features we regularly use that need to happen in the background.
Example: Our server sends out a silent push that the proximity config has been updated. |
Upgrading to 0.14 fixed this issue for me. |
Thanks for the use cases guys, totally makes sense. |
EDIT: This problem seems to have been fixed in 0.14. |
@toblux @jamesfzhang Heya, just wondering how exactly the issue is fixed for you since 0.14 – Does your JavaScript event handler code actually run when the app is in the background? |
@ehd I'm not sure exactly how it was fixed but the event handler code do run when the app runs in the background. I use the remote controls (like play/pause a song) to test the event handlers. |
@jamesfzhang Thank you, good to know! Perhaps it works for remote controls but not for push notifications. Maybe also a |
@ehd If it works for remote, I imagine it must work for push. How are you subscribing to the push events? For the remote controls, I subscribe to them like so & dispatch an app event: let commandCenter = MPRemoteCommandCenter.sharedCommandCenter()
commandCenter.playCommand.addTarget(self, action: Selector("didReceivePlayCommand")) |
@jamesfzhang Yeah, I think you're right. There's no reason why it shouldn't work. I'm subscribing to push events via So now I'm going to implement And thank you for getting back, I really appreciate your assistance! Edit: Actually implementing |
Sounds like a good plan, good luck! |
Holy cow, I think it works and it was really simple: Instead of - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification
{
[RCTPushNotificationManager didReceiveRemoteNotification:notification];
} [edit] adding a additional delegate method works: - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
{
[RCTPushNotificationManager didReceiveRemoteNotification:notification];
handler(UIBackgroundFetchResultNewData);
} I can actually |
@ehd - did it work even though you called the completion handler right away? and wait until whatever operation you were doing completed? I'm able to perform network operations if I retain the completion handler and not call it right away. But then I don't know how signal from react back to iOS that the operation has completed |
@joshblour In fact it only works when the phone is connected to power (and possibly on wifi). So we need a way of retaining the handler and calling it from JS somehow, don't we? |
@ehd thats exactly right. retaining is easy enough (although its tricky because ios can call the delegate multiple times and expects you to call the completion handler for each one, so you need some kind of queue) But i have no idea how to export an AppDelegate method to JS... |
here's my current hacky workaround: -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[RCTPushNotificationManager didReceiveRemoteNotification:userInfo];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
completionHandler(UIBackgroundFetchResultNewData);
});
} |
@jaygarcia Hey - do you have code sample of how you achieved this? When phone off / screen locked - you hit a button and then RN code works while in background? |
@joshblour how would we rewrite that for Android per #1282 (comment)? |
@nicklockwood agree with idea of |
If you have a delegate method that is fired every X seconds in the background when the device is locked. The delegate method is fired but the event is not. The following code
This log message Is triggered when the device is locked and screen is inactive.
This event is triggered if the device is locked but the screen needs to be active.
The text was updated successfully, but these errors were encountered: