We have been looking for a reliable way to periodically get data from a URL from an iOS app, regardless of the state of execution of the app on the device (foreground, background, suspended or terminated/force-quit).
We have gone through all the questions on this topic that are on this site, and their answers, as well as all the relevant iOS documentation from Apple and blog posts we can find on the subject. But, we have not yet found a solution that will work.
Here is what has been considered/implemented:
Background fetch - This is our current implementation. It works at the whim of the OS as far as the frequency and timing of the fetch goes, and only when the app is not "terminated" or "force-quit" by the user. This has been found to be totally unreliable, as the users themselves don't understand the quirks of iOS, and force-quit the app, yet expecting it to function even after that. The app deals with financial information, and thus can result in loss of potential financial gains to the users if the fetches are not performed on a schedule.
Change notifications from the server - this is not an option, as we neither store nor wish to store certain information on a server, for privacy reasons. Therefore, we cannot use this.
Silent notifications from the server to trigger fetch - again, this won't work if the app has been force-quit, as the notifications are not delivered to the app in that state.
PushKit - this is what apps like WhatsApp or Vonage would use to fire the app regardless of its state of execution. However, this is only available to VoIP apps, and we don't fall into that category. Can this still be used by non-VoIP apps? If so, we could settle for this but only as a last resort, as the preferred option is to have it all done from the app without involving a server to generate "empty" push notifications, simply for the purpose of triggering a URL download.
Given the nature of the app and the potential for the user to benefit financially, it seems rather harsh that iOS would not allow a simple operation such as a periodic download of a URL. So, hoping that someone knows how to overcome this challenge.
As an aside, the exact same functionality on Android works like a charm, regardless of the app's state of execution.
Related
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.
We are designing a system that based on particular events on the server creates geofences for particular device. It is expected that the client (device) will be in sync with the server data, question is how?
Initial (most optimal) idea was to send a silent push to the device to notify it about new data, and trigger data pull. Knowing that this solution will work for Android OS devices, we though the problem can be solved in similar fashion on iOS. Unfortunately, my iOS dev told me that silent push are not reliable on iOS, and presented following discussion: Silent push notifications only delivered if device is charging and/or app is foreground.
Therefore, my question is how to keep the (geofence) data on the iOS devices in sync with server side?
We can pull, say every say 5 minutes, this solution is extremely inefficient, for most of the devices new geofences are changed rarely if at all, but our ‘power users’ need to have geofences updated very often.
We could push with some kind of silent push mechanism, but it has to be reliable.
Maybe some kind of persistent connection (tcp or better udp) but that seems like battery draining solution. Besides not reliable, the server would have to keep track of changing IPs which is not even possible on many cellular networks.
WebSocket. Also battery draining solution, that is not intended for background sync. Overkill for devices that really have the data updated rarely (like once a month).
Some commercial solution (PubNub or Pusher), but we would definitely prefer in house solution.
Are there any other solutions that are used in such cases? Maybe our approach with silent push is not right, but there is other build in Apple solution for such use case?
There's a fantastic service called Simperium with an iOS SDK that can help keep your info in Sync. I heard about them because I started using SimpleNote, a free note-taking tool that uses the sync service. They were acquired by Automattic, which runs Wordpress so the whole deal should be decently stable.
Hope this helps!
You can run your syncing operations in the applicationDidEnterBackground: method within AppDelegate. That's the solution I've always used as long as the syncing operation doesn't take too long.
Here you can also query your database for data changes instead of pushing a trigger to the device, which could get hairy with push notifications and aren't really their intended use. If changes in the data are found (or some boolean flag is checked) then initiate a data pull.
I'm not sure how much data you are working with but having a REST query every 5 mins is the way I'd go. Perhaps you can even switch it to a query each time you start up the app would be good enough?
We have an app where the user data needs to be sync'd with the back end server - each time we start the app it queries the backend server to see if there are any updates. We md5hash the data from the server and then we can just check our hash against the latest data - if it doesn't "match" then we pull the new data set.
In general, iOS doesn't really allow you to do multi-tasking the way you can do on android. Now, if you aren't releasing to the app store - and only using this as an in-house app you can get a little funky with things and run in a background mode.
I'm trying to look for a way as to how I can notify a user of new updates based off of a .Net API that I created. Much like that notification you get on facebook, I just need to alert the user that something has been updated. So I'm thinking I need a function that runs in the background while my user uses the app combined with a NSTimer.
Based on my research (and on this question https://stackoverflow.com/a/14835300/639713) apparently you can only achieve such a thing for VOIP and location services. And that using push notification is the only way. Is it really the only option that I can use for such a need? Or are there any other ways?
Thank you for your time.
You have two options:
While your app is open, poll the server every so often to see if there are any updates to report.
This will work only as long as the user has your app open, and as you note, your app will only be allowed to stay open for a long time if it happens to be a VOIP or navigation app.
Use push notifications to push updates to the user’s device.
The disadvantage here is that you will need to write some server-side code to talk to Apple’s push notification servers (as described in this tutorial). This may or may not be a big deal in your particular situation, but it’s the only way to get data to the user when your app isn’t open.
I have a requirement to develop an app that is capable of receiving pushed information from a server - which as its not possible to intercept SMSs or apple push notifications would probably have to be implemented as a poll and see what's there or similar type of thing.
However of course such a thing isn't possible if the app isn't executing in the background.
The app couldn't be considered to be musical or voip related, however its possible that it could be considered to be gps related as the pushed information would be displayed to the user based on certain triggers, and one of those triggers could be location.
Would this app with a UIBackgroundMode of gps submitted to the app store stand a good chance of being accepted?
i have been trying to do the same thing and here is what i found
iPhone - Backgrounding to poll for events
(top answer: update 2)
shows a method that should be ok, meaning your app wont be rejected for using it. the guy who posted it said it should be ok and i have asked other members who said the same (i have not verified this myself).
here is my implementation of that post
local notifications?
You don't have to use a hack for your requirements.
iOS provides a facility whereas your application is suspended but your socket is still monitored. If there's any incoming traffic on the socket, the app is woken up and handed back the control of the socket.
Advanced App Tricks
Look under the heading, "Tips for Developing a VoIP App"
Within my iPhone application I periodically make calls to a webservice, providing the endpoint with a list of numeric IDs. The webservice then returns information relating to the IDs it receives.
This is all well and good. However, I would like to be able to provide functionality whereby the user will receive a local/push notification when these changes occur, regardless of whether the application is open or not.
I'm just looking for guidance on my options in this scenario. As I see it, there are two main approaches: calculate any data changes on my webserver and send a push notification to all devices, or query the webservice from the device itself.
The second option seems ideal, as not all devices will need each push notification, but I'm unsure as to whether this is possible with the current state of iOS' multitasking APIs. Any advice would be appreciated.
Bad news: it's not possible. Apps can only run in the background for a short period of time after the user has exited unless it fits into a small number of categories (GPS, VoIP, etc).
Web services, unfortunately, do not count. So this would have to be performed on the server side and with push notifications.