Get CMMotionActivityManager updated when app is terminated - ios

Right now I'm developing an app that needs to know what the user is doing activity-wise (standing still, running, walking, ect.) all the time. I found that using CMMotionActivity might be a good way to do this.
Except for one thing: when the app is terminated, the CMMotionActivityManager stops running. First I tried to solve this by creating a cronjob to send remote silent notifications every n minutes and wake the app for motion data. I then did some research and found that silent notifications do not wake the app.
After some more research, I found that using Location and startMonitoringSignificantLocationChanges the app will be woken from a terminated state when the user moves 500 meters or more.
However, I believe I need more data then one point every 500 meters. Something more along the lines of one point every 5 minutes would be nice. But the sense I get is that startMonitoringSignificantLocationChanges won't update even if the user stands still for a whole day.
So my question in a nutshell is two parts:
Am I misunderstanding startMonitoringSignificantLocationChanges? Will it give me a notification every so often even if the user doesn't move?
If I don't misunderstand significant changes, is there any way to get Motion Updates every n minutes even when the app is terminated?
Thanks friends.

Related

Background fetch regularly

I want to upload the location in background every 30secs to 1min. Is it possible?
I have found that I can set UIApplicationBackgroundFetchIntervalMinimum. But I looked around this constant to tell the device to fetch about every 30mins. Any way to do that? Thanks.
I don't know the exact purpose of yours for uploading location for every 30 secs. It's not recommended to do so. I think you can go for MonitoringSignificationChanges in CoreLocation framework. It will give you update whenever there is a significant change in location. It helps in saving the battery.
Starts the generation of updates based on significant location changes by the following method:
func startMonitoringSignificantLocationChanges()
This method initiates the delivery of location events asynchronously, returning shortly after you call it. Location events are delivered to your delegate’s locationManager(_:didUpdateLocations:) method. The first event to be delivered is usually the most recently cached location event (if any) but may be a newer event in some circumstances. Obtaining a current location fix may take several additional seconds, so be sure to check the time stamps on the location events in your delegate method.
Fore more info: Apple Docs
Your approach has multiple problems. Most apps are not allowed to run continuously in the background like you want to do. You get ~3 minutes of background time, and then your app gets suspended. Navigation apps are an exception. If your app is a navigation app you are allowed to run continuously in the background.
Polling the GPS every 30 seconds is also a bad idea unless you're a navigation app. You'll quickly drain the user's battery.
Likewise uploading the user's location every 30 seconds will keep the cellular/WiFi radio on the phone powered up nearly constantly, which will drain the user's battery quite rapidly.

Add life every N hours

I want to implement mechanism that will be add one life to UserDefaults.standard.value(forKey: "lifes") every 4 hours even if app was closed and notify user about it.
About notifications i read articles, it will not be hard. But how increase life number value if i didn't be in game for 12 hours. I should get +3 lifes when back.
You get an event when the game is paused (UIApplicationWillResignActive) so you can write down in user defaults what time it was. You get an event when the game resumes (UIApplicationDidBecomeActive) so you can check to see what time it is and how many hours have elapsed since you became inactive.
This is not possible if the app is "closed".
The only way to achieve this behaviour is to use Push Notifications (pushed by your server, not the app).
See this and this Apple documentation.
My opinion is, that the user will delete your app, as she will get disturbed by too frequent notifications.

Waking up an app from background by a time interval?

is it possible on newest ios to make a tracking app wake up every x minutes in order to send the stored locations to an url, even if the user is not moving?
Requested functions of the app are:
App is getting locations based on distance filter (example: only get coordinate via gps, when user has moved more than 10 meters.
App is not allowed to send every new position immediately to url
App should store all new locations of the last 3 minutes
App should send stored positions (of the last 3 minutes) in an interval of 3 minutes. (! Even if user has not moved since a while, app shall connect to url.
App is mainly running in backround.
Example case:
User has moved more than 10 meters at 9:00:11 to position 53.432, 13.245, at 9:01:20 to position 53.235, 13.435 and at 9:03:10 to position 54.002, 13.768. No more movement of more than 10 meters before 9:15:00.
So from 9:00:00 until 9:15:00 device has located 3 coordinates.
Order from server is: Send all locations in an interval of 3 min., starting from 9:00:00.
Requested result is:
At 9:03:00 app sends all positions from 9:00:00 until 9:03:00:
9:00:11: 53.432, 13.245,
9:01:20: 53.235, 13.435
At 9:06:00 app sends all positions from 9:03:00 until 9:06:00:
9:03:10: 54.002, 13.768
At 9:09:00 app sends all positions from 9:06:00 until 9:09:00:
„no new positions“....
Problem is:
App has to be waken up, in order to process actions like sending informations to the server.
One event, that could wake up the app would be a movement of more than 10 meters.
But since user is not moving from 9:03:10 until 9:15:00, there is no event that wakes up the app. App stays suspended and will not send the location of 9:03:10 before next movement at 9:15:00
Solution?
Are there other possibilities to make the app wake up and send stored locations at 9:06:00?
Can apps have an internal timer to wake up?
(According to my understanding a timer app is not waking up, when the alert sound should be given. Instead it is scheduling a local notification to fire at the time of the alert.)
But if it is possible to schedule local notifications, can´t an app schedule other actions like „wake me up“?
Thanks a lot for your time and help!
the app can attempt to run background tasks, but it can't force itself to stay in existence - the OS will shut it down after a couple of minutes, regardless of local timer handlers or notifications.
Your best bet is that as soon as the user has moved more than 10 metres, the server starts sending push notifications. You can have a handler which can wake the app in the background, and you can use this handler to send data back to the server.
There are a lot of rules regarding when to use certain background modes, so in case you haven't come across it before, check out this link.
https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html

In iOS, is it possible to start region based geofencing at a particular time?

My iOS app (which targets iOS 8.1+) use location services to determine if a user has entered a particular region during an event. Ideally I would like to enable the geofencing a little before the event and turn it off a little after the event completes. The problem is there is no guarantee the app is running an hour before the event so I turn on geofencing at the point the user registers for the event. This is not the best approach as it means the geofencing is on for much longer than it needs to be.
As far as I can tell, there is no way to "wake up" the app in the background at a scheduled time in iOS. I could use the push notification meant for updating content, but It's not clear to me if Apple would reject such a misuse of that notification.
Any suggestions?
I've been looking into this myself.
If you can arrange a push notification from your backend ("Silent push notification", aka "content-available"), it seems to be a good option. In real-world situations, this seems to give you the best control over the timing. Unfortunately, it won't work if the person doesn't have connectivity. Also, unfortunately, you need a backend that can queue events at a time (not just in response to an input.) If you have such a backend already, and your app is only useful to the user when they have network coverage anyway, this is probably the best option. It seems this an appropriate use of the technology, so Apple should approve.
Another option I'm trying is to use background fetch. You specify a "minimum interval" to avoid too much fetching. Try 50% of the remaining time-to-event as a minimum. Every time the app wakes up (whether in the foreground because the user opened it, or in the background because background-fetch opens it) you can calculate the time-to-next-event, update the fetch interval, or start the region monitoring. You are supposed to use "background fetch" to fetch information from a server, but there doesn't seem to be any requirement to poll a server, you could poll your internal data instead. I haven't fully tested this yet but it seems promising.
You can use significant location change monitoring, which I've read will wake up your app briefly every 15 minutes or less, and you can use the time/location information to decide whether to turn on the geofence. I think this would work well in combination with the above "background fetch": Many hours or days before the event you rely on background fetch, which you then use to turn on significant location change monitoring a few hours before the event. (There's speculation that geofencing is actually more battery efficient than significant change monitoring, but you could choose to assume that other apps on the user's device will already by watching for significant changes, in which case the marginal cost of your app adding itself to the list should be minimal.)
Putting them all together, you could create a sequence of
background fetch -> significant location monitoring -> geofencing
as the time gets closer.
There is also the CLVisit monitoring functionality, it's not understood very well, but supposedly uses less power and is called less frequently than significant location change monitoring. If the background fetch or silent remote notifications aren't working to wake up your app, give this a try, and please report back!
You can't (yet) do a silent content-available local notification (AFAICT). However, perhaps you can schedule up a local notification "Your event starts tomorrow" or something that convinces the user to click the option that starts the geofence. Here's a tutorial on it http://www.appcoda.com/local-notifications-ios8/, the response of action can be UIUserNotificationActivationMode.Background so your geofence can come on (if the user responds to the notification) without bringing the app to the foreground.
It's been 5 to 6 weeks since you asked, do you have your own answer already? Please let me know.

When waking up from significant location change notification how much time do I have in the background?

Testing an app that monitors a region then wakes up to do some processing. I cant seem to find anywhere documentation that says how long I have to do work in the background before the watchdog timer kicks in and kills the app.
I saw a document (even I believe official one) where most of the timings related to background was shown. However, I can't find it right now (I will try to find it and post here).
Based on my experience, I believe application is awoken for 10 seconds while significant location change. Also, the interesting thing that if you try to do call backgroundTimeRemaining it will return +INFINITY for these 10 seconds (generally speaking this API is designed only for beginBackgroundTaskWithExpirationHandler:)
Update 1
Sorry. I wasn't able to find that document. I have a feeling that it was remove/updated by Apple, because before (about 6 month ago) I hit it quite often while searching information on iOS backgrounding.
I found couple of interesting things. One is here. It's related to VOIP callback.
It says: "Your handler has a maximum of 10 seconds to perform any needed tasks and exit. If it does not exit before time expires, the application is suspended."
Also, the same 10 seconds are mentioned here for Bluetooth:
"Upon being woken up, the app has around 10 seconds to process the data."
I believe underlying mechanics for location manager wake up, VOIP and Bluetooth wake up are exactly the same and all of them grant 10 seconds of execution time/
you can register for a maximum of 10 minutes background-task.
But if you want to know, how long the called method can be executed, try measuring it with a infinite while-loop!

Resources