No GPS onLocationChanged callbacks while app in background? - cllocationmanager

I have a working app that processes and logs GPS positions using the LocationManager's onLocationChanged() callback. It works fine until I put the app in the background, e.g. by going to another app using the "Recent Tasks" button or Home button. Updates resume when I bring it to the front again. Interestingly, I do see status changes from GPS "Temporarily Unavailable" to "GPS Available" when brought to front. I do check "isProviderEnabled()" while in background but it always returns true.
I see no mention of this artifact in the LocationManager doc: maybe this is an undocumented but intended behavior (???)
I tried implementing GPS listener as a service. No joy.
Then I tried spawning an ASyncTask inside Service (including GPS listener on service start). Still no joy.
In either case, same behavior: onLocationChanged not called when app that started Sevice goes to background.
Anybody have a suggestion?

I found the solution: I need to use a Foreground Service.
This is described in https://androidwave.com/foreground-service-android.example
With this change, GPS fixes are then received even after main activity is stopped (finished).

Related

AVAggregateAssetDownloadTask stops sending updates when going to background (perhaps stops downloading)

First off, I'm on iOS 13.6.1
I'm downloading HLS videos to later play offline. It all works as expected when in foreground, all the logic does what it should and there doesn't seem to be any problem.
But when the app goes to background I stop getting updates for the AVAggregateAssetDownloadTask (I mean, I don't see the logs in the delegate callbacks printing in the Xcode console).
I followed the documentation:
NSURLSessionConfiguration sessionSendsLaunchEvents is set to true
The AppDelegate implements handleEventsForBackgroundURLSession
The Session delegate implements URLSessionDidFinishEventsForBackgroundURLSession
Also, I have background modes enabled for fetch.
The crazy thing is, if I hook up the instruments network monitor, I do get all the updates. And I see that the download keeps going in the background.
Even without the changes mentioned in the documentation indicated above, I still see that the download keeps going in the background with the monitor open.
But it seems that the network monitor keeps the app alive somehow, because if I don't open it, then I get zero updates.
To be clear, I'm not even thinking about downloads starting or finishing in the background, and waking the app or anything of that. I just want to start a download, go to the background and have the download keep downloading stuff and notifying me (which AFAIK is done in a separate process, and I can confirm from the network monitor it is).
An example:
open the app
start a download
go to background
no updates are shown
open the instruments network monitor and connect to the app running in the device
suddenly start getting updates
I'm running out of ideas. Nothing makes sense anymore, short of a bug in the framework.
Any sort of idea will be greatly appreciated, no matter how simple it may appear.
Thanks in advance!
PS: when going to settings>storage I sometimes see that the file size grows while in the background, which would mean that the download is continuing even if I don't see updates from the delegate callbacks. At some points I saw the file size unchanged over a period of background time, but that might have been an unrelated thing (I hope).

Local Region recognition while the app isn't running in iOs

I'm developing a simple application that when i press one button, creates a Local Region. Till this is all ok, the app creates Region and notify correctly when i enter in this, even if my app is in background. Now, i think that my question is so tricky. Can i create an app that while it's running creates a local region, but even when it's NOT running notify that we are entered in the region created before? I want to know if there is a method that allow me to monitoring significant location changes, even when the app is closed. And if this method recognize (with the app still closed) that i'm entered in a Local Region, starts to uploading my location (i don't know, with a costant interval or something).
You can set a region and your app will get notified via the UIApplication's Launch Options. This will launch you app and you can handle the event then. There will be some limits what you can do when the app is still in the background.
This article from Apple should be helpful: https://developer.apple.com/documentation/corelocation/monitoring_the_user_s_proximity_to_geographic_regions
Edit: You also must enable Location updates for Background Modes in the Capabilities.

iOS Location Services do not run after terminating app

First time posting here, so please forgive me if I'm asking a question with a simple answer, but I can't seem to find anything relevant for my case.
I'm trying to have location services run on an iOS app indefinitely throughout pretty much all the stages of the app lifecycle. The user has an option inside the app to activate a certain functionality which starts location services, with the expectation that these services must run even while the app is terminated.
The issue I'm having here is that, when I terminate the app manually, it just stops working.
Here's what I've done so far:
Added background modes in Capabilities (location)
Added Application does not run in background mode and set it to NO in Info.plist. Also added the NSLocationAlwaysUsageDescription and
NSLocationWhenInUsageDescription.
When initializing CLLocationManager, I have set the following: desiredAccuracy to kCLLocationAccuracyBestForNavigation;
distanceFilter to kCLDistanceFilterNone; activityType to
CLActivityTypeFitness; pausesLocationUpdatesAutomatically to NO;
allowsBackgroundLocationUpdates to YES; and calling
requestAlwaysAuthorization.
Tried initiating significant or region monitoring on applicationWillTerminate: method in the app delegate.
So, I understand that what I've done in point 4 should restart the app once a change is detected. At least I've managed to get that much to work with significant changes but not with region monitoring. However, it does not work instantly. The only way I found this to work instantly is to either deactivate/activate airplane mode, or turn the device off and on.
Is there any way to make this work (almost) instantly after terminating the app? What I want to achieve here is to relaunch the app right after the user has terminated it, so that the app can continue to do whatever it needs to do with location services. Would there be any implications when submitting to the app store?
I have seen some things about using a background task to achieve this, could this be the way to go?
Thanks.

How does iOS Google Map detect I am entering a car?

The latest iOS Google Map application(currently of version 4.9.0) has a very nice feature, but so far I can not figure out how this is possible.
The feature is: whenever I am entering my car, try to drive somewhere, Google map will send me a notification to my phone, guess where I am going, giving me an estimate of the traffic, even when the phone is in locked state, and the Google map app hasn't been used for days. A screenshot is provied as following:
This is quite amazing to me as an iOS developer. How can it live in the background and detect I am entering a car with such accuracy?
One of my guess is, Google map is using significant location change API. By using this way, the app can be waken in background mode, but, there is still no guarantee it is waken when I am entering my car. And I have already written a test app using this mechanism, although it can be waken in the background, but the timing is not correct, failed to detect I am entering a car or not.
CLLocationManager Class Reference
If you start this service and your app is subsequently terminated, the system automatically relaunches the app into the background if a new event arrives. In such a case, the options dictionary passed to the application:willFinishLaunchingWithOptions: and application:didFinishLaunchingWithOptions: methods of your app delegate contains the key UIApplicationLaunchOptionsLocationKey to indicate that your app was launched because of a location event. Upon relaunch, you must still configure a location manager object and call this method to continue receiving location events. When you restart location services, the current event is delivered to your delegate immediately. In addition, the location property of your location manager object is populated with the most recent location object even before you start location services.
Any suggestion and help appreciated.
One comment from #alexkent points out my mistake. This is Apple's Maps.app, not Google Maps. All credits belongs to #alexkent.
That notification is from Apple's Maps.app not Google Maps. A new
feature in iOS9 (which you must be running) is the ability to detect
when you are in your car. I imagine this is done by detecting the
Bluetooth signal from the car radio (I have not checked this). I do
not believe there is developer API available for this feature.
#alexkent is right. It works using bluetooth and there is no public API for that. If you close your bluetooth this stops happening.
Geofencing and in general Geolocation accuracy is not that granular.

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