iOS Enterprise app - How can I make sure my app runs in the background? - ios

First of all it's important to note that I'm developing an Enterprise App, so there is no need for App Store guidelines \ approvals considerations.
My goal is the following:
1) An iPhone app which the user should open only one time only. During this one time he will go through some sign up process.
2) Once step (1) has finished (either by app suspension or app close), the app should "wake up" every hour (more or less) and send the server some data regarding the user from the background (all is done with the user agreement of course).
Optional Solutions I tried:
I read very thoroughly Apple guidelines for running in background in https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
I decided to go with 2 UIBackgroundModes:
location
fetch
1) For location I use:
startMonitoringSignificantLocationChanges();
manager.requestAlwaysAuthorization()
In order to make sure my app will run after "app close" or even "device reboot" I had to use both options. See Apple guidelines:
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html#//apple_ref/doc/uid/TP40009497-CH2-SW1
If you leave the significant-change location service running and your
iOS app is subsequently suspended or terminated, the service
automatically wakes up your app when new location data arrives.
2) For background fetch I use
performFetchWithCompletionHandler()
and
UIApplication.sharedApplication().setMinimumBackgroundFetchInterval(UIApplicationBackgroundFetchIntervalMinimum);
For some reason the app doesn't run in background after 24 hours. Meaning the app never "wakes up" again even though according to Apple guidelines whenever significant location update occurs - it suppose to wake up.
What can I do in order to guarantee as much as possible that my app will run regularly in the background?

In your project properties you have to allow background mode for your application to Update location and for background fetch.
Fetch in background is not so easy as it seems.
iOS will define by itself how often it will fetch data in background modeeven you set option for each 15 minutes :(
As my practice shows time interval for fetching new data is less if user open application from time to time so iOS makes some calculations about normal app use. As a result app calls background fetch data according to app ussage.
But you can make one trick:
you can call fetch procedure from you location procedure. For data exchange it was usefull in my projects :)

The solution worked with Silent PN.
My goal as noted in the bounty was: ".. to have an iOS app that runs regularly in the background for 30+ days when not opened at all. Should also run after the app closes."
I found that when sending PN with "content-available" : 1 did the trick for me.
I set up a server which sends every 15 min a "silent PN" to all registered devices. I was able to confirm from the same server that those clients receive the PN and act on it.
Thanks #andlin for the advice.

Related

iOS Backrground Sync Alternative for enterprise apps?

I have been investigating iOS background fetch for our enterprise applications. According to articles like this, there are limitations like having 30 seconds to download before the app is terminated and the may be (unconfirmed) a penalty where after 3 timeouts, an app gets banned from background sync. Also if the user kills the app, fetches stop happening -noted here.
The goal is to be able to retrieve data from our servers periodically when app is suspended/not running but sometimes the transfers can take minutes due to long running SQL. I don't want to implement sending periodic notifications to all users.
Before I go down the path of developing for the iOS background sync, I needed to do some due diligence and research alternatives to iOS's background sync and didn't find anything.
Has anyone seen or developed an alternative to iOS's background sync or dealt with this issue for their enterprise apps?
As an enterprise app there's nothing extra you can do except that you can use whatever background modes you want (audio, location, voip etc,) without needing to have a legitimate reason to do so.
Where this might assist is:
you could make use of a significant location change (as opposed to a regular location change) notification to run your app in the background. The problem with this is it of course depends on the user of your app to move around. However, assuming everybody in your workforce commutes to/from work with their iPhone then you would have two opportunities each day for the app to run in the background. A app run due to a location change can be made to execute in the background for more than 30 seconds.
voip pushes: Unlike a regular push notification, a voip push will launch the app even if the user has force terminated it. To make use of this functionality is only a tiny bit more effort than using regular push, you don't have to do anything regarding making or receiving an actual voip call, you just need the voip capability and voip certificates instead of normal push certificates.
The comment in that link is not correct regarding force quitting and background fetch - a user force quitting an app does not make it ineligible to run for a background fetch, I have force quit my own app that uses background fetch but it will still be started by the OS, however what will happen is that the frequency when the app is run will decrease lots, and if the user never runs the app again then the OS will stop launching it.
A user force quitting an app will prevent other things from happening, such as it running in the background in response to a silent push notification for example (unless its a voip push).
Also the 30 seconds in not related to download times, NSURLConnection would stop after 30 seconds, NSURLSession is designed to continue to download on your app's behalf. But if you are downloading and then applying lengthy SQL processing it would be an issue. But minutes of processing time seems excessive, are you sure its all optimized?
The goal is to be able to retrieve data from our servers periodically when app is suspended/not running
The only reliable way to achieve such a behaviour is implementing a User-facing Remote (Push) Notifications framework on backend & apps.
You can append 4kB (or 5 for VOIP) worth of data in the push JSON payload, eliminating need for a network fetch request if implemented in a handshake mechanism.
You can evaluate usage on Silent Remote Notifications to augment content updation & fetch small amounts of content opportunistically, though it has the same as Background App Refresh.
You can definitely improve the API that can take minutes due to long running SQL
And remember you need to have the app updated only when the user actually fires it up. Evaluate implementing a catchy & smooth fetching content screen that transitions into the actual screens once all data is fetched.

iOS GPS Tracking app shutdown in background

I'm currently working on an iOS app using objective-C that send every minute gps coordinates to my API.
I've used AFNetworking & CoreLocation, I also wanted my App to run all day long, but only send coordinates if time is between 8am - 6pm.
Everything's working fine on iOS simulator targetting iOS9 my app is sending his location every 1 minute to my API, even if i press home or lock the phone.
PhoneCall, loss of network or GPS have been handled in order to keep my task running.
But when I tested it on some device (iPhone 4S on iOS9) Location stop updating after an average time of 1hour to 1hour and a half.
Is iOS shutting down my app in background after a given time?
If so, is there a way to keep my app doing her job in background for at least 10 hour, without having to prompt the device user?
Implementing long running background task are "allowed" by apple if it concern:
"The app keeps users informed of their location, even while it is running in the background."
Does that mean background task will block my http request after a while?
For long term deployment, I wish my app to be upload on the App Store, but I've read many post about app GPS tracking app which have been rejected.
Here's the minimal list of requirement my app should have:
Send GPS coordinates to my API every minute
Working in background for a minimum time of 10 hours without shutting down or prompting user to reload the view
Could those requirement be accepted to get my app upload on AppStore?
Or will I have to use local/remote notification and prompt the user to reload my app in order to keep it running for such a long time?
The documentation says.
The significant-change location service is highly recommended for apps that do not need high-precision location data. With this service, location updates are generated only when the user’s location changes significantly; thus, it is ideal for social apps or apps that provide the user with noncritical, location-relevant information. If the app is suspended when an update occurs, the system wakes it up in the background to handle the update. If the app starts this service and is then terminated, the system relaunches the app automatically when a new location becomes available. This service is available in iOS 4 and later, and it is available only on devices that contain a cellular radio.
I think this will be apt for your scenario.

Is there a way to set an iOS app to automatically download data every night?

We have a customer who wants us to have our iOS app check for new data posted every night and download it if it is available. As far as I can tell this is only possible if the app is already open or if they have someone physically accept a notification or initiate the process themselves.
Is this correct? I can't imagine Apple wanting to allow launching of an app and downloading data with no user interaction at all.
Yes, generally you can only download data at exactly specified times if the app is actually running in the foreground, that is correct. It wouldn't matter if the app was open already or the user opened it from a notification, the point is that user interaction is required. So, the client can't have exactly what they want.
Look at background downloading (fetch) from iOS7+ where you can register the app to perform background downloading in advance of usage. iOS is fully in control of this and it may choose to run the app and it may not. iOS will monitor when your app is usually used by a particular user and, if appropriate, it will allow the app to run in the background to do some downloading before the user is expected to use the app.
In particular you're looking at setMinimumBackgroundFetchInterval: and setting the UIBackgroundModes key with to fetch in the Info.plist.
As an aside, here's an idea based on your expanded information:
Use idleTimerDisabled to prevent the app from sleeping during main usage and keep a track of the time
After the main usage period of the app is over, start your downloads
After the downloads are done allow the screen to sleep
On the next day, if a user opens the app, repeat
It isn't perfect, but it's an approximation

How to run run a process frequently as a background service ios

I am working on ios app that used to read ticket data as a barcode scanner. It needs to upload data frequently to a web server, Like two or three times a day. I have done the sync function. I just wanted to run the function when the app is run in background.
This is not possible on iOS, Apple is not allowing any kind of background service on iOS.
The options you are left with is setting your apps background mode to fetch and implement application:performFetchWithCompletionHandler:. But it is totally up to ios if and when this method is called.
You could misuse one of the other background modes to keep your app open in the background, but Apple might reject your app for doing so. Also user might complain about you app draining battery.
What kind of data is that you need that you have to update it two to three times a day? I would say the when the app is opened by the user would be a good time to update, because this is when the user is expecting new data.
If you need to inform the user about some data changes you should be pull it in the app but a server should send a push notification to inform the user that there is new data.

guaranteed delivery for uploads after network reconnect, even if my app is not running

I'm spec-ing an iOS app (which will be built outside of our company) which will upload a user's data entry to a server. If the device is not connected to the Internet, we'd like to save data on the device and upload it when the network is re-connected. (The app will primarily run on iPod Touch devices that will be disconnected most of the time).
If the user unlocks the device and re-opens our app after the network is reconnected, then uploading to the server should be easy because the app is running.
But what if the app is not running, where "not running" can mean one or more of:
device was power cycled
user has locked the device and it's sitting in his pocket
app crashed
user exited the app
user started using other apps so our app isn't running in the foreground anymore
are there other cases?
In the cases above, is there a way (ideally a battery-efficient way) to ensure that local data is uploaded soon after Internet connectivity is restored? Is the answer different depending on which of the cases above caused the app not to be running?
And is there a minimum iOS version the device will need in order to enable some (or all) of the above not-running cases to still upload when the app is not running?
My apologies if these are obvious newbie questions-- I'm not an iOS expert.
There is an interesting technique that is used by among others Instapaper and News.me(the pioneers of this technique) where you use region monitoring to initiate background downloads or uploads. Marco (Instapaper) blogged and talked (in episode 80 of the Build and Analyze podcast) about his communication with Apple so it should be a allowed in the App Store.
In brief the technique is that you set up certain regions (geofences) like "home" or "work" and respond to the locationManager:didEnterRegion: (and similar) callback(s). Your app will wake up from the background once you enter the pre-specified region and you can check to see if there is any data to upload.
This technique won't guarantee that the data is uploaded when the network reconnects but it will allow your app to automatically upload the information when the iPod Touch users gets home to their WiFi network.
That should most likely be at least once a day which may or may not be frequent enough for you. You could add a timestamp to when the initial upload was attempted and send that along the upload once it succeeds to get the correct order of events (data entries) on your server.
There is no way to ensure this. If your application is "not running" (by the definition described in your question), it will not be capable of responding to a change in the device's network status. It should be setup to resume upload operations the next time the application runs again.
EDIT:
Some of the cases you've described may indeed provide different opportunities for your application. Specifically, if the user "exits" the app by pressing the home button or launches another app in the foreground, your application may continue to run the in the background and could potentially respond to a change in network reachability.
The nature of what may be done in the background and for how-long is well documented, and supported by any version of iOS that supports multi-tasking. I recommend you review the documentation pertaining to App States and Background Services.
device was power cycled --> really NO WAY of resuming, unless you open the App!!!
user has locked the device and it's sitting in his pocket --> apps applicationStatus is UIApplicationStateInactive but it is running in the background. You still are able to react to notifications and i.e. accelerometer events. Try the Reachability Class and Log the changes!
app crashed --> NO WAY, unless opening the App
user exited the app --> App is sitting in the background. There you have a maximum of 10 Minutes Restriction of fully using your App (like the App "Pastebot" does)
user started using other apps so our app isn't running in the
foreground anymore --> Same as user exited the app
On multitasking Apple says the following:
Real multitasking only for certain kinds of usage, as there is Audio Background playing, VOIP (like Skype), navigation applications
All the other apps can request a specific amount of time after the app is closed/in the background, to finish certain tasks (as sending an email, sms or uploading/downloading important data)
Important Quote from dev docs:
Your app delegate’s applicationDidEnterBackground: method has approximately 5 seconds to finish any tasks and return. In practice, this method should return as quickly as possible. If the method does not return before time runs out, your app is killed and purged from memory. If you still need more time to perform tasks, call the beginBackgroundTaskWithExpirationHandler: method to request background execution time and then start any long-running tasks in a secondary thread. Regardless of whether you start any background tasks, the applicationDidEnterBackground: method must still exit within 5 seconds.
If you're building a restful API then I would recommend using RestKit, it has a request queue that checks the network status on the device and starts uploading once network access has been assured. You can read more about this here: http://mobile.tutsplus.com/tutorials/iphone/advanced-restkit-development_iphone-sdk/. Read the sections about Request Queue and background download/upload. It should be noted that RestKit is a big library which has it's advantages and disadvantages. I'm not completely sure how this que works with the app lifecycle, if it saves the request que even if the app is terminated. You would have to investigate that. RestKit does support background uploading/downloading, but as already noted, I think it's impossible to do any uploading if the app is terminated and not in background state.
I wouldn't recommend using RestKit if the API isn't Rest though.
You can download and experiment with RestKit here: https://github.com/RestKit/RestKit.

Resources