[ios] Fixed location manager behavior when device location is disabled.

This commit is contained in:
Ilya Grechuhin 2016-03-18 19:12:56 +03:00 committed by Sergey Yershov
parent 257aacef51
commit fc653ecd92
24 changed files with 251 additions and 153 deletions

View file

@ -43,7 +43,7 @@ extern NSString * const kBookmarksChangedNotification = @"BookmarksChangedNotifi
self = [super initWithStyle:UITableViewStyleGrouped];
if (self)
{
m_locationManager = [MapsAppDelegate theApp].m_locationManager;
m_locationManager = [MapsAppDelegate theApp].locationManager;
m_categoryIndex = index;
self.title = @(GetFramework().GetBmCategory(index)->GetName().c_str());
[self calculateSections];

View file

@ -65,7 +65,7 @@
{
m_countryId = storage::kInvalidCountryId;
auto const & countryInfoGetter = f.CountryInfoGetter();
LocationManager * locationManager = [MapsAppDelegate theApp].m_locationManager;
LocationManager * locationManager = [MapsAppDelegate theApp].locationManager;
if (locationManager.lastLocationIsValid)
m_countryId = countryInfoGetter.GetRegionCountryId(locationManager.lastLocation.mercator);

View file

@ -371,7 +371,7 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell)
{
[[Statistics instance] logEvent:kStatMenu withParameters:@{kStatButton : kStatShare}];
[Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"share@"];
CLLocation * location = [MapsAppDelegate theApp].m_locationManager.lastLocation;
CLLocation * location = [MapsAppDelegate theApp].locationManager.lastLocation;
if (!location)
{
[[[UIAlertView alloc] initWithTitle:L(@"unknown_current_position")

View file

@ -76,15 +76,26 @@ extern NSString * const kAlohalyticsTapEventKey;
self.hidden = NO;
self.zoomHidden = NO;
self.menuState = MWMBottomMenuStateInactive;
LocationManager * m = MapsAppDelegate.theApp.m_locationManager;
self.routeSource = m.lastLocationIsValid ? MWMRoutePoint(m.lastLocation.mercator) :
MWMRoutePoint::MWMRoutePointZero();
self.routeDestination = MWMRoutePoint::MWMRoutePointZero();
[self configRoutePoints];
[MWMFrameworkListener addObserver:self];
return self;
}
- (void)configRoutePoints
{
if ([Alohalytics isFirstSession])
{
self.routeSource = MWMRoutePoint::MWMRoutePointZero();
}
else
{
LocationManager * m = MapsAppDelegate.theApp.locationManager;
self.routeSource = m.lastLocationIsValid ? MWMRoutePoint(m.lastLocation.mercator)
: MWMRoutePoint::MWMRoutePointZero();
}
self.routeDestination = MWMRoutePoint::MWMRoutePointZero();
}
#pragma mark - MWMFrameworkRouteBuilderObserver
- (void)processRouteBuilderEvent:(routing::IRouter::ResultCode)code
@ -353,7 +364,7 @@ extern NSString * const kAlohalyticsTapEventKey;
- (void)restoreRouteTo:(m2::PointD const &)to
{
auto & f = GetFramework();
m2::PointD const myPosition = [MapsAppDelegate theApp].m_locationManager.lastLocation.mercator;
m2::PointD const myPosition = [MapsAppDelegate theApp].locationManager.lastLocation.mercator;
f.SetRouter(f.GetBestRouter(myPosition, to));
self.routeSource = MWMRoutePoint(myPosition);
self.routeDestination = {to, @"Destination"};
@ -455,7 +466,7 @@ extern NSString * const kAlohalyticsTapEventKey;
if (!self.isPossibleToBuildRoute)
return;
LocationManager * locMgr = [MapsAppDelegate theApp].m_locationManager;
LocationManager * locMgr = [MapsAppDelegate theApp].locationManager;
if (!locMgr.lastLocationIsValid && self.routeSource.IsMyPosition())
{
MWMAlertViewController * alert =
@ -524,7 +535,7 @@ extern NSString * const kAlohalyticsTapEventKey;
if (!isSourceMyPosition)
{
MWMAlertViewController * controller = [[MWMAlertViewController alloc] initWithViewController:self.ownerController];
LocationManager * manager = MapsAppDelegate.theApp.m_locationManager;
LocationManager * manager = MapsAppDelegate.theApp.locationManager;
BOOL const needToRebuild = manager.lastLocationIsValid && !manager.isLocationModeUnknownOrPending && !isDestinationMyPosition;
m2::PointD const locationPoint = manager.lastLocation.mercator;
[controller presentPoint2PointAlertWithOkBlock:^
@ -553,7 +564,7 @@ extern NSString * const kAlohalyticsTapEventKey;
- (void)didCancelRouting
{
[[Statistics instance] logEvent:kStatEventName(kStatPointToPoint, kStatClose)];
[[MapsAppDelegate theApp].m_locationManager stop:self.navigationManager];
[[MapsAppDelegate theApp].locationManager stop:self.navigationManager];
self.navigationManager.state = MWMNavigationDashboardStateHidden;
self.disableStandbyOnRouteFollowing = NO;
[MapsAppDelegate theApp].routingPlaneMode = MWMRoutingPlaneModeNone;
@ -591,7 +602,7 @@ extern NSString * const kAlohalyticsTapEventKey;
- (void)resetRoutingPoint
{
LocationManager * m = MapsAppDelegate.theApp.m_locationManager;
LocationManager * m = MapsAppDelegate.theApp.locationManager;
self.routeSource = m.lastLocationIsValid ? MWMRoutePoint(m.lastLocation.mercator) :
MWMRoutePoint::MWMRoutePointZero();
self.routeDestination = MWMRoutePoint::MWMRoutePointZero();

View file

@ -167,7 +167,7 @@ extern NSString * const kSearchStateKey = @"SearchStateKey";
- (void)tapMyPositionFromHistory
{
MapsAppDelegate * a = MapsAppDelegate.theApp;
MWMRoutePoint const p = MWMRoutePoint::MWMRoutePoint(a.m_locationManager.lastLocation.mercator);
MWMRoutePoint const p = MWMRoutePoint::MWMRoutePoint(a.locationManager.lastLocation.mercator);
if (a.routingPlaneMode == MWMRoutingPlaneModeSearchSource)
[self.delegate buildRouteFrom:p];
else if (a.routingPlaneMode == MWMRoutingPlaneModeSearchDestination)

View file

@ -29,7 +29,7 @@ static NSString * const kMyPositionCellIdentifier = @"MWMSearchHistoryMyPosition
MWMRoutingPlaneMode const m = MapsAppDelegate.theApp.routingPlaneMode;
return (m == MWMRoutingPlaneModeSearchSource ||
m == MWMRoutingPlaneModeSearchDestination) &&
MapsAppDelegate.theApp.m_locationManager.lastLocationIsValid;
MapsAppDelegate.theApp.locationManager.lastLocationIsValid;
}
- (void)attachCell:(MWMSearchTabbedCollectionViewCell *)cell

View file

@ -58,7 +58,7 @@
{
string distanceStr;
double lat, lon;
LocationManager * locationManager = MapsAppDelegate.theApp.m_locationManager;
LocationManager * locationManager = MapsAppDelegate.theApp.locationManager;
if ([locationManager getLat:lat Lon:lon])
{
m2::PointD const mercLoc = MercatorBounds::FromLatLon(lat, lon);

View file

@ -360,9 +360,9 @@ forRowAtIndexPath:(NSIndexPath *)indexPath
return;
_watchLocationUpdates = watchLocationUpdates;
if (watchLocationUpdates)
[[MapsAppDelegate theApp].m_locationManager start:self];
[[MapsAppDelegate theApp].locationManager start:self];
else
[[MapsAppDelegate theApp].m_locationManager stop:self];
[[MapsAppDelegate theApp].locationManager stop:self];
}
@synthesize searchOnMap = _searchOnMap;

View file

@ -1,11 +1,12 @@
#import "LocationManager.h"
#import "MapsAppDelegate.h"
#import "MWMFirstLaunchController.h"
#import "MWMPageController.h"
#import "MapViewController.h"
#import "MapsAppDelegate.h"
#include "Framework.h"
@interface MWMFirstLaunchController ()
@interface MWMFirstLaunchController () <LocationObserver>
@property (weak, nonatomic) IBOutlet UIView * containerView;
@property (weak, nonatomic) IBOutlet UIImageView * image;
@ -21,15 +22,12 @@
@property (weak, nonatomic) IBOutlet NSLayoutConstraint * titleTopOffset;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint * titleImageOffset;
@property (nonatomic) BOOL locationError;
@end
namespace
{
void requestLocation()
{
GetFramework().SwitchMyPositionNextMode();
}
void requestNotifications()
{
UIApplication * app = [UIApplication sharedApplication];
@ -50,7 +48,7 @@ void requestNotifications()
void zoomToCurrentPosition()
{
LocationManager * locationManager = MapsAppDelegate.theApp.m_locationManager;
LocationManager * locationManager = MapsAppDelegate.theApp.locationManager;
if (![locationManager lastLocationIsValid])
return;
m2::PointD const centerPt = locationManager.lastLocation.mercator;
@ -58,6 +56,9 @@ void zoomToCurrentPosition()
GetFramework().SetViewportCenter(centerPt, zoom);
}
NSInteger constexpr kRequestLocationPage = 2;
NSInteger constexpr kRequestNotificationsPage = 3;
NSArray<TMWMWelcomeConfigBlock> * pagesConfigBlocks = @[
[^(MWMFirstLaunchController * controller)
{
@ -114,21 +115,68 @@ NSArray<TMWMWelcomeConfigBlock> * pagesConfigBlocks = @[
return pagesConfigBlocks;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if (self.pageIndex == kRequestLocationPage)
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(appWillEnterForeground:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (self.pageIndex == 2)
requestLocation();
else if (self.pageIndex == 3)
if (self.pageIndex == kRequestLocationPage)
[self requestLocation];
else if (self.pageIndex == kRequestNotificationsPage)
requestNotifications();
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
if (self.locationError)
[MapsAppDelegate.theApp.locationManager reset];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)requestLocation
{
MapsAppDelegate * app = MapsAppDelegate.theApp;
LocationManager * lm = app.locationManager;
[lm onForeground];
[lm start:self];
}
- (void)close
{
[self.pageController close];
zoomToCurrentPosition();
}
- (void)appWillEnterForeground:(NSNotification *)notification
{
[self requestLocation];
}
#pragma mark - LocationManager Callbacks
- (void)onLocationUpdate:(location::GpsInfo const &)info
{
}
- (void)onLocationError:(location::TLocationError)errorCode
{
if (errorCode == location::EDenied)
self.locationError = YES;
}
#pragma mark - Properties
- (void)setSize:(CGSize)size

View file

@ -1,8 +1,16 @@
#import "MWMWelcomeController.h"
@class MWMPageController;
@protocol MWMPageControllerProtocol <NSObject>
- (void)closePageController:(MWMPageController *)pageController;
@end
NS_CLASS_AVAILABLE_IOS(8_0) @interface MWMPageController : UIPageViewController
+ (instancetype)pageControllerWithParent:(UIViewController *)parentViewController;
+ (instancetype)pageControllerWithParent:(UIViewController<MWMPageControllerProtocol> *)parentViewController;
- (void)close;
- (void)nextPage;

View file

@ -6,7 +6,7 @@
@interface MWMPageController ()
@property (nonatomic) SolidTouchView * iPadBackgroundView;
@property (weak, nonatomic) UIViewController * parent;
@property (weak, nonatomic) UIViewController<MWMPageControllerProtocol> * parent;
@property (nonatomic) MWMPageControllerDataSource * pageControllerDataSource;
@property (nonatomic) MWMWelcomeController * currentController;
@ -16,7 +16,7 @@
@implementation MWMPageController
+ (instancetype)pageControllerWithParent:(UIViewController *)parentViewController
+ (instancetype)pageControllerWithParent:(UIViewController<MWMPageControllerProtocol> *)parentViewController
{
NSAssert(parentViewController != nil, @"Parent view controller can't be nil!");
MWMPageController * pageController = [[MWMWelcomeController welcomeStoryboard]
@ -33,6 +33,7 @@
[self.iPadBackgroundView removeFromSuperview];
[self.view removeFromSuperview];
[self removeFromParentViewController];
[self.parent closePageController:self];
}
- (void)nextPage

View file

@ -27,7 +27,7 @@ using namespace routing::turns;
{
_isPedestrian = YES;
string distance;
CLLocationCoordinate2D const & coordinate ([MapsAppDelegate theApp].m_locationManager.lastLocation.coordinate);
CLLocationCoordinate2D const & coordinate ([MapsAppDelegate theApp].locationManager.lastLocation.coordinate);
ms::LatLon const & directionPos = info.m_pedestrianDirectionPos;
//TODO: Not the best solution, but this solution is temporary and will be replaced in future
MeasurementUtils::FormatDistance(ms::DistanceOnEarth(coordinate.latitude, coordinate.longitude,

View file

@ -478,7 +478,7 @@ extern NSString * const kTTSStatusWasChangedNotification;
if (f.GetRouter() != routing::RouterType::Pedestrian)
return;
CLLocation * location = [MapsAppDelegate theApp].m_locationManager.lastLocation;
CLLocation * location = [MapsAppDelegate theApp].locationManager.lastLocation;
if (!location)
return;

View file

@ -60,10 +60,9 @@ double getExactDPI(double contentScaleFactor)
// The GL view is stored in the nib file. When it's unarchived it's sent -initWithCoder:
- (id)initWithCoder:(NSCoder *)coder
{
BOOL const isDaemon = MapsAppDelegate.theApp.m_locationManager.isDaemonMode;
NSLog(@"EAGLView initWithCoder Started");
self = [super initWithCoder:coder];
if (self && !isDaemon)
if (self && !MapsAppDelegate.theApp.isDaemonMode)
[self initialize];
NSLog(@"EAGLView initWithCoder Ended");
@ -91,7 +90,7 @@ double getExactDPI(double contentScaleFactor)
- (void)createDrapeEngineWithWidth:(int)width height:(int)height
{
NSLog(@"EAGLView createDrapeEngine Started");
if (MapsAppDelegate.theApp.m_locationManager.isDaemonMode)
if (MapsAppDelegate.theApp.isDaemonMode)
return;
Framework::DrapeCreationParams p;

View file

@ -200,7 +200,7 @@ enum class AttributePosition
BOOL const isMyPosition = entity.isMyPosition;
self.addressLabel.text = entity.address;
BOOL const isHeadingAvaible = [CLLocationManager headingAvailable];
BOOL const noLocation = MapsAppDelegate.theApp.m_locationManager.isLocationModeUnknownOrPending;
BOOL const noLocation = MapsAppDelegate.theApp.locationManager.isLocationModeUnknownOrPending;
self.distanceLabel.hidden = noLocation || isMyPosition;
BOOL const hideDirection = noLocation || isMyPosition || !isHeadingAvaible;
self.directionArrow.hidden = hideDirection;

View file

@ -61,14 +61,14 @@ extern NSString * const kBookmarksChangedNotification;
{
[self.delegate placePageDidClose];
[self.placePage dismiss];
[[MapsAppDelegate theApp].m_locationManager stop:self];
[[MapsAppDelegate theApp].locationManager stop:self];
GetFramework().DeactivateMapSelection(false);
self.placePage = nil;
}
- (void)showPlacePage:(place_page::Info const &)info
{
[[MapsAppDelegate theApp].m_locationManager start:self];
[[MapsAppDelegate theApp].locationManager start:self];
self.entity = [[MWMPlacePageEntity alloc] initWithInfo:info];
if (IPAD)
[self setPlacePageForiPad];
@ -113,7 +113,7 @@ extern NSString * const kBookmarksChangedNotification;
if (self.entity.isMyPosition)
{
BOOL hasSpeed;
self.entity.category = [[MapsAppDelegate theApp].m_locationManager formattedSpeedAndAltitude:hasSpeed];
self.entity.category = [[MapsAppDelegate theApp].locationManager formattedSpeedAndAltitude:hasSpeed];
}
self.placePage.parentViewHeight = self.ownerViewController.view.height;
[self.placePage configure];
@ -150,7 +150,7 @@ extern NSString * const kBookmarksChangedNotification;
if (!self.entity.isMyPosition)
return;
BOOL hasSpeed = NO;
[self.placePage updateMyPositionStatus:[[MapsAppDelegate theApp].m_locationManager
[self.placePage updateMyPositionStatus:[[MapsAppDelegate theApp].locationManager
formattedSpeedAndAltitude:hasSpeed]];
}
@ -188,7 +188,7 @@ extern NSString * const kBookmarksChangedNotification;
withParameters:@{kStatValue : kStatDestination}];
[Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"ppRoute"];
LocationManager * lm = MapsAppDelegate.theApp.m_locationManager;
LocationManager * lm = MapsAppDelegate.theApp.locationManager;
[self.delegate buildRouteFrom:lm.isLocationModeUnknownOrPending ? MWMRoutePoint::MWMRoutePointZero()
: MWMRoutePoint(lm.lastLocation.mercator)
to:{self.entity.mercator, self.placePage.basePlacePageView.titleLabel.text}];
@ -318,7 +318,7 @@ extern NSString * const kBookmarksChangedNotification;
- (NSString *)distance
{
CLLocation * location = [MapsAppDelegate theApp].m_locationManager.lastLocation;
CLLocation * location = [MapsAppDelegate theApp].locationManager.lastLocation;
// TODO(AlexZ): Do we REALLY need this check? Why this method is called if user mark/m_info is empty?
// TODO(AlexZ): Can location be checked before calling this method?
if (!location/* || !m_userMark*/)
@ -333,7 +333,7 @@ extern NSString * const kBookmarksChangedNotification;
- (void)onCompassUpdate:(location::CompassInfo const &)info
{
CLLocation * location = [MapsAppDelegate theApp].m_locationManager.lastLocation;
CLLocation * location = [MapsAppDelegate theApp].locationManager.lastLocation;
// TODO(AlexZ): Do we REALLY need this check? Why compass update is here if user mark/m_info is empty?
// TODO(AlexZ): Can location be checked before calling this method?
if (!location/* || !m_userMark*/)

View file

@ -52,7 +52,7 @@ using namespace storage;
- (void)configNearMeSection
{
LocationManager * lm = MapsAppDelegate.theApp.m_locationManager;
LocationManager * lm = MapsAppDelegate.theApp.locationManager;
if (!lm.lastLocationIsValid)
return;
auto & countryInfoGetter = GetFramework().CountryInfoGetter();

View file

@ -108,7 +108,8 @@ NSString * const kReportSegue = @"Map2ReportSegue";
@end
@interface MapViewController ()<MTRGNativeAppwallAdDelegate, MWMFrameworkRouteBuilderObserver,
MWMFrameworkDrapeObserver, MWMFrameworkStorageObserver>
MWMFrameworkDrapeObserver, MWMFrameworkStorageObserver,
MWMPageControllerProtocol>
@property (nonatomic, readwrite) MWMMapViewControlsManager * controlsManager;
@property (nonatomic) MWMBottomMenuState menuRestoreState;
@ -137,13 +138,13 @@ NSString * const kReportSegue = @"Map2ReportSegue";
case location::EDenied:
{
[self.alertController presentLocationAlert];
[[MapsAppDelegate theApp].m_locationManager stop:self];
[[MapsAppDelegate theApp].locationManager stop:self];
break;
}
case location::ENotSupported:
{
[self.alertController presentLocationServiceNotSupportedAlert];
[[MapsAppDelegate theApp].m_locationManager stop:self];
[[MapsAppDelegate theApp].locationManager stop:self];
break;
}
default:
@ -355,7 +356,7 @@ NSString * const kReportSegue = @"Map2ReportSegue";
- (void)onEnterForeground
{
if (self.isDaemon)
if (MapsAppDelegate.theApp.isDaemonMode)
return;
// Notify about entering foreground (should be called on the first launch too).
GetFramework().EnterForeground();
@ -364,7 +365,7 @@ NSString * const kReportSegue = @"Map2ReportSegue";
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (self.isDaemon)
if (MapsAppDelegate.theApp.isDaemonMode)
return;
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
@ -387,7 +388,7 @@ NSString * const kReportSegue = @"Map2ReportSegue";
- (void)viewDidLoad
{
[super viewDidLoad];
if (self.isDaemon)
if (MapsAppDelegate.theApp.isDaemonMode)
return;
self.view.clipsToBounds = YES;
[MTRGManager setMyCom:YES];
@ -422,6 +423,12 @@ NSString * const kReportSegue = @"Map2ReportSegue";
[ud synchronize];
}
- (void)closePageController:(MWMPageController *)pageController
{
if ([pageController isEqual:self.pageViewController])
self.pageViewController = nil;
}
- (void)showViralAlertIfNeeded
{
NSUserDefaults * ud = [NSUserDefaults standardUserDefaults];
@ -488,16 +495,11 @@ NSString * const kReportSegue = @"Map2ReportSegue";
[self setNeedsStatusBarAppearanceUpdate];
}
- (BOOL)isDaemon
{
return MapsAppDelegate.theApp.m_locationManager.isDaemonMode;
}
- (id)initWithCoder:(NSCoder *)coder
{
NSLog(@"MapViewController initWithCoder Started");
self = [super initWithCoder:coder];
if (self && !self.isDaemon)
if (self && !MapsAppDelegate.theApp.isDaemonMode)
[self initialize];
NSLog(@"MapViewController initWithCoder Ended");
@ -567,12 +569,13 @@ NSString * const kReportSegue = @"Map2ReportSegue";
case location::MODE_UNKNOWN_POSITION:
{
self.disableStandbyOnLocationStateMode = NO;
[[MapsAppDelegate theApp].m_locationManager stop:self];
if (![Alohalytics isFirstSession])
[[MapsAppDelegate theApp].locationManager stop:self];
break;
}
case location::MODE_PENDING_POSITION:
self.disableStandbyOnLocationStateMode = NO;
[[MapsAppDelegate theApp].m_locationManager start:self];
[[MapsAppDelegate theApp].locationManager start:self];
break;
case location::MODE_NOT_FOLLOW:
self.disableStandbyOnLocationStateMode = NO;

View file

@ -29,7 +29,8 @@ typedef NS_ENUM(NSUInteger, MWMRoutingPlaneMode)
@property (nonatomic) MWMRoutingPlaneMode routingPlaneMode;
@property (nonatomic, readonly) MapViewController * mapViewController;
@property (nonatomic, readonly) LocationManager * m_locationManager;
@property (nonatomic, readonly) LocationManager * locationManager;
@property (nonatomic, readonly) BOOL isDaemonMode;
+ (MapsAppDelegate *)theApp;

View file

@ -131,6 +131,9 @@ using namespace osm_auth_ios;
@property (weak, nonatomic) NSTimer * checkAdServerForbiddenTimer;
@property (weak, nonatomic) NSTimer * mapStyleSwitchTimer;
@property (nonatomic, readwrite) LocationManager * locationManager;
@property (nonatomic, readwrite) BOOL isDaemonMode;
@end
@implementation MapsAppDelegate
@ -336,7 +339,7 @@ using namespace osm_auth_ios;
NSAssert([MapsAppDelegate isAutoNightMode], @"Invalid auto switcher's state");
auto & f = GetFramework();
MapsAppDelegate * app = MapsAppDelegate.theApp;
CLLocation * l = app.m_locationManager.lastLocation;
CLLocation * l = app.locationManager.lastLocation;
if (!l || !f.IsRoutingActive())
return;
dispatch_async(dispatch_get_main_queue(), [&f, l, self, app]
@ -376,8 +379,7 @@ using namespace osm_auth_ios;
BOOL returnValue = [self initStatistics:application didFinishLaunchingWithOptions:launchOptions];
if (launchOptions[UIApplicationLaunchOptionsLocationKey])
{
_m_locationManager = [[LocationManager alloc] init];
[self.m_locationManager onDaemonMode];
self.isDaemonMode = YES;
return returnValue;
}
@ -393,8 +395,8 @@ using namespace osm_auth_ios;
[self determineMapStyle];
[self.mapViewController onEnterForeground];
_m_locationManager = [[LocationManager alloc] init];
[self.m_locationManager onForeground];
self.isDaemonMode = NO;
[self initPushNotificationsWithLaunchOptions:launchOptions];
[self commonInit];
@ -516,13 +518,13 @@ using namespace osm_auth_ios;
- (void)applicationWillTerminate:(UIApplication *)application
{
[self.m_locationManager beforeTerminate];
[self.locationManager beforeTerminate];
[self.mapViewController onTerminate];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[self.m_locationManager onBackground];
[self.locationManager onBackground];
[self.mapViewController onEnterBackground];
if (m_activeDownloadsCounter)
{
@ -563,9 +565,10 @@ using namespace osm_auth_ios;
- (void)applicationWillEnterForeground:(UIApplication *)application
{
if (self.m_locationManager.isDaemonMode)
BOOL const needInit = self.isDaemonMode;
self.isDaemonMode = NO;
if (needInit)
{
[self.m_locationManager onForeground];
[self.mapViewController initialize];
[(EAGLView *)self.mapViewController.view initialize];
[self.mapViewController.view setNeedsLayout];
@ -573,10 +576,6 @@ using namespace osm_auth_ios;
[self commonInit];
[self incrementSessionsCountAndCheckForAlert];
}
else
{
[self.m_locationManager onForeground];
}
[self.mapViewController onEnterForeground];
[MWMTextToSpeech activateAudioSession];
}
@ -798,6 +797,33 @@ using namespace osm_auth_ios;
return [(UINavigationController *)self.window.rootViewController viewControllers].firstObject;
}
- (LocationManager *)locationManager
{
if (!_locationManager)
_locationManager = [[LocationManager alloc] init];
return _locationManager;
}
@synthesize isDaemonMode = _isDaemonMode;
- (BOOL)isDaemonMode
{
if ([Alohalytics isFirstSession])
return NO;
return _isDaemonMode;
}
- (void)setIsDaemonMode:(BOOL)isDaemonMode
{
if (_isDaemonMode == isDaemonMode)
return;
_isDaemonMode = isDaemonMode;
if (isDaemonMode)
[self.locationManager onDaemonMode];
else
[self.locationManager onForeground];
}
#pragma mark - Route state
- (void)restoreRouteState

View file

@ -58,7 +58,7 @@ using namespace storage;
[Statistics logEvent:kStatDownloaderMigrationStarted
withParameters:@{kStatType : limited ? kStatCurrentMap : kStatAllMaps}];
auto & f = GetFramework();
LocationManager * lm = [MapsAppDelegate theApp].m_locationManager;
LocationManager * lm = [MapsAppDelegate theApp].locationManager;
ms::LatLon position{};
if (![lm getLat:position.lat Lon:position.lon])
position = MercatorBounds::ToLatLon(f.GetViewportCenter());

View file

@ -21,7 +21,7 @@ CGSize constexpr kInitialDialogSize = {200, 200};
BOOL canAutoDownload(TCountryId const & countryId)
{
LocationManager * locationManager = MapsAppDelegate.theApp.m_locationManager;
LocationManager * locationManager = MapsAppDelegate.theApp.locationManager;
if (![locationManager lastLocationIsValid])
return NO;
if (GetPlatform().ConnectionStatus() != Platform::EConnectionType::CONNECTION_WIFI)

View file

@ -15,15 +15,6 @@
@end
@interface LocationManager : NSObject <CLLocationManagerDelegate>
{
CLLocationManager * m_locationManager;
BOOL m_isStarted;
NSMutableSet * m_observers;
NSDate * m_lastLocationTime;
BOOL m_isCourse;
}
@property (nonatomic, readonly) BOOL isDaemonMode;
- (void)start:(id <LocationObserver>)observer;
- (void)stop:(id <LocationObserver>)observer;
@ -49,6 +40,8 @@
- (void)onBackground;
- (void)beforeTerminate;
- (void)reset;
@end
@interface CLLocation (Mercator)

View file

@ -21,35 +21,18 @@ static NSString * const kAlohalyticsLocationRequestAlwaysFailed = @"$locationAlw
@interface LocationManager ()
@property (nonatomic, readwrite) BOOL isDaemonMode;
@property (nonatomic) BOOL deferringUpdates;
@property (nonatomic) CLLocationManager * locationManager;
@property (nonatomic) BOOL isStarted;
@property (nonatomic) NSMutableSet * observers;
@property (nonatomic) NSDate * lastLocationTime;
@end
@implementation LocationManager
- (id)init
{
if ((self = [super init]))
{
m_locationManager = [[CLLocationManager alloc] init];
m_locationManager.delegate = self;
[UIDevice currentDevice].batteryMonitoringEnabled = YES;
[self refreshAccuracy];
if (!(isIOS7 || isIOS8))
m_locationManager.allowsBackgroundLocationUpdates = YES;
m_locationManager.pausesLocationUpdatesAutomatically = YES;
m_locationManager.headingFilter = 3.0;
m_isStarted = NO;
m_observers = [[NSMutableSet alloc] init];
m_lastLocationTime = nil;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged) name:UIDeviceOrientationDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryStateChangedNotification:) name:UIDeviceBatteryStateDidChangeNotification object:nil];
}
return self;
}
- (void)batteryStateChangedNotification:(NSNotification *)notification
{
[self refreshAccuracy];
@ -58,48 +41,44 @@ static NSString * const kAlohalyticsLocationRequestAlwaysFailed = @"$locationAlw
- (void)refreshAccuracy
{
UIDeviceBatteryState state = [UIDevice currentDevice].batteryState;
m_locationManager.desiredAccuracy = (state == UIDeviceBatteryStateCharging) ? kCLLocationAccuracyBestForNavigation : kCLLocationAccuracyBest;
self.locationManager.desiredAccuracy = (state == UIDeviceBatteryStateCharging) ? kCLLocationAccuracyBestForNavigation : kCLLocationAccuracyBest;
}
- (void)dealloc
{
m_locationManager.delegate = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
[self reset];
}
- (void)onDaemonMode
{
self.isDaemonMode = YES;
[m_locationManager stopMonitoringSignificantLocationChanges];
[m_locationManager startUpdatingLocation];
[self.locationManager stopMonitoringSignificantLocationChanges];
[self.locationManager startUpdatingLocation];
}
- (void)onBackground
{
if (!GpsTracker::Instance().IsEnabled())
[m_locationManager stopUpdatingLocation];
[self.locationManager stopUpdatingLocation];
}
- (void)beforeTerminate
{
if (!GpsTracker::Instance().IsEnabled())
return;
[m_locationManager startMonitoringSignificantLocationChanges];
[self.locationManager startMonitoringSignificantLocationChanges];
}
- (void)onForeground
{
self.isDaemonMode = NO;
[m_locationManager stopMonitoringSignificantLocationChanges];
[m_locationManager disallowDeferredLocationUpdates];
[self onDaemonMode];
[self.locationManager disallowDeferredLocationUpdates];
self.deferringUpdates = NO;
[m_locationManager startUpdatingLocation];
[self orientationChanged];
}
- (void)start:(id <LocationObserver>)observer
{
if (!m_isStarted)
if (!self.isStarted)
{
//YES if location services are enabled; NO if they are not.
if ([CLLocationManager locationServicesEnabled])
@ -110,13 +89,13 @@ static NSString * const kAlohalyticsLocationRequestAlwaysFailed = @"$locationAlw
case kCLAuthorizationStatusAuthorizedWhenInUse:
case kCLAuthorizationStatusAuthorizedAlways:
case kCLAuthorizationStatusNotDetermined:
if (kRequestAuthStatus == kCLAuthorizationStatusAuthorizedAlways && [m_locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
[m_locationManager requestAlwaysAuthorization];
[m_locationManager startUpdatingLocation];
if (kRequestAuthStatus == kCLAuthorizationStatusAuthorizedAlways && [self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
[self.locationManager requestAlwaysAuthorization];
[self.locationManager startUpdatingLocation];
if ([CLLocationManager headingAvailable])
[m_locationManager startUpdatingHeading];
m_isStarted = YES;
[m_observers addObject:observer];
[self.locationManager startUpdatingHeading];
self.isStarted = YES;
[self.observers addObject:observer];
break;
case kCLAuthorizationStatusRestricted:
case kCLAuthorizationStatusDenied:
@ -129,8 +108,8 @@ static NSString * const kAlohalyticsLocationRequestAlwaysFailed = @"$locationAlw
}
else
{
BOOL updateLocation = ![m_observers containsObject:observer];
[m_observers addObject:observer];
BOOL updateLocation = ![self.observers containsObject:observer];
[self.observers addObject:observer];
if ([self lastLocationIsValid] && updateLocation)
{
// pass last location known location when new observer is attached
@ -142,33 +121,30 @@ static NSString * const kAlohalyticsLocationRequestAlwaysFailed = @"$locationAlw
- (void)stop:(id <LocationObserver>)observer
{
[m_observers removeObject:observer];
if (m_isStarted)
[self.observers removeObject:observer];
if (self.isStarted && self.observers.count == 0)
{
if ([m_observers count] == 0)
{
// stop only if no more observers are subsribed
m_isStarted = NO;
if ([CLLocationManager headingAvailable])
[m_locationManager stopUpdatingHeading];
[m_locationManager stopUpdatingLocation];
}
// stop only if no more observers are subsribed
self.isStarted = NO;
if ([CLLocationManager headingAvailable])
[self.locationManager stopUpdatingHeading];
[self.locationManager stopUpdatingLocation];
}
}
- (CLLocation *)lastLocation
{
return m_isStarted ? m_locationManager.location : nil;
return self.isStarted ? self.locationManager.location : nil;
}
- (CLHeading *)lastHeading
{
return m_isStarted ? m_locationManager.heading : nil;
return self.isStarted ? self.locationManager.heading : nil;
}
- (void)triggerCompass
{
[self locationManager:m_locationManager didUpdateHeading:m_locationManager.heading];
[self locationManager:self.locationManager didUpdateHeading:self.locationManager.heading];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)heading
@ -181,7 +157,7 @@ static NSString * const kAlohalyticsLocationRequestAlwaysFailed = @"$locationAlw
[self processLocation:locations.lastObject];
if (!self.deferringUpdates)
return;
[m_locationManager allowDeferredLocationUpdatesUntilTraveled:300 timeout:15];
[self.locationManager allowDeferredLocationUpdatesUntilTraveled:300 timeout:15];
self.deferringUpdates = NO;
}
@ -199,12 +175,12 @@ static NSString * const kAlohalyticsLocationRequestAlwaysFailed = @"$locationAlw
return;
// Save current device time for location.
m_lastLocationTime = [NSDate date];
self.lastLocationTime = [NSDate date];
[[Statistics instance] logLocation:location];
auto const newInfo = gpsInfoFromLocation(location);
if (!self.isDaemonMode)
if (!MapsAppDelegate.theApp.isDaemonMode)
{
for (id observer in m_observers)
for (id observer in self.observers)
[observer onLocationUpdate:newInfo];
// TODO(AlexZ): Temporary, remove in the future.
}
@ -221,16 +197,16 @@ static NSString * const kAlohalyticsLocationRequestAlwaysFailed = @"$locationAlw
NSLog(@"locationManager failed with error: %ld, %@", (long)error.code, error.description);
if (error.code == kCLErrorDenied)
{
if (kRequestAuthStatus == kCLAuthorizationStatusAuthorizedAlways && [m_locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
if (kRequestAuthStatus == kCLAuthorizationStatusAuthorizedAlways && [self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
[Alohalytics logEvent:kAlohalyticsLocationRequestAlwaysFailed];
for (id observer in m_observers)
for (id observer in self.observers)
[self observer:observer onLocationError:location::EDenied];
}
}
- (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager
{
if (self.isDaemonMode)
if (MapsAppDelegate.theApp.isDaemonMode)
return NO;
bool on = false;
settings::Get("CompassCalibrationEnabled", on);
@ -340,7 +316,7 @@ static NSString * const kAlohalyticsLocationRequestAlwaysFailed = @"$locationAlw
- (bool)lastLocationIsValid
{
return (([self lastLocation] != nil) && ([m_lastLocationTime timeIntervalSinceNow] > -300.0));
return (([self lastLocation] != nil) && ([self.lastLocationTime timeIntervalSinceNow] > -300.0));
}
- (bool)isLocationModeUnknownOrPending
@ -354,7 +330,7 @@ static NSString * const kAlohalyticsLocationRequestAlwaysFailed = @"$locationAlw
- (BOOL)enabledOnMap
{
for (id observer in m_observers)
for (id observer in self.observers)
if ([observer isKindOfClass:[MapViewController class]])
return YES;
return NO;
@ -362,12 +338,12 @@ static NSString * const kAlohalyticsLocationRequestAlwaysFailed = @"$locationAlw
- (void)orientationChanged
{
m_locationManager.headingOrientation = (CLDeviceOrientation)[UIDevice currentDevice].orientation;
self.locationManager.headingOrientation = (CLDeviceOrientation)[UIDevice currentDevice].orientation;
}
- (void)notifyCompassUpdate:(location::CompassInfo const &)newInfo
{
for (id observer in m_observers)
for (id observer in self.observers)
if ([observer respondsToSelector:@selector(onCompassUpdate:)])
[observer onCompassUpdate:newInfo];
}
@ -414,6 +390,38 @@ location::CompassInfo compasInfoFromHeading(CLHeading const * h)
return info;
}
- (void)reset
{
_isStarted = NO;
_lastLocationTime = nil;
_observers = [NSMutableSet set];
_locationManager.delegate = nil;
_locationManager = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - Properties
- (CLLocationManager *)locationManager
{
if (!_locationManager)
{
[self reset];
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
[UIDevice currentDevice].batteryMonitoringEnabled = YES;
[self refreshAccuracy];
if (!(isIOS7 || isIOS8))
_locationManager.allowsBackgroundLocationUpdates = YES;
_locationManager.pausesLocationUpdatesAutomatically = YES;
_locationManager.headingFilter = 3.0;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged) name:UIDeviceOrientationDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryStateChangedNotification:) name:UIDeviceBatteryStateDidChangeNotification object:nil];
}
return _locationManager;
}
@end
@implementation CLLocation (Mercator)