WatchKit perform task when app inactive - ios

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).

Related

Handling server being aware if iPhone app is running (heartbeat)

I am not sure how to best implement keeping our server informed that our iPhone application is currently running (even when in the background). There are a few different options but there is some concern as to what is allowed by the Apple approval process as well as what is the most reliable. The application does have the ability to play music in the background, if that factors into what is approved by Apple.
The first option, is to continually send some sort of heartbeat to the server at a set interval through a simple GET/POST; however, the concern is whether or not this is allowed as a background task. In a very roundabout way it can be argued that it is necessary for the playback but I'm not so sure whether or not that is acceptable. If the server does not hear from them in a set amount of time it will assume the app is no longer running.
The second option involves using a presence channel socket connection and have the server just handle when users enter and leave that channel. With this option the main concern is how reliable is a socket connection like this while an app is in the background. Similarly, whether or not this is allowed by Apple. In this case when the app dies, connection closes and server knows app is not running.
Third option can be used in tandem with either of the other options but to use some sort of APNS push to query the phone as to whether or not it has died and have it respond with some data to let us know; however, this seems somewhat counterintuitive as the push itself wakes the app up.
Any other suggestions or input are also welcome.
Not sure if this should be a comment or answer, but let me put my 2 cents here.
Firstly, Can you please elaborate your needs further, because in case you are playing an Audio in background with AVPlayer/AVPlayerItem you would hand over your content URL to iOS and it will make the calls as and when necessary to keep the playback running, you dont need to know about apps' state.
Let me assume, for whatever reasons you want to achieve what the question asks:
There are 3 states your app can be in when it is "Not Running"
i. Suspended State: your app is not killed but its not receiving any CPU time to execute your code.
ii. Killed by OS: Your app can be terminated by iOS to free up the memory or any other resources.
iii. Force Killed by User: If user swipes up your app from app switcher it gets force killed.
Now when your app is Not Running, you CAN NOT query it, but you can move it to Running State. You can achieve this transition by using following methods (Not exhaustive list, but mentions common ways)
i. Background Fetch : You can configure your app to be invoked periodically, so that it can synchronise with the server and updates its state.
ii. Push Notifications (APNS) : You can ping the app from server so that iOS invokes it for some short period of time (few seconds) to update its state.
iii. VOIP Pushes: If your App is VOIP app you can use PushKit to send Silent Pushes which will launch even the Force-Killed Apps, the above two methods does not transition the app to Running state if it was force killed by user
The above point can be helpful in devising overall strategy but does not answer the question, "How to keep syncing the RUNNING state"
i. When your app is Running(Forground/Background), you can do almost anything that is publicly documented, you can keep calling a URL every minute or every 5 seconds, you need to worry about UX on the device rather than approval process, (People will delete app if they see your app in top battery drainers in the settings section)
ii. For making an HTTP call while your app is in background, you can look at Background URL Session, which off loads the HTTP calls to another process so that the call completes even if app gets killed.
iii. For the socket based approach please refer this technical note. The main issue is that you do not/can not know when your app moves from Running to Not Running State.
iv. As you mentioned that your app uses background audio, it will be always be in Running state if the user plays an audio and puts app in background, in such case you can use Periodic Observer to do some Heartbeat call periodically when the content is being played out.

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.

Ios schedule task for specific time even when app closed?

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.

Implementing Long-Running Background Tasks in iOS

my client asks me to develop some app that periodically retrieves the user location & the phone battery status, and then send them to our backend server for data analysis, then feed back by push notification.
But through the app doc, I get to know that from apple ios dev doc:
For tasks that require more execution time to implement, you must
request specific permissions to run them in the background without
their being suspended. In iOS, only specific app types are allowed to
run in the background:
Apps that play audible content to the user while in the background,
such as a music player app
Apps that keep users informed of their
location at all times, such as a navigation app
Apps that support
Voice over Internet Protocol (VoIP)
Newsstand apps that need to
download and process new content
Apps that receive regular updates
from external accessories
I'm wonder if this would be feasible if we wrap this app as some navigation app so we can have long-running background tasks? Does appstore will reject on our app?
BTW, what is the definition of navigation app by Apple?
You might consider using:
[CLLocationManager startMonitoringSignificantLocationChanges];
This will cause your app to be restarted if it has been killed whenever the location changes significantly, allowing you to update the details on the server at fairly regular intervals, assuming the user is moving. This does not require any special background permission. From the docs:
If you start this service and your application is subsequently terminated, the system automatically relaunches the application into the background if a new event arrives. In such a case, the options dictionary passed to the locationManager:didUpdateLocations: method of your application delegate contains the key UIApplicationLaunchOptionsLocationKey to indicate that your application was launched because of a location event.
Your other option is to configure the app as requiring continuous location updates in the background, but without knowing the primary function of the app it is hard to know if this will pass store submission or not.
https://github.com/yarodevuci/backgroundTask Check my code here I am using audio player that plays blank wav file Works perfectly on IOS 8 Battery usage around 10% in 24 hour period How to use:
var backgroundTask = BackgroundTask()
backgroundTask.startBackgroundTask() //Starts playing blank audio file. You can run NSTimer() or whatever you need and it will continue executing in the background.
backgroundTask.stopBackgroundTask() //Stops the task

Running IOS App with Screen Locked

I am working on a sports app that uses GPS and OpenEars text-to-speech. The app delivers speed and other GPS info to the user audibly (via earphones) so the user (skier, cyclist, etc) can get the GPS info without looking at the screen. In order to save battery life, I would like the app to run in the background with the screen off. Is this possible with IOS? I tried setting "Required backgrund modes" for both GPS and audio, but my app quits working when the screen is off.
thanks..
One one to get around it is to have a silent audio file playing, when there is no audio, it might get your app rejected in the app store though... here is a question that talks about the silent audio file playing to keep in the background... It might get through app store approval in your situation since it is an app that relays on audio as one of its main functionalities..
You can subscribe to GPS info change notifications and your app will run when something needs to be updated. Check this.
Please note this sentence:
"If you leave this service running and your application is subsequently suspended or terminated, the service automatically wakes up your application when new location data arrives. At wake-up time, your application is put into the background and given a small amount of time to process the location data. Because your application is in the background, it should do minimal work and avoid any tasks (such as querying the network) that might prevent it from returning before the allocated time expires. If it does not, your application may be terminated."
There's no way to do it as service except some special cases provided by ios. But you can simulate it. This post answer how to:
https://stackoverflow.com/a/19121250/2835520
I hope it's gonna help!

Resources