Locations while in background - ios8

Sorry if this one's a bit of a stupid question.
I'm currently building an iOS app which needs to be able to have (or acquire) the user's location when a push notification is received, potentially waking up the app. Previously, I was just monitoring significant location changes, updating a property as locations were received, using the last acquired location when the push notification is received (the location doesn't need to be very accurate, within 0.5-1.0 km will suffice).
However, with the highly annoying changes to location permissions in iOS8, this now requires 'always' authorisation - which repeatedly prompts the user about the access, greatly increasing the chances it will be turned off altogether. So my question is basically twofold. Will 'when in use' authorisation allow the location to be accessed even when the app is in the background, woken up by a push notification? And if it will, is there anything special I need to do to get the location - for example, wait a few seconds for the GPS to acquire a position, or make a call to enable location monitoring?

Related

How exactly do Firebase Analytics handle session duration / timeouts?

I'm implementing some basic usage statistics for the first time in an Android/iOS app using Firebase Analytics, but the docs seem a little ambiguous to me on how exactly session durations are calculated and how sessions are timed out, and the 24-hour cycle for seeing results does not help in understanding by trial-and-error.
I'm only interested in a very simple statistic for now - the time users spend in the app. What exactly happens when the app is "minimised"/"in the background" - does that count as active usage or the same as the app being closed - is not so important right now, but if you have something to add in this regard in the context of the question, please do.
From what I understand such an easy statistic should probably be available out-of-the-box with Firebase Analytics, so I'm currently not using any custom events or anything fancier than simply linking Firebase Analytics into the projects, adding the configuration files, and calling FirebaseAnalytics.getInstance(this); on Android and [FIRApp configure]; on iOS.
I'm seeing first_open, session_start and app_remove events show up in the console as expected, some aggregate session data in the dashboard, etc, and I also know there is a configurable session timeout available.
But what is unclear to me is, when exactly does a user session expire - does Firebase automatically keep it open as long as the app is open, or do I need to make sure to post some artificial "keep-alive" events to prevent user sessions from expiring while a user is still actually using the app.
Assuming the following:
I send no explicit custom events using Firebase, as this is not
explicitly required by the app.
I only touch Firebase once during a single run of the app - initialising it on startup.
The user stays in the app for a long time (let's say 2 hours - much longer than the default 30 minute session timeout), without interacting with it - e.g. reading something, watching a video, etc, none of this generates any events that Firebase can see, but the app prevents the screen from locking, the app remains in foreground.
Will that count as a single 2 hour session for the user? Will it only count as a 30 minute session since the session expires after 30 minutes and no events are generated to keep it alive? Will something else happen?
Bonus question: what happens if the user exits the app for a time shorter/longer than the session timeout?
Bonus bonus question: does something change if instead of exiting from the app, it is simply put into background?
Thanks!
Quick answer: The scenario you describe will result in a single 2-hour session.
Sessions are based on the time that an app's activity is the current activity. There is no need to send events; the period from the time an activity resumes to the time it is suspended is counted as engagement time. At the end of an hour of continuous engagement an engagement event will be logged but this does not end the session. A session expires when there is a continuous period (30 minutes by default) that none of the app's activities is the current activity.
If the user exits the app for a shorter period than the session timeout and then restarts it, the session continues. If the user exits the app for longer than the session timeout, then the session ends. No change between exiting the app and putting it in the background. If it's not the thing the user is looking at, it doesn't count as engagement for the app to be running.

Why does didUpdateLocations: only have one location after locationManagerDidResumeLocationUpdates:

I have location services working in iOS8.
It is set for kCLLocationAccuracyBest using startMonitoringSignificantLocationChanges to restart when in the background and startUpdatingLocation for accuracy.
When I set pausesLocationUpdatesAutomatically = YES, the location services get paused and resumed as expected. However, the following call to didUpdateLocations: only has one location in it.
I was expecting to receive a bunch of locations that were received by the OS while the delivery was paused. Am I missing something here? Does it have anything to do with deferredLocationUpdatesAvailable?
This answer talks about a post on Apple Dev Forum, but I get nothing when searching for pausesLocationUpdatesAutomatically.
Please note: this issue has nothing to do with calling requestAlwaysAuthorization or setting prompts in info.plist.
Further to the answer by Quentin Hayot...
The documentation for pausesLocationUpdatesAutomatically states:
Allowing the location manager to pause updates can improve battery life on the target device without sacrificing location data.
This is highly misleading.
What it really means is when location manager pauses it will sacrifice location data: the app does not get and never will get location updates until the location manager resumes.
It should explain that paused location updates are completely different from deferred location updates.
To improve battery life, the app should call allowDeferredLocationUpdatesUntilTraveled:timeout: which does deliver all location updates gathered while deferring to locationManager:didUpdateLocations:.
The documentation for locationManager:didUpdateLocations: states:
If updates were deferred or if multiple locations arrived before they could be delivered, the array may contain additional entries.
which is reasonably clear, but it could state that it has nothing to do with, and should not be confused with, pausesLocationUpdatesAutomatically.
When you pause the location updates, the system considers that you don't need the location for now. Resuming it will only give you the current location.
This is a normal behavior.

caching to memory, writing to file and saving to iCloud while iDevice is locked

Here is the deal, I have an application in which the device listens to iBeacons in the background and timestamps the moment user passes the area in range. Initially, as soon as I get a didEnter call back I used the chance to save the information to the iCloud using CloudKit. But sometimes on a bad luck, the internet is not available at that very moment and saving fails (e.g. when the user is in elevator).
I tried to use FMDB to write the information to database and sync them when app enters foreground. That doesn't work either. Since iOS8 by default encrypts the disk and does not allow me to write to disk after the phone gets locked by the user or the phone get a reboot (eventhough there are some APIs in NSFileManager to let you write to a file until it's open called "NSFileProtectionCompleteUnlessOpen" but they don't work after few hours of phone being locked. Perhaps a bug).
Third solution was to write them into a array and use reachability to sync them to iCloud as soon as I get a chance (on location callbacks, appdelegate callbacks or reachbilityChanges notification). But this solution is not secure to app termination. If the user termiate the app I dont have enough time to do anything.
The last solution is a mix of all together. Write to array if the disk is encrypted. write to disk if not encrypted. sync them all together and save to internet at any time possible. Do not want to put myself in alot of hassles before getting some help.
Do you have any idea how to deal with this?
You have 10 seconds of time to execute in the background after a region entry/exit event. You can save the data into an Array in UserDefaults during this time. Then do the syncing with CloudKit when the app is active.

how to handle UI actions on front-end responsively while waiting for the processing in back-end?

Use a StackOverflow Q&A thread as an example - when you vote up, vote down, or favorite a question, you can see the UI quickly respond to that action with changes in the # of up-votes on the side.
How can we achieve that effect? If send every of such action to back-end for processing and use the returned response to update UI, you will see a slow update and feel the glitches. But if put some of the logic on the front-end, you will also need to take care of the fraud/abuse etc before reflecting the action on UI, i.e - before changing the # of up-votes, don't you need to make sure that's a valid click by an valid user first?
You make sure that a valid user is using the app before a user clicks on anything. This is done through authentication, and it must include various protection mechanisms against malicious users.
When a user clicks, a call is made to a server. In a properly architected app this call is lightweight, and the server responds very quickly. I don't know why you believe that "you will see a slow update and feel the glitches". Adding an upvote to the database should take a few hundred milliseconds at most (including the roundtrip from the client), especially if the commit is asynchronous or a memcache is used.
If a database update results in a need to do some complex operations, typically these operations are not done right away. For example, a cron job may run periodically to compute new rankings, etc., precisely because you do not want every user to wait. Alternatively, a task is created and put in a task queue to be executed when resources are available - again to make sure that a user does not wait.
In some apps a UI is updated immediately after the call to the server is made, before any response from a server arrives. You can do it when the consequences of a failed call are negligible. For example, if an upvote fails to be saved in the database, it's not a disaster, especially if it happens once in a million tries. Again, in a properly architected app calls fail extremely rarely.
This is a decision that an app developer needs to make. I would not update a UI before a server response if such an update may lead a user to believe that some other action is now possible. For example, if a user uploads a new photo, I would not show icons to edit or share this photo until I know that the photo is safely saved.

Windows Phone Background Application Service

In my windows phone 8 application, I would like to refresh/load some data periodically (less than 10 minutes) from server, while application running in background (ie, in dormant and tombstoned). I tried scheduled task agent and resource intensive task agent, but they are called at rate of 30 minutes gap. Please let me know is there any other solution for implementing the above said requirement.
Thanks and Regards
#nish
If you need to get data more frequently than the default available in Windows Phone, you should think about using push notifications. This won't be suitable for a full data push, but if you use it correctly, you can get a user experience that you can live with.
One common approach to this is to set up your server to send a notification to the device when there is something new to report instead of pushing a "nothing has changed" message every 10 minutes or so. If you push out a tile update notification to say, for example, "You have x unread items", the user may then click on the tile for your app and you can poll the server for new items on launch/resume. If you want a more intrusive option, you can send a toast notification as well, but in most cases the tile update will be sufficient.
This method has a few advantages.
You won't be burning through battery power polling every 10 minutes while the user is asleep
Your server will have significantly less load since it is not having to process full data requests every 10 minutes per client.
This fits in with the design philosophy of Phone apps - you are surfacing the required data to the user, while at the same time preserving battery life.
Do I understand correctly that your primary goal is to keep some host session alive by having the phone make a query periodically? If so...
I would not recommend this approach: 1) you cannot count on the phone having network connectivity when it tries to send its query. If the user puts the phone away in a pocket or purse, the odds worsen. 2) it's probably bad from a security perspective, and wasteful from a host resources perspective.
You might instead add logic to your app to resume a timed-out host session as seamlessly as possible. This would add real utility value to the mobile app value proposition over raw HTTP access to the same host.

Resources