From c1978759f5a25eb3371a2a5460a639347e44b75b Mon Sep 17 00:00:00 2001 From: Ilya Grechuhin Date: Wed, 18 Jan 2017 17:13:58 +0300 Subject: [PATCH] [location] [ios] Removed location reporting in background. --- .../Maps/Core/Location/MWMLocationManager.mm | 112 ++++++++++++------ .../Maps/Core/Location/MWMLocationPredictor.h | 4 +- .../Core/Location/MWMLocationPredictor.mm | 40 ++++--- 3 files changed, 101 insertions(+), 55 deletions(-) diff --git a/iphone/Maps/Core/Location/MWMLocationManager.mm b/iphone/Maps/Core/Location/MWMLocationManager.mm index 966930b25f..45f1b55080 100644 --- a/iphone/Maps/Core/Location/MWMLocationManager.mm +++ b/iphone/Maps/Core/Location/MWMLocationManager.mm @@ -21,10 +21,10 @@ namespace using TObserver = id; using TObservers = NSHashTable<__kindof TObserver>; -location::GpsInfo gpsInfoFromLocation(CLLocation * l) +location::GpsInfo gpsInfoFromLocation(CLLocation * l, location::TLocationSource source) { location::GpsInfo info; - info.m_source = location::EAppleNative; + info.m_source = source; info.m_latitude = l.coordinate.latitude; info.m_longitude = l.coordinate.longitude; @@ -57,6 +57,13 @@ location::CompassInfo compassInfoFromHeading(CLHeading * h) return info; } +typedef NS_OPTIONS(NSUInteger, MWMLocationFrameworkUpdate) { + MWMLocationFrameworkUpdateNone = 0, + MWMLocationFrameworkUpdateLocation = 1 << 0, + MWMLocationFrameworkUpdateHeading = 1 << 1, + MWMLocationFrameworkUpdateStatus = 1 << 2 +}; + enum class GeoMode { Pending, @@ -127,22 +134,6 @@ BOOL keepRunningInBackground() return NO; } -void sendInfoToFramework(dispatch_block_t block) -{ - MapsAppDelegate * delegate = - static_cast(UIApplication.sharedApplication.delegate); - if (delegate.isDrapeEngineCreated) - { - block(); - } - else - { - runAsyncOnMainQueue(^{ - sendInfoToFramework(block); - }); - } -} - NSString * const kLocationPermissionRequestedKey = @"kLocationPermissionRequestedKey"; BOOL isPermissionRequested() @@ -168,6 +159,8 @@ void setPermissionRequested() @property(nonatomic) location::TLocationError lastLocationStatus; @property(nonatomic) MWMLocationPredictor * predictor; @property(nonatomic) TObservers * observers; +@property(nonatomic) MWMLocationFrameworkUpdate frameworkUpdateMode; +@property(nonatomic) location::TLocationSource locationSource; @end @@ -265,13 +258,9 @@ void setPermissionRequested() - (void)processLocationStatus:(location::TLocationError)locationError { - // if (self.lastLocationStatus == locationError) - // return; self.lastLocationStatus = locationError; - sendInfoToFramework(^{ - if (self.lastLocationStatus != location::TLocationError::ENoError) - GetFramework().OnLocationError(self.lastLocationStatus); - }); + if (self.lastLocationStatus != location::TLocationError::ENoError) + self.frameworkUpdateMode |= MWMLocationFrameworkUpdateStatus; for (TObserver observer in self.observers) { if ([observer respondsToSelector:@selector(onLocationError:)]) @@ -282,9 +271,7 @@ void setPermissionRequested() - (void)processHeadingUpdate:(CLHeading *)headingInfo { self.lastHeadingInfo = headingInfo; - sendInfoToFramework(^{ - GetFramework().OnCompassUpdate(compassInfoFromHeading(self.lastHeadingInfo)); - }); + self.frameworkUpdateMode |= MWMLocationFrameworkUpdateHeading; location::CompassInfo const compassInfo = compassInfoFromHeading(headingInfo); for (TObserver observer in self.observers) { @@ -297,18 +284,19 @@ void setPermissionRequested() { if (!locationInfo || self.lastLocationStatus != location::TLocationError::ENoError) return; - location::GpsInfo const gpsInfo = gpsInfoFromLocation(locationInfo); - [self onLocationUpdate:gpsInfo]; - if (self.lastLocationInfo == locationInfo) - return; - self.lastLocationInfo = locationInfo; - [self.predictor reset:gpsInfo]; + [self onLocationUpdate:locationInfo source:self.locationSource]; + if (![self.lastLocationInfo isEqual:locationInfo]) + [self.predictor reset:locationInfo]; } -- (void)onLocationUpdate:(location::GpsInfo const &)gpsInfo +- (void)onLocationUpdate:(CLLocation *)locationInfo source:(location::TLocationSource)source { + location::GpsInfo const gpsInfo = gpsInfoFromLocation(locationInfo, source); GpsTracker::Instance().OnLocationUpdated(gpsInfo); - sendInfoToFramework([gpsInfo] { GetFramework().OnLocationUpdate(gpsInfo); }); + + self.lastLocationInfo = locationInfo; + self.locationSource = source; + self.frameworkUpdateMode |= MWMLocationFrameworkUpdateLocation; for (TObserver observer in self.observers) { if ([observer respondsToSelector:@selector(onLocationUpdate:)]) @@ -374,10 +362,9 @@ void setPermissionRequested() if (!_predictor) { __weak MWMLocationManager * weakSelf = self; - _predictor = [[MWMLocationPredictor alloc] - initWithOnPredictionBlock:^(location::GpsInfo const & gpsInfo) { - [weakSelf onLocationUpdate:gpsInfo]; - }]; + _predictor = [[MWMLocationPredictor alloc] initWithOnPredictionBlock:^(CLLocation * location) { + [weakSelf onLocationUpdate:location source:location::EPredictor]; + }]; } return _predictor; } @@ -460,6 +447,7 @@ void setPermissionRequested() return; self.lastLocationStatus = location::TLocationError::ENoError; + self.locationSource = location::EAppleNative; [self processLocationUpdate:location]; [[Statistics instance] logLocation:location]; } @@ -548,4 +536,50 @@ void setPermissionRequested() [[PushNotificationManager pushManager] stopLocationTracking]; } +#pragma mark - Framework + +- (void)updateFrameworkInfo +{ + auto app = UIApplication.sharedApplication; + auto delegate = static_cast(app.delegate); + if (delegate.isDrapeEngineCreated && app.applicationState == UIApplicationStateActive) + { + auto & f = GetFramework(); + if (self.frameworkUpdateMode & MWMLocationFrameworkUpdateLocation) + { + location::GpsInfo const gpsInfo = + gpsInfoFromLocation(self.lastLocationInfo, self.locationSource); + f.OnLocationUpdate(gpsInfo); + } + if (self.frameworkUpdateMode & MWMLocationFrameworkUpdateHeading) + f.OnCompassUpdate(compassInfoFromHeading(self.lastHeadingInfo)); + if (self.frameworkUpdateMode & MWMLocationFrameworkUpdateStatus) + f.OnLocationError(self.lastLocationStatus); + self.frameworkUpdateMode = MWMLocationFrameworkUpdateNone; + } + else + { + runAsyncOnMainQueue(^{ + [self updateFrameworkInfo]; + }); + } +} + +#pragma mark - Property + +- (void)setFrameworkUpdateMode:(MWMLocationFrameworkUpdate)frameworkUpdateMode +{ + if (frameworkUpdateMode != _frameworkUpdateMode && + _frameworkUpdateMode == MWMLocationFrameworkUpdateNone && + frameworkUpdateMode != MWMLocationFrameworkUpdateNone) + { + _frameworkUpdateMode = frameworkUpdateMode; + [self updateFrameworkInfo]; + } + else + { + _frameworkUpdateMode = frameworkUpdateMode; + } +} + @end diff --git a/iphone/Maps/Core/Location/MWMLocationPredictor.h b/iphone/Maps/Core/Location/MWMLocationPredictor.h index c1cd4927e9..18c9034663 100644 --- a/iphone/Maps/Core/Location/MWMLocationPredictor.h +++ b/iphone/Maps/Core/Location/MWMLocationPredictor.h @@ -2,12 +2,12 @@ #include "platform/location.hpp" -using TPredictionBlock = void (^)(location::GpsInfo const &); +using TPredictionBlock = void (^)(CLLocation *); @interface MWMLocationPredictor : NSObject - (instancetype)initWithOnPredictionBlock:(TPredictionBlock)onPredictBlock; -- (void)reset:(location::GpsInfo const &)info; +- (void)reset:(CLLocation *)info; - (void)setMyPositionMode:(MWMMyPositionMode)mode; @end diff --git a/iphone/Maps/Core/Location/MWMLocationPredictor.mm b/iphone/Maps/Core/Location/MWMLocationPredictor.mm index 5e12023c94..39159182a6 100644 --- a/iphone/Maps/Core/Location/MWMLocationPredictor.mm +++ b/iphone/Maps/Core/Location/MWMLocationPredictor.mm @@ -10,8 +10,8 @@ NSUInteger constexpr kMaxPredictionCount = 20; @interface MWMLocationPredictor () -@property (nonatomic) location::GpsInfo lastLocationInfo; -@property (nonatomic) BOOL isLastLocationInfoValid; +@property(copy, nonatomic) CLLocation * lastLocation; +@property(nonatomic) BOOL isLastLocationValid; @property (nonatomic) BOOL isLastPositionModeValid; @property (nonatomic) NSUInteger predictionsCount; @property (copy, nonatomic) TPredictionBlock onPredictionBlock; @@ -34,18 +34,19 @@ NSUInteger constexpr kMaxPredictionCount = 20; [self restart]; } -- (void)reset:(location::GpsInfo const &)locationInfo +- (void)reset:(CLLocation *)location { - self.isLastLocationInfoValid = (locationInfo.HasSpeed() && locationInfo.HasBearing()); - if (self.isLastLocationInfoValid) - self.lastLocationInfo = locationInfo; + self.isLastLocationValid = (location.speed >= 0.0 && location.course >= 0.0); + if (self.isLastLocationValid) + self.lastLocation = location; [self restart]; } - (BOOL)isActive { - return self.isLastLocationInfoValid && self.isLastPositionModeValid && self.predictionsCount < kMaxPredictionCount; + return self.isLastLocationValid && self.isLastPositionModeValid && + self.predictionsCount < kMaxPredictionCount; } - (void)restart @@ -68,13 +69,24 @@ NSUInteger constexpr kMaxPredictionCount = 20; self.predictionsCount++; - location::GpsInfo info = self.lastLocationInfo; - info.m_source = location::EPredictor; - info.m_timestamp = [NSDate date].timeIntervalSince1970; - Framework::PredictLocation(info.m_latitude, info.m_longitude, info.m_horizontalAccuracy, - info.m_bearing, info.m_speed, - info.m_timestamp - self.lastLocationInfo.m_timestamp); - self.onPredictionBlock(info); + CLLocation * l = self.lastLocation; + CLLocationCoordinate2D coordinate = l.coordinate; + CLLocationDistance altitude = l.altitude; + CLLocationAccuracy hAccuracy = l.horizontalAccuracy; + CLLocationAccuracy vAccuracy = l.verticalAccuracy; + CLLocationDirection course = l.course; + CLLocationSpeed speed = l.speed; + NSDate * timestamp = [NSDate date]; + Framework::PredictLocation(coordinate.latitude, coordinate.longitude, hAccuracy, course, speed, + timestamp.timeIntervalSince1970 - l.timestamp.timeIntervalSince1970); + CLLocation * location = [[CLLocation alloc] initWithCoordinate:coordinate + altitude:altitude + horizontalAccuracy:hAccuracy + verticalAccuracy:vAccuracy + course:course + speed:speed + timestamp:timestamp]; + self.onPredictionBlock(location); [self schedule]; }