Ios schedule task for specific time even when app closed? - ios

is it possible to run a cllocationmanager at a specific time even when the app has been closed (not terminated)?
For example I need to maintain a location between 22:00 and 01:00 and pass it to my server at 15minute intervals. It will be disabled as default to protect privacy as well as battery life.
It's not integral to sucess but could add a new revenue stream.
Any ideas?
Thank you for your time.

On iOS 7 you can (link -> "Multitasking Enhancements").
Apps that regularly update their content by contacting a server can
register
with the system and be launched periodically to retrieve that content in the
background. To register, include the UIBackgroundModes key with the fetch value
in your app’s Info.plist file. Then, when your app is launched, call the
setMinimumBackgroundFetchInterval: method to determine how often it receives
update messages. Finally, you must also implement the
application:performFetchWithCompletionHandler: method in your app delegate.

Related

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

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.

Can an ios app fetch data from a server even if it is terminated

I need my app to alert the users about certain updates. I am aware that I can do remote notification service but all I want to get, is a small count variable and I was wondering if I could do it with something simple like, pinging the server every 30 minutes, even if the app is not running. I believe that such a provision exists for Android
I think the iOS background mode "background fetch" is exactly what you describe.
From the App Programming Guide for iOS - Background Execution:
Fetching Small Amounts of Content Opportunistically
Apps that need to
check for new content periodically can ask the system to wake them up
so that they can initiate a fetch operation for that content. To
support this mode, enable the Background fetch option from the
Background modes section of the Capabilities tab in your Xcode
project. (You can also enable this support by including the
UIBackgroundModes key with the fetch value in your app’s Info.plist
file.) 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. After assessing that information, the system
gives time to apps when there are good opportunities to do so.
When a good opportunity arises, the system wakes or launches your app
into the background and calls the app delegate’s
application:performFetchWithCompletionHandler: method. Use that method
to check for new content and initiate a download operation if content
is available. As soon as you finish downloading the new content, you
must execute the provided completion handler block, passing a result
that indicates whether content was available. Executing this block
tells the system that it can move your app back to the suspended state
and evaluate its power usage. Apps that download small amounts of
content quickly, and accurately reflect when they had content
available to download, are more likely to receive execution time in
the future than apps that take a long time to download their content
or that claim content was available but then do not download anything.
When downloading any content, it is recommended that you use the
NSURLSession class to initiate and manage your downloads. For
information about how to use this class to manage upload and download
tasks, see URL Session Programming Guide.

WatchKit perform task when app inactive

I am creating a standalone app for Apple Watch that measure heart beat rate every 30mn and send them to the server.
I am referring to this projet to extract the heart beat rate. The project contain a class that extract this measure via HealthKit.
What I need to do is to make this task running permanently, even if the app in inactive. And be able to disable it via a settings view in my app.
So my question is: how to perform a task permanently in background in an Apple Watch application?
Thank you.
Look what they say in documentation:
Workout sessions let apps continue to run in the foreground.
So you app can gather heart rate information while app is inactive. Then you can use workoutSession(_:didChangeToState:fromState:date:) method and split information into 30 minute intervals according to date property.
If your application is suspended, the delegate receives this call
after the application resumes. This means you may receive the
notification long after the state changed. Check the date parameter to
determine when the state change actually occurred.
Finally you can send information to server when app becomes active.
UPD:
You also can call openParentApplication:reply: inside workoutSession(_:didChangeToState:fromState:date:) to send stats to server in the background (on iphone).

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 does the Navita TEM app get call log information?

How does Navita https://itunes.apple.com/us/app/navita-t.e.m.-personal/id590228620?mt=8
manage to display a call log?
If I swipe the app out of the task manager then it misses the calls, this indicates that it must presumably be using CTCallCenter's callEventHandler and is creating its own call log by saving the time/duration in response to the callEventHandler callbacks.
However if that is the case then how does it manage to do this in the background? I was under the impression that callEventHandler can only be used by apps in the foreground and not in the background?
The app is using location services, however even after disabling this it was still able to get information about the calls (provided the app isn't suspended). I though it might be using background location updates to keep itself primed to receive callEventHandler callbacks but apparently not.
The Navita app is additionally able to display call time and call duration.
The bounty will be awarded to an answer which contains sufficient, accurate and detailed information that enables me to emulate the behavior of the Navita app, specifically I must be able to write an app that can obtain the time and duration of a phone call that occurred while the app was not in the foreground, while the device's location services was turned off, and after the app had been in the background longer than the ~3 minutes granted by using beginBackgroundTaskWithExpirationHandler:
Here is what I observe with the Navita app that I want to be able to reproduce:
1) Run app
2) Task away from app
3) Go to device settings, privacy, and turn off Location Services.
4) Go to device settings, privacy, background app refresh and turn off for the app
5) Wait > 10 minutes to make sure the app is not still in the background as a consequence of using beginBackgroundTaskWithExpirationHandler:
6) Call the device from another phone, answer the phone call, then hang up.
7) Launch the app again and display the call time and duration
(This is iOS7 and unjailbroken)
Here is what I've found from Navita TEM disassembly and it's resources.
Application uses two background modes - location and audio. You can see it in the Info.plist file. When you enable phone calls logging application will also enable "alerts" and "Real-time" switches. When "alerts" enabled application infinitely loops in background "bg-sound.mp3" file which has no sound, it's just silence. Because of that it doesn't use hacks like this one How to get a call event using CTCallCenter:setCallEventHandler: that occurred while the app was suspended? . It's similar trick to location used in order to keep the app running in background and receive phone call events. Somehow this was not rejected from the AppStore.
If you are observing the call center while the app is in the background you get a set of updates when the app is brought back to the foreground. This set of data may not be as accurate as if the app had been mostly in the foreground but it does include quite a bit of info.

Resources