We have an iOS app which is collecting some data (location, accelerometer, etc.) in the background. We would like to upload this data to our server so our server can do some analysis on the data; we would like to batch all the collected data and upload it to our servers periodically, perhaps every 12 or so hours (so ~2 times a day).
After looking around I've seen lots of recommendations:
Background Fetch: This appears to be limited to downloads and also isn't guaranteed execution
Silent (Push) Notification: This also appears to be not guaranteed, especially when the app is terminated. Also setting up our server to auth with APNS and send notifications seems excessive for such a simple 'problem'.
Continuing Upload: Specifically when the app is entering the background. This is a good first step, but because we want to batch data doesn't solve the upload on schedule problem.
I was considering testing if we could use applicationSignificantTimeChange to kickoff an upload at midnight, but that seems to only trigger when the app is opened.
So my question is, is it possible to "wake" our app on a schedule to start a background upload?
You can look into the Background fetch again and I believe it can solve your problem.
Look into Selene Library on how to run periodic tasks.
and also glance through how to run code when your app is terminated
Related
I have a VPN-Client app that asks the user to pause the connection for 5, 30, and 120 Minutes. The user probably leaves the application to do some work outside of my app in this period, therefore I need to Reconnect the app even if is in the background.
I tested these ways:
UIApplication.shared.beginBackgroundTask: It only leaves the app unsuspended for 30 seconds.
DispatchQueue.global(qos: .background).asyncAfter: It waits to app enter the foreground to toggle.
Thread.sleep in Background Thread: This waits to launch as DispatchQueue
Local Notification: Unfortunately it does not support silent mode as APNS.
My problem with possible ways:
Using APNS and Scheduled Push Notification` to send a silent message: This way probably works, but I prefer to handle it without a server.
Using Background Fetch from Capabilities in Background Modes: I searched a lot about this, and I think it was used for background app refresh and cycling tasks that should be run every day, hour, etc. Therefore, my case can't be used, or it's not efficient at all.
Using Background processing from Capabilities in Background Modes: I searched a lot about this too, I didn't quite catch that it can be used once, or this should be used in a cyclic way as Background Fetch. and my task to reconnect is not that heavy and long to use this strict feature that many times apple mentioned using alternative ways if possible.
Apple only allows a very limited set of app types to run in the background:
Music streaming apps, turn-by-turn navigation apps, VoIP apps, and maybe one or 2 more. (I haven't looked at this in detail for a couple of years so my info is a little stale.)
They do support various tasks like background downloading that the system performs on your app's behalf, but you want your app to re-launch after the designated period and start running again. (Even if the user just locks their phone while your app is paused, the app won't get any CPU time and may be terminated without warning.)
In short, I suspect you are out of luck.
It seems like a VPN app is another class of app that should get "always running in the background" status.
If you are a licensed Apple developer I suggest using one of your pre-paid support tickets to ask about OS support for what you are trying to do, but I have a feeling the answer is going to be "no dice."
I have been looking at the options available to do a user driven on demand sync of a large data set (roughly 1gb) to a iOS device from a central server. The intention is that the user will go offline some time after the sync is complete, and use the app in offline mode for some time afterwards. However, I am running into a lot of iOS restrictions that seems to prevent this.
The beginBackgroundTask does not allow enough time to complete a sync before its suspended as it only allows up to 30 seconds of background processing. I have seen a few references to this being increased by using audio or gps functions however neither of these are applicable to my situation.
The BGProcessingTask apis are at the systems discretion as to when they are run, so are not sutiable for an on demand process.
The NSURLSession api allows for downloads to occur while the app is suspended, however the problem with this api is that it requires the server to extract all necessary data to a temporary file before it can be downloaded, this process can take several minutes. This introduces the problem where the application can be suspended before the server has completed generating the file to download.
I'm aware a background push can be used to wake the app and start the download using the NSURLSession api if the app has been suspended, however this approach places the execution of the download back at the discretion of the OS which can lead to significant delays in the sync actually starting, which makes for a rather undesirable solution.
Its also worth noting that precalculating and caching the data to download in advance is not a viable option due to the number of updates that occur and different permutations of data depending on permissions assigned to each user.
With that, are there any apis that I have not considered, or any misinterpretations to the ones above that would allow me to achieve an on demand sync of such a large data set?
It seems iOS is missing the ability for a user to explicitly opt in to starting a long running process and allow it to continue till complete. I'd assume some other enterprise apps would have come across a similar problem before, and I would be gratefull to see how its been solved.
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.
I'm building an app that fetches data from a third party server and syncs some of that data to my own server. The data for all users will be aggregated on my server and the results will be displayed in the app. The whole data sync (3rd party server -> App -> My server) should be done at least once a day. The app is only for a limited group of users and will be distributed with an enterprise account.
I'd prefer it to sync the data in the background, so the results on my server are always up to date and do not depend on the single users to open the app. I figured I'd use setMinimumBackgroundFetchInterval with UIApplicationBackgroundFetchIntervalMinimum so the sync would be handled in performFetchWithCompletionHandler in my AppDelegate. Unfortunately it doesn't seem to be possible to set a fixed interval for the background fetch. So I can't control when the sync is done, since it partly depends on the way the app is used when and how often the background fetch is executed.
Is there a way to modify the background fetch so I could guarantee the daily sync?
Or is there any other way to execute a background task on a daily basis with which I could accomplish the above?
The only solution I could come up with is a usability nightmare with daily local notifications to remind the users to open up the app, so that the background fetch can "learn" when to execute. I know this sounds bad, but I do have to present a solution to our customer :/
I have an iOS app that needs to sync a lot of data from the cloud to device when first installed, maybe even 2GB worth if the user wants access to everything offline. Without saying "change your design", how can I ensure this initial sync completes without too much interaction from the user?
Currently it will complete as long as they keep my app in the foreground and don't let the device go to sleep. I'd like to allow them to use other apps or let the screen turn off during this process, since it's a pretty boring thing to watch.
I've seen application:performFetchWithCompletionHandler: and
beginBackgroundTaskWithName:expirationHandler, but they only allow for a short amount of time (around 30 seconds) to complete a task. Is there something better, or do I need to complicate my design by stopping my sync every ~25 seconds, and then resume next time I'm given more time by the OS?
My app is like Microsoft Outlook, it has emails (in some case millions), contacts, calendar, and several other areas. I have different sync options to limit the amount of data, but some users want access to everything offline (yes, even emails and attachments that are 10 years old). I think they are silly, but can't argue with the end-users.
I know this is a really old question, but I suggest you use NSURLSession to download data in the background even without your app running.
You simply create an NSURLSession that uses a Background NSURLSessionConfiguration (use NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier:) and create an NSURLSessionDownloadTask for each request you need to download.
NSURLSession will download the data even when your app is not running at all, and it will save the data as files in your app's sandbox. Implement the NSURLSession delegate methods to receive notification of the download completion, read the downloaded files and save them how you see fit.
You should check out Apple's guide on Using NSURLSession.