diff --git a/Libraries/Geolocation/Geolocation.js b/Libraries/Geolocation/Geolocation.js index 3df191692a3d87..ba9a93d2f0db6f 100644 --- a/Libraries/Geolocation/Geolocation.js +++ b/Libraries/Geolocation/Geolocation.js @@ -22,6 +22,7 @@ const LocationEventEmitter = new NativeEventEmitter(RCTLocationObserver); var subscriptions = []; var updatesEnabled = false; +var headingUpdatesEnabled = false; type GeoOptions = { timeout: number, @@ -141,6 +142,37 @@ var Geolocation = { } subscriptions = []; } + }, + + /* + * Invokes the update callback whenever the location heading changes. + */ + startUpdatingHeading: function(update: Function) { + if (headingUpdatesEnabled) { + warning('Called startUpdatingHeading while currently updating heading.'); + } + + RCTLocationObserver.startUpdatingHeading(); + headingUpdatesEnabled = true; + + LocationEventEmitter.addListener( + 'headingDidChange', + update + ); + }, + + /* + * Stops observing a location heading. + */ + stopUpdatingHeading: function() { + if (!headingUpdatesEnabled) { + warning('Called stopUpdatingHeading without currently updating heading.'); + } + + RCTLocationObserver.stopUpdatingHeading(); + headingUpdatesEnabled = false; + + LocationEventEmitter.remove('headingDidChange'); } }; diff --git a/Libraries/Geolocation/RCTLocationObserver.m b/Libraries/Geolocation/RCTLocationObserver.m index e392db3203ac02..d79630c17d3d15 100644 --- a/Libraries/Geolocation/RCTLocationObserver.m +++ b/Libraries/Geolocation/RCTLocationObserver.m @@ -12,6 +12,7 @@ #import #import #import +#import #import #import @@ -108,6 +109,7 @@ @implementation RCTLocationObserver NSDictionary *_lastLocationEvent; NSMutableArray *_pendingRequests; BOOL _observingLocation; + BOOL _observingHeading; RCTLocationOptions _observerOptions; } @@ -128,7 +130,7 @@ - (dispatch_queue_t)methodQueue - (NSArray *)supportedEvents { - return @[@"geolocationDidChange", @"geolocationError"]; + return @[@"geolocationDidChange", @"geolocationError", @"headingDidChange"]; } #pragma mark - Private API @@ -267,6 +269,27 @@ - (void)timeout:(NSTimer *)timer [self beginLocationUpdatesWithDesiredAccuracy:accuracy distanceFilter:options.distanceFilter]; } +RCT_EXPORT_METHOD(startUpdatingHeading) +{ + if (!_locationManager) { + _locationManager = [CLLocationManager new]; + _locationManager.delegate = self; + } + + [_locationManager startUpdatingHeading]; + _observingHeading = YES; +} + +RCT_EXPORT_METHOD(stopUpdatingHeading) +{ + if (!_locationManager || !_observingHeading) { + RCTLogError(@"%@.stopUpdatingHeading called without starting to update.", [self class]); + } + + [_locationManager stopUpdatingHeading]; + _observingHeading = NO; +} + #pragma mark - CLLocationManagerDelegate - (void)locationManager:(CLLocationManager *)manager @@ -283,6 +306,8 @@ - (void)locationManager:(CLLocationManager *)manager @"altitudeAccuracy": @(location.verticalAccuracy), @"heading": @(location.course), @"speed": @(location.speed), + @"course": @(location.course), + @"floorLevel": @(location.floor.level) }, @"timestamp": @([location.timestamp timeIntervalSince1970] * 1000) // in ms }; @@ -347,6 +372,25 @@ - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError * } } +- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading +{ + // Create event + NSDictionary *headingEvent = @{ + @"heading": @{ + @"magneticHeading": @(newHeading.magneticHeading), + @"trueHeading": @(newHeading.trueHeading), + @"headingAccuracy": @(newHeading.headingAccuracy), + @"x": @(newHeading.x), + @"y": @(newHeading.y) + } + }; + + // Send event + if (_observingHeading) { + [self sendEventWithName:@"headingDidChange" body:headingEvent]; + } +} + static void checkLocationConfig() { #if RCT_DEV