forked from organicmaps/organicmaps
Merge pull request #5226 from igrechuhin/location
[location] [ios] Removed location reporting in background.
This commit is contained in:
commit
cd0d0fdc7a
3 changed files with 101 additions and 55 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue