In my app, I have performed the following listed below and have added counter to the app fetch routine to highlight the number of times fetch is called by iOS 8.1.
Turned on Background Modes and enabled background fetch.
Wrote code for “performFetchWithCompletionHandler”. NSLog message indicate the start and end of the fetch process. Counters are between these messages.
Added code in “didFinishLaunchingWithOptions”. However, instead of using “setMinimumBackgroundFetchInterval” I am using double of 60 assuming seconds.
When I test the code in Debug by setting “Simulate Background Fetch” all works perfectly as expected with absolutely no problems. Counters work and show expected values.
However, when I go live on the iPhone, launch the app, then hit the home button to put in background, wait one or two hours or overnight. Nothing happens, no fetch, no downloads and all counters remain at zero.
If I cannot get this to work, I will need to create my own background thread and manage it directly, which I would prefer not to do.
Any input or ideas are deeply appreciated.
As of iOS 8, I started having this same problem with both of my apps. In iOS 7, background refresh triggered pretty reliably. In iOS 8, it just stopped. If I launch either app from xcode into the background fetch mode, everything works like it should. Background refreshes themselves just stopped triggering on their own in iOS. I have a hopeful theory that I'm trying out right now. Here's my thinking...
iOS will exclude your app from background refresh if the user force kills it from the multi-tasking screen. How might Apple have implemented this behavior? One way would be to just set your minimum fetch interval to UIApplicationBackgroundFetchIntervalNever. Easy peasy. Let's assume that's how they do it. Does your app set the minimum fetch interval every time it launches, or does it only set it on the initial launch?
In my case, I was only setting the minimum fetch interval as part of the initial setup of my app. If the user force killed the app, and iOS is in fact setting the minimum fetch interval to UIApplicationBackgroundFetchIntervalNever, then my apps are stuck in the state of never. I made a minor change in one of my apps, so that it sets the minimum fetch interval on every launch. So far so good.
Update:
All is well in my background fetch land.
Both my app that's currently in development and my app that's in the app store are once again triggering background fetches reliably.
The code for doing this can be pretty simple...
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:minimumBackgroundFetchInterval];
Calling that every time your application launches will do the trick, however, you'll want to consider whether setting that value is appropriate to the current state of your app. In my case, one of my apps is a concert listings app. There's no point in setting a minimum background fetch interval if the user hasn't selected a location for concerts yet. I have an NSUserDefault to track whether a location has been set. Here's an approximation of my code for setting the fetch interval ...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if ([INCUserDefaults isLocationConfigured]) {
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:kSecondsIntervalForUpcomingShowsBackgroundFetch];
}
return YES;
}
Prior to the bug fix that I issued, I was only setting the minimum background fetch interval as part of the setup process. Now I set it during the setup process, and on application startup if the setup process was previously completed.
Apple uses a secret algorithm to determine the frequency of fetch events. This algorithm is presumably based upon app usage patterns (ie: how frequently and when the user users the app). It can take several days before fetch events begin to arrive consistently.
If fetch event works in simulator, that proves that everything is correctly set up. There's nothing you can do but wait.
iOS does the background fetch in certain way. It wakes up apps it believes the user uses often. Try opening the app after you wake the phone for a few times.
As kkarayannis wrote, iOS will learn how often to call your app. I've seen the same behaviour as I wrote my first background fetch. I believe, that you should not only open your app manually, but also trigger a manual refresh then. IOS will learn that the user wants to load data regularly and will start to do it on it's own.
Have you also tried to use "setMinimumBackgroundFetchInterval" instead of 120sec? Maybe it's a too short intervall. However you could also past your code for better understanding.
Related
Firstly, apologies for the slightly open ended questions but I can't find the info I'm looking for in other questions.
I'm trying to understand the lifecycle of a RN app on both iOS and Android. I understand the app bootstraps when you first start it and stays running while the phone is alive, but what happens when the user switches to a different app and comes back, or their screen times out then they switch it back on? It would be really annoying if the app restarted just because they briefly switched to check their email.
My specific use case (not particularly important to this generic question but included for context) is that I'm trying to build a game with socket.io connections and I'm wondering if I can hook into events to see if the app has been in the background or if I even need to. I have found a way of forcing a restart which may be necessary at some points, but I'd rather just try to reconnect things that have disconnected if I can find out when that happens.
Any push in the right direction would be appreciated.
The app doesn't restart when it goes in the background as you describe. The app keeps its state and the user sees the last screen they visited.
You should have a look at react native's AppState
https://facebook.github.io/react-native/docs/appstate
Using AppState you can addEventListeners that capture the change of the app's state like when going to background.
Of course there are also some problems here...
You can't capture the "kill "event. You can only detect if the app is sent to the background but unfortunately you can't detect when the user chooses to "kill" the app
You can't run any code while your app is in the background. This might be serious in your case but you should evaluate it. For example if you have a timer and you sent the app to the background then the timer stops.
I read in many places that if user swipes up and kills an app, that app will not be able to receive location updates. I get didEnterRegion and didExitRegion callbacks are received when my app is not killed and is in background. But if I swipe kill app, app doesn't get those callbacks. My question here is,
Is it that app will stop getting callbacks ever? i.e., even if the app is launched again and is in background it does not get the callbacks
I read about startMonitoringSignificantLocationChanges and background app refresh when used together, I can get callback even when app is killed by swipe. I tried this and could not get it working. Is this the expected behavior?
Will startMonitoringSignificantLocationChanges and background app refresh together when used, I get region entry/exit callbacks after rebooting device?
This is not expected behavior. You are supposed to get didEnterRegion and didExitRegion callbacks even after killing an app in the task switcher. If you are not seeing this, something may be wrong with your app or testing methodology. Posting code may be helpful.
A few caveats and tips:
Make sure your app has obtained backround permission with locationManager.requestAlwaysAuthorization(). Without it, it cannot detect at all in the background.
Detection in the killed state did not work on iOS 7.0.x. It started working as of 7.1+.
Make sure you wait long enough to get detections. In some app states, it can take up to 15 minutes.
Before killing your app in testing, check logs to ensure you know what CoreLocation thinks is your current region state. If you turn off a beacon then kill your app, CoreLocation may not have had time to realize the beacon disappeared, thinking it is still inside the region. If you then turn on the beacon, you will not get a new entry event because it thinks you are already inside.
I have a simple app that uses location services, and registers to run in the background. I update a simple tableView with location data. This data is still being received when the user leaves the app and does something else.
Currently I am calling a method in my - (void)applicationWillEnterForeground:(UIApplication *)application to update the UI, but there is still a split second when the app opens, and the UI gets updated.
I have also tried to do periodic UI updates when in the background, but not surprisingly this doesn't seem to work.
Are there any solutions out there so that I can have the UI fully updated when the user brings the app back into the foreground?
The best solution would probably be to profile and see why you have any delay at all before displaying new data. It's quite possible you could do some things to get ready for the display to arrive, like doing Core Data queries ahead of time (they can take a significant amount of time).
An alternative would be to dump a blank UI bitmap from the screen as you were being suspended, and write to it directly based on activity - then when the application resumes, briefly show that bitmap as a screen overlay before showing the real complete UI.
I am making an app where I need to know
every button that was ever pushed by the user in the app, and when it was pushed, and
where the iPhone has gone (using gps), but there are no cell towers in the area so I can't use that significant location changes method everyone uses.
It seems to me like the Plist method for data saving won't work because I don't want the app to start where it left off, I want it to start at the beginning every time.
Also, if any of you have any idea how I can make my app wake up at certain specific times, and/or how I can make it impossible to exit, that would be awesome. This is for an experiment with the University of Queensland St. Lucio Psych Department and the Grute Eylandt Aborigines.
You can know everything the user does in your app if you want. You could use your own solution with an SQLite database for example, and dispatch the data to a server every once in a while.
The GPS is also easy, you could just track the user with the Core Location framework.
You can't make the app wake at specific times, the best you can do is implement push notifications but it's up to the user to open the app via the notification or by themselves by tapping the app icon on the iPhone home screen.
Otherwise you could set up a local notification just before exiting the application, this is faster and easier to implement then setting up push notifications.
There is also no way to stop the app being closed, that is until iOS 6 comes along with it's accessibility features, you can disable the home button then. But not now.
I am building a small app that I can use to do Interval Training,
it schedules a series of UILocalNotifications, all scheduled at the same
time and all fired within a few minutes of each other.
The idea is that you put in your headphones and start a workout,
when you hear one kind of sound you rest and another kind of
sound you workout. I do this with localnotifications, it works
just fine. The reason for doing it like this and not just
having the app run with a timer is that I would like for
the Nike +iPod app to run in the foreground at the same time.
The notifications are just an alert and an OK button:
[notif setHasAction:NO];
So the idea is: Pop in the headphones, start my app, it schedules a series of notification - then start the Nike +iPod workout. When you hear the Notification sound, change from rest to workout or vice versa.
Ok, when the workout is over there are 15+ notifications on the screen and they need to be manually dismissed, this is a bit annoying and not at all user friendly.
My question is now if there is a way to post only sound notifications? OR make sure earlier notifications are removed as new ones pop up OR is there a different/better way of going about achieving the functionality of getting a "sound indicator" while the app is in the background?
Hope someone can lend a bit of experience or a good idea for an alternative:)
Thanks in advance.
I can't confirm how well this would actually work, but if you set the alertBody property on your UILocalNotification object to nil (this is the default value) when you create them, it should prevent an alert from appearing on screen as you fire them.
In addition, you might also want to set the hasAction property to NO, which prevents the user from seeing the action buttons (if you had an alert), or the slider (if they had the device locked).
But as for the actual stacked notification alerts - I don't believe there's any way to prevent them getting stacked. That's something which might be worth raising a Radar for, so Apple could consider allowing that to happen in future iOS versions.