iOS background usage of Network.Framework - ios

I've written a simple WiFi based App using TCP on Network.Framework that receives about 80 bytes every 10s from a remote service on specific port. I want to write this data to file while in the foreground and the background.
The question is which of the background modes if any/is permitted/best fits this requirement?
All wisdom gratefully accepted.

Without knowing anything else about your app (is it a music app?, location?, VoIP?, bluetooth?) it's hard to say what you might do. But there are two classes of background actions:
Actions that are ongoing when you go to the background that can be finished.
Permitted background actions for specific kinds of apps. See "Implementing Long-Running Tasks" in the link you have about background modes.
The first doesn't really apply to you since this is ongoing. Of the second items, I'd guess that "Background fetch" is the one that fits best.
Note that you won't necessarily be called as regularly as you might like. But since your time interval is quite long (10sec) then a few hundred milliseconds latency wouldn't be particularly damaging I'd guess.
But also note that "Enabling this mode is not a guarantee that the system will give your app any time to perform background fetches. The system must balance your app’s need to fetch content with the needs of other apps and the system itself."

Related

Download multiple files with operation queue not stable in background mode

Currently what I want to achieve is download files from an array that download only one file at a time and it still performs download even the app goes to the background state.
I'm using Rob code as stated in here but he's using URLSessionConfiguration.default which I want to use URLSessionConfiguration.background(withIdentifier: "uniqueID") instead.
It did work in the first try but after It goes to background everything became chaos. operation starts to download more than one file at a time and not in order anymore.
Is there any solution to this or what should I use instead to achieve what I want. If in android we have service to handle that easily.
The whole idea of wrapping requests in operation is only applicable if the app is active/running. It’s great for things like constraining the degree of concurrency for foreground requests, managing dependencies, etc.
For background session that continues to proceed after the app has been suspended, though, none of that is relevant. You create your request, hand it to the background session to manage, and monitor the delegate methods called for your background session. No operations needed/desired. Remember, these requests will be handled by the background session daemon even if your app is suspended (or if it terminated in the course of its normal lifecycle, though not if you force quit it). So the whole idea of operations, operation queues, etc., just doesn’t make sense if the background URLSession daemon is handling the requests and your app isn’t active.
See https://stackoverflow.com/a/44140059/1271826 for example of background session.
By the way, true background sessions are really useful when download very large resources that might take a very long time. But it introduces all sorts of complexities (e.g., you often want to debug and diagnose when not connected to the Xcode debugger which changes your app lifecycle, so you have to resort to mechanisms like unified messaging; you need to figure out how to restore UI if the app was terminated between the time the requests were initiated and when they finished; etc.).
Because of this complexity, you might want to consider whether this is absolutely needed. Sometimes, if you only need less than 30 seconds to complete some requests, it’s easier to just ask the OS to keep your app running in the background for a little bit after the user leaves the app and just use standard URLSession. For more information, see Extending Your App's Background Execution Time. It’s a much easier solution, bypassing many background URLSession hassles. But it only works if you only need 30 seconds or less. For larger requests that might exceed this small window, a true background URLSession is needed.
Below, you asked:
There are some downside with [downloading multiple files in parallel] as I understanding.
No, it’s always better to allow downloads to progress asynchronously and in parallel. It’s much faster and is more efficient. The only time you want to do requests consecutively, one after another, is where you need the parse the response of one request in order to prepare the next request. But that is not the case here.
The exception here is with the default, foreground URLSession. In that case you have to worry about latter requests timing out waiting for earlier requests. In that scenario you might bump up the timeout interval. Or we might wrap our requests in Operation subclass, allowing us to constrain not only how many concurrent requests we will allow, but not start subsequent requests until earlier ones finish. But even in that case, we don’t usually do it serially, but rather use a maxConcurrentOperationCount of 4 or something like that.
But for background sessions, requests don’t time out just because the background daemon hasn’t gotten around to them yet. Just add your requests to the background URLSession and let the OS handle this for you. You definitely don’t want to download images one at a time, with the background daemon relaunching your app in the background when one download is done so you can initiate the next one. That would be very inefficient (both in terms of the user’s battery as well as speed).
You need to loop inside an array of files and then add to the session to make it download but It will be download asynchronously so it's hard to keeping track also since the files are a lot.
Sure, you can’t do a naive “add to the end of array” if the requests are running in parallel, because you’re not guaranteed the order that they will complete. But it’s not hard to capture these responses as they come in. Just use a dictionary for example, perhaps keyed by the URL of the original request. Then you can easily look up in that dictionary to find the response associated with a particular request URL.
It’s incredibly simple. And we now can perform requests in parallel, which is much faster and more efficient.
You go on to say:
[Downloading in parallel] could lead the battery to be high consumption with a lot of requests at the same time. that's why I tried to make it download each file one at a time.
No, you never need to perform downloads one at a time for the sake of power. If anything, downloading one at a time is slower, and will take more power.
Unrelated, if you’re downloading 800+ files, you might want to allow the user to not perform these requests when the user is in “low data mode”. In iOS 13, for example, you might set allowsExpensiveNetworkAccess and allowsConstrainedNetworkAccess.
Regardless (and especially if you are supporting older iOS versions), you might also want to consider the appropriate settings isDiscretionary and allowsCellularAccess.
Bottom line, you want to make sure that you are respectful of a user’s limited cellular data plan or if they’re on some expensive service (e.g. connecting on an airplane’s expensive data plan or tethered via some local hotspot).
For more information on these considerations, see WWDC 2019 Advances in Networking, Part 1.

In iOS11, how to keep a background task running past 10 min?

My question involves keeping an app that monitors user interactions in the background, for example time spent in one or the app. The issue arises when you can not have a background process run for more than 10 min or violate Apple's sandbox restrictions. Since I am relatively new to the Apple API, and could not find a direct answer that didn't involve location services or VOIP (which are both interesting options, but my application will not be able to use either viably), I come to ask for options in which I can understand when another app opens, when it closes, when it fetches data, and when user holds phone in certain orientation (ie when people hold their phone at certain angles to read text and etc.) for certain amount of time.
The purpose of this analyzation is to predict an attention span for the user, so I need to be able to run in the background, as the user will not be using my app while it predicts attention span.
My thoughts on this are possibly accessing the system log, and somehow parse previous statements (I don't think sandbox will allow), but inevitably the iOS system will suspend my processes after some point unless I put a timer. There is also the option of having the system wake up my app via opportunistic fetching, but that won't be useful if I don't collect the data.
Keep in mind this is within IOS 11, so it is much more restrictive than previous iterations. I understand this may seem like a complex problem, but even a direction in which to head could be useful to me.
This solution might work, (not recommended since it drains the battery quicker).
Just update your current location, every 10 mins. It will reset the background thread timer.

Continue background task after 3 minutes

I tried the answer of this question
How can a connection started with NSURLConnection while in the foreground be continued in the background?
And works like a charm! but only for 3 minutes in background, then iOS sends the app to sleep, Im trying to upload n videos and 3 minutes is not enought to send all data, I also readed that I can change my NSURLConnection to NSURLSession but I have no idea how to start that or how much time it takes.
Is there a way to keep background task alive after 3 minutes and until upload ends?
Is there a way to keep background task alive after 3 minutes and until upload ends?
No, there isn't. On-going background execution is limited to very narrow purposes (e.g. playing music, VOIP apps, navigation apps, etc.). All of this is outlined in the Background Execution section of the App Programming Guide for iOS.
I also [read] that I can change my NSURLConnection to NSURLSession but I have no idea how to start that or how much time it takes.
Yes, this is correct. If you want network request to continue for more than a few minutes after the app enters background, you should use NSURLSession with a background NSURLSessionConfiguration. See Downloading Content in the Background in the App Programming Guide for iOS for more information. See WWDC 2013 What's New in Foundation Networking for introduction to NSURLSession, including a demonstration on how to do background session.
I'd suggest you tackle this in two steps: First, convert to NSURLSession, and second, enable background NSURLSession operation. I think you'll find this first step is pretty easy. All of the concepts are very familiar. The only trick is that NSURLSession has two types of interfaces, delegate-protocol pattern and completion handlers. If you plan on using this for background operation later, you'll want to stick with the delegate-protocol pattern because the simpler completion handler pattern is not compatible with background sessions. And you'll want to use the upload task method that uploads from a file (don't use the stream-based rendition).
This second step, enabling background operation, isn't hard, but it can be tricky, though, simply because it involves a few new little details that we haven't had to worry about in the past (e.g. the app delegate code to capture (and later call) the completion handler for background sessions). Also, when you start debugging background session code, it can be disorienting to have requests initiated by one debugging session to show up in the next debugging session (hey, they're background sessions that are supposed to keep running when your app is terminated, after all). It's not a problem, but can be a bit disorienting.

battery consuming tasks when launched in the background

Apple states that the app using the background mode shouldn't perform expensive, battery consuming tasks when launched in the background. What exactly is considered a batter consuming task? To be specific: is searching and array of 100 entries acceptable? What about 1000?
A battery-consuming task is just that - a task that uses so much CPU that it makes considerable "dent" on the battery, as measured by the "battery percentage" screen. To that end, searching 100, 1000, or 1000000 items a single time is unlikely to do any damage. On the other hand, searching a 10-item list fifty times a second is very likely to make your task a high energy consumer. Same goes for downloading data multiple times per minute, using location services, etc.
A rule of thumb is very simple: go to the "Last 24 hours" view of the "Battery percentage" screen, and see if your app is listed there. If it is not there, of if it is below "Home & Lock Screen", your app is fine.
The remark from the guidelines you are referencing is meant to keep people form draining a user's battery in the background.
As a lot of applications use GPS and/or radio in the background and those are way more power consuming than searching tiny arrays, searching some array will probably be fine, as long as it has a reasonable size.
You shouldn't create an app that helps SETI or Folding or searches for the next biggest prime - or excessively use radio. But for small tasks like your's, this guideline is not to be concerned. Yet, this is only an estimate and in the end, the review process will decide on this on a case by case basis.
The general rule of thumb from apple is:
Always try to avoid doing any background work unless doing so improves the overall user experience. An app might move to the background because the user launched a different app or because the user locked the device and is not using it right now. In both situations, the user is signaling that your app does not need to be doing any meaningful work right now. Continuing to run in such conditions will only drain the device’s battery and might lead the user to force quit your app altogether. So be mindful about the work you do in the background and avoid it when you can.
So the question for you to decide if this is okay is: Does the user expect that to be done right now? rather than does that use too many battery?. If searching that array cannot be deferred to when the app is active again (I cannot see a reason for not deferring it, but there might be), you are fine searching the array in background.

Possible to make a task scheduler for iOS?

I want to make an app where I can have a task (GET URL) run at predefined times (selectable in UI). For instance, Monday to Friday at 8am.
Is this possible in iOS?
I tried searching but haven't found anything very useful, probably using the wrong search terms. Does anyone happen to find some sample code for what I'm trying to do?
Edit: Pointing out that I want the app to perform these tasks even if the app is not running. I want to user to just select wanted days of the week and time, and then the phone will take care of everything - even if the phone is restarted.
If you want to regularly wake up to download content, you can register to get push notifications, and download based on the contents of the notification. You are likely to get some cycles to do this close to the scheduled time. If you want to 'opportunistically' download content you can register for background 'fetch' but there is no guarantee of scheduling.
See
https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
So, first of all, the app has to be open for any kind of task to run. After that, there are 2 ways you can do it:
You can set a timer with a selector, or you can use grand central dispatch. Both have their strengths and weaknesses depending on what the task is...
https://developer.apple.com/Library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/index.html
https://developer.apple.com/library/ios/documentation/performance/reference/gcd_libdispatch_ref/index.html
check out those links and see if they can help.
Remember that you should do stuff like this on a background thread, and that the UI cannot be updated from any thread by the main thread. Additionally, remember the limitations iOS puts on background applications.
Yes, it is possible.
You can use -
[self performSelector:#selector(myFunc:) withObject:nil afterDelay:5.0];

Resources