Developer David Nottage proposes an interesting solution to a problem some of you might have noticed on FireMonkey when switching to iOS 9 or higher, in particular the Location Sensor stops working when the application is in background. The reason behind this behavior is that Apple introduced a new required property – allowBackgroundLocationUpdates to be set on CLLocationManager. Also you have to include location UIBackgroundModes in the project options. In order for the Location Sensor to work in the background you have to always pass True to requestWhenInUseAuthorization method. In order to make this change, you have to modify the implementation sections of the units: iOSapi.CoreLocation and System.iOS.Sensors and completely redeclare CLLocationManager here, and add the new methods for the property.
Here is some sample code:
type // Reintroducing the entire CLLocationManager and CLLocationManagerDelegate in order to add allowsBackgroundLocationUpdates property CLLocationManager = interface(NSObject) ['{B162A514-4334-48B8-B31A-32926B758340}'] // New GUID function activityType : CLActivityType; cdecl; procedure allowDeferredLocationUpdatesUntilTraveled(distance: CLLocationDistance; timeout: NSTimeInterval); cdecl; function allowsBackgroundLocationUpdates: Boolean; cdecl; // New method for allowsBackgroundLocationUpdates property function delegate: Pointer; cdecl; // snip procedure setActivityType(activityType: CLActivityType); cdecl; procedure setAllowsBackgroundLocationUpdates(allowsBackgroundLocationUpdates: Boolean); cdecl; // New method for allowsBackgroundLocationUpdates property procedure setDelegate(delegate: Pointer); cdecl; // snip end; TCLLocationManager = class(TOCGenericImport<CLLocationManagerClass, CLLocationManager>) end; CLLocationManagerDelegate = interface(IObjectiveC) ['{113A227F-AD2D-4983-83C3-C5158F394257}'] // New GUID procedure locationManager(manager: CLLocationManager; didFailWithError: NSError); overload; cdecl; // snip [MethodName('locationManager:didFinishDeferredUpdatesWithError:')] procedure locationManagerDidFinishDeferredUpdatesWithError(manager: CLLocationManager; error: NSError); cdecl; end;
If you want to always set the authorization for allowsBackgroundLocationUpdates not only when the sensor is active, you have to modify TiOSLocationSensor.DoStart method.
if TOSVersion.Check(9) and (FLocater <> nil) then begin {$IF Defined(BACKGROUNDUPDATES) and Defined(CPUARM64)} // for some reason, this function crashes in 32-bit FLocater.setAllowsBackgroundLocationUpdates(True); {$ENDIF} end; // check authorization if Authorized = TAuthorizationType.atUnauthorized then SensorError(SLocationServiceUnauthorized); // snip
Mirror: Download the background location sensor demo for Delphi on IOS.