Merge pull request #5226 from igrechuhin/location

[location] [ios] Removed location reporting in background.
This commit is contained in:
Sergey Yershov 2017-01-19 12:28:46 +03:00 committed by GitHub
commit cd0d0fdc7a
3 changed files with 101 additions and 55 deletions

View file

@ -21,10 +21,10 @@ namespace
using TObserver = id<MWMLocationObserver>;
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<MapsAppDelegate *>(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<MapsAppDelegate *>(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

View file

@ -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

View file

@ -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];
}