diff --git a/iphone/Maps/Classes/EAGLView.h b/iphone/Maps/Classes/EAGLView.h index a84c017e0e..600ce61de8 100644 --- a/iphone/Maps/Classes/EAGLView.h +++ b/iphone/Maps/Classes/EAGLView.h @@ -27,5 +27,6 @@ namespace dp - (void)deallocateNative; - (CGPoint)viewPoint2GlobalPoint:(CGPoint)pt; - (CGPoint)globalPoint2ViewPoint:(CGPoint)pt; +- (void)initialize; @end diff --git a/iphone/Maps/Classes/EAGLView.mm b/iphone/Maps/Classes/EAGLView.mm index d5e2f2278c..6534585cc2 100644 --- a/iphone/Maps/Classes/EAGLView.mm +++ b/iphone/Maps/Classes/EAGLView.mm @@ -1,5 +1,7 @@ #import "Common.h" #import "EAGLView.h" +#import "MapsAppDelegate.h" +#import "LocationManager.h" #import "MWMDirectionView.h" #import "../Platform/opengl/iosOGLContextFactory.h" @@ -58,33 +60,39 @@ 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"); - - if ((self = [super initWithCoder:coder])) - { - lastViewSize = CGRectZero; - _widgetsManager = [[MWMMapWidgets alloc] init]; - - // Setup Layer Properties - CAEAGLLayer * eaglLayer = (CAEAGLLayer *)self.layer; - - eaglLayer.opaque = YES; - eaglLayer.drawableProperties = @{kEAGLDrawablePropertyRetainedBacking : @NO, - kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8}; - - // Correct retina display support in opengl renderbuffer - self.contentScaleFactor = correctContentScale(); - - m_factory = make_unique_dp(new iosOGLContextFactory(eaglLayer)); - } + self = [super initWithCoder:coder]; + if (self && !isDaemon) + [self initialize]; NSLog(@"EAGLView initWithCoder Ended"); return self; } +- (void)initialize +{ + lastViewSize = CGRectZero; + _widgetsManager = [[MWMMapWidgets alloc] init]; + + // Setup Layer Properties + CAEAGLLayer * eaglLayer = (CAEAGLLayer *)self.layer; + + eaglLayer.opaque = YES; + eaglLayer.drawableProperties = @{kEAGLDrawablePropertyRetainedBacking : @NO, + kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8}; + + // Correct retina display support in opengl renderbuffer + self.contentScaleFactor = correctContentScale(); + + m_factory = make_unique_dp(new iosOGLContextFactory(eaglLayer)); +} + - (void)createDrapeEngineWithWidth:(int)width height:(int)height { NSLog(@"EAGLView createDrapeEngine Started"); + if (MapsAppDelegate.theApp.m_locationManager.isDaemonMode) + return; Framework::DrapeCreationParams p; p.m_surfaceWidth = width; diff --git a/iphone/Maps/Classes/MapViewController.h b/iphone/Maps/Classes/MapViewController.h index b4f1b89267..248d38ba09 100644 --- a/iphone/Maps/Classes/MapViewController.h +++ b/iphone/Maps/Classes/MapViewController.h @@ -38,6 +38,9 @@ namespace search { struct AddressInfo; } - (void)openBookmarks; - (void)refreshAd; + +- (void)initialize; + @property (nonatomic) MTRGNativeAppwallAd * appWallAd; @property (nonatomic, readonly) BOOL isAppWallAdActive; diff --git a/iphone/Maps/Classes/MapViewController.mm b/iphone/Maps/Classes/MapViewController.mm index b4afa77c9c..fc27420527 100644 --- a/iphone/Maps/Classes/MapViewController.mm +++ b/iphone/Maps/Classes/MapViewController.mm @@ -380,6 +380,8 @@ typedef NS_ENUM(NSUInteger, UserTouchesAction) - (void)onEnterForeground { + if (MapsAppDelegate.theApp.m_locationManager.isDaemonMode) + return; // Notify about entering foreground (should be called on the first launch too). GetFramework().EnterForeground(); @@ -392,6 +394,8 @@ typedef NS_ENUM(NSUInteger, UserTouchesAction) - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; + if (MapsAppDelegate.theApp.m_locationManager.isDaemonMode) + return; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; self.controlsManager.menuState = self.menuRestoreState; @@ -405,6 +409,8 @@ typedef NS_ENUM(NSUInteger, UserTouchesAction) - (void)viewDidLoad { [super viewDidLoad]; + if (MapsAppDelegate.theApp.m_locationManager.isDaemonMode) + return; self.view.clipsToBounds = YES; [MTRGManager setMyCom:YES]; self.controlsManager = [[MWMMapViewControlsManager alloc] initWithParentController:self]; @@ -480,89 +486,91 @@ typedef NS_ENUM(NSUInteger, UserTouchesAction) - (id)initWithCoder:(NSCoder *)coder { NSLog(@"MapViewController initWithCoder Started"); - - if ((self = [super initWithCoder:coder])) - { - Framework & f = GetFramework(); - - using UserMarkActivatedFnT = void (*)(id, SEL, unique_ptr); - using PlacePageDismissedFnT = void (*)(id, SEL); - - SEL userMarkSelector = @selector(onUserMarkClicked:); - UserMarkActivatedFnT userMarkFn = (UserMarkActivatedFnT)[self methodForSelector:userMarkSelector]; - f.SetUserMarkActivationListener(bind(userMarkFn, self, userMarkSelector, _1)); - m_predictor = [[LocationPredictor alloc] initWithObserver:self]; - - self.forceRoutingStateChange = ForceRoutingStateChangeNone; - self.userTouchesAction = UserTouchesActionNone; - self.menuRestoreState = MWMBottomMenuStateInactive; - - f.LoadBookmarks(); - - using TLocationStateModeFn = void (*)(id, SEL, location::EMyPositionMode); - SEL locationStateModeSelector = @selector(onLocationStateModeChanged:); - TLocationStateModeFn locationStateModeFn = (TLocationStateModeFn)[self methodForSelector:locationStateModeSelector]; - f.SetMyPositionModeListener(bind(locationStateModeFn, self, locationStateModeSelector, _1)); - - f.SetDownloadCountryListener([self, &f](storage::TIndex const & idx, int opt) - { - ActiveMapsLayout & layout = f.GetCountryTree().GetActiveMapLayout(); - if (opt == -1) - { - layout.RetryDownloading(idx); - } - else - { - LocalAndRemoteSizeT sizes = layout.GetRemoteCountrySizes(idx); - uint64_t sizeToDownload = sizes.first; - MapOptions options = static_cast(opt); - if(HasOptions(options, MapOptions::CarRouting)) - sizeToDownload += sizes.second; - - NSString * name = @(layout.GetCountryName(idx).c_str()); - Platform::EConnectionType const connection = Platform::ConnectionStatus(); - if (connection != Platform::EConnectionType::CONNECTION_NONE) - { - if (connection == Platform::EConnectionType::CONNECTION_WWAN && sizeToDownload > 50 * MB) - { - [self.alertController presentnoWiFiAlertWithName:name downloadBlock:^ - { - layout.DownloadMap(idx, static_cast(opt)); - }]; - return; - } - } - else - { - [self.alertController presentNoConnectionAlert]; - return; - } - - layout.DownloadMap(idx, static_cast(opt)); - } - }); - - f.SetRouteBuildingListener([self, &f](routing::IRouter::ResultCode code, vector const & absentCountries, vector const & absentRoutes) - { - dispatch_async(dispatch_get_main_queue(), [=] - { - [self processRoutingBuildingEvent:code countries:absentCountries routes:absentRoutes]; - }); - }); - - f.SetRouteProgressListener([self](float progress) - { - dispatch_async(dispatch_get_main_queue(), ^ - { - self.controlsManager.routeBuildingProgress = progress; - }); - }); - } + BOOL const isDaemon = MapsAppDelegate.theApp.m_locationManager.isDaemonMode; + self = [super initWithCoder:coder]; + if (self && !isDaemon) + [self initialize]; NSLog(@"MapViewController initWithCoder Ended"); return self; } +- (void)initialize +{ + Framework & f = GetFramework(); + + using UserMarkActivatedFnT = void (*)(id, SEL, unique_ptr); + using PlacePageDismissedFnT = void (*)(id, SEL); + + SEL userMarkSelector = @selector(onUserMarkClicked:); + UserMarkActivatedFnT userMarkFn = (UserMarkActivatedFnT)[self methodForSelector:userMarkSelector]; + f.SetUserMarkActivationListener(bind(userMarkFn, self, userMarkSelector, _1)); + m_predictor = [[LocationPredictor alloc] initWithObserver:self]; + self.forceRoutingStateChange = ForceRoutingStateChangeNone; + self.userTouchesAction = UserTouchesActionNone; + self.menuRestoreState = MWMBottomMenuStateInactive; + f.LoadBookmarks(); + + using TLocationStateModeFn = void (*)(id, SEL, location::EMyPositionMode); + SEL locationStateModeSelector = @selector(onLocationStateModeChanged:); + TLocationStateModeFn locationStateModeFn = (TLocationStateModeFn)[self methodForSelector:locationStateModeSelector]; + f.SetMyPositionModeListener(bind(locationStateModeFn, self, locationStateModeSelector, _1)); + + f.SetDownloadCountryListener([self, &f](storage::TIndex const & idx, int opt) + { + ActiveMapsLayout & layout = f.GetCountryTree().GetActiveMapLayout(); + if (opt == -1) + { + layout.RetryDownloading(idx); + } + else + { + LocalAndRemoteSizeT sizes = layout.GetRemoteCountrySizes(idx); + uint64_t sizeToDownload = sizes.first; + MapOptions options = static_cast(opt); + if(HasOptions(options, MapOptions::CarRouting)) + sizeToDownload += sizes.second; + + NSString * name = @(layout.GetCountryName(idx).c_str()); + Platform::EConnectionType const connection = Platform::ConnectionStatus(); + if (connection != Platform::EConnectionType::CONNECTION_NONE) + { + if (connection == Platform::EConnectionType::CONNECTION_WWAN && sizeToDownload > 50 * MB) + { + [self.alertController presentnoWiFiAlertWithName:name downloadBlock:^ + { + layout.DownloadMap(idx, static_cast(opt)); + }]; + return; + } + } + else + { + [self.alertController presentNoConnectionAlert]; + return; + } + + layout.DownloadMap(idx, static_cast(opt)); + } + }); + + f.SetRouteBuildingListener([self, &f](routing::IRouter::ResultCode code, vector const & absentCountries, vector const & absentRoutes) + { + dispatch_async(dispatch_get_main_queue(), [=] + { + [self processRoutingBuildingEvent:code countries:absentCountries routes:absentRoutes]; + }); + }); + + f.SetRouteProgressListener([self](float progress) + { + dispatch_async(dispatch_get_main_queue(), ^ + { + self.controlsManager.routeBuildingProgress = progress; + }); + }); +} + - (void)processRoutingBuildingEvent:(routing::IRouter::ResultCode)code countries:(vector const &)absentCountries routes:(vector const &)absentRoutes diff --git a/iphone/Maps/Classes/MapsAppDelegate.mm b/iphone/Maps/Classes/MapsAppDelegate.mm index f03417358f..6a9bde77ff 100644 --- a/iphone/Maps/Classes/MapsAppDelegate.mm +++ b/iphone/Maps/Classes/MapsAppDelegate.mm @@ -219,16 +219,40 @@ void InitLocalizedStrings() m_fileURL = nil; } +- (void)incrementSessionsCountAndCheckForAlert +{ + [self incrementSessionCount]; + [self showAlertIfRequired]; +} + +- (void)commonInit +{ + [HttpThread setDownloadIndicatorProtocol:self]; + [self trackWatchUser]; + InitLocalizedStrings(); + [Preferences setup]; + [self subscribeToStorage]; + [self customizeAppearance]; + + self.standbyCounter = 0; + NSTimeInterval const minimumBackgroundFetchIntervalInSeconds = 6 * 60 * 60; + [[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:minimumBackgroundFetchIntervalInSeconds]; + [self startAdServerForbiddenCheckTimer]; + Framework & f = GetFramework(); + [UIApplication sharedApplication].applicationIconBadgeNumber = f.GetCountryTree().GetActiveMapLayout().GetOutOfDateCount(); + f.InvalidateMyPosition(); +} + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Initialize all 3party engines. + BOOL returnValue = [self initStatistics:application didFinishLaunchingWithOptions:launchOptions]; if (launchOptions[UIApplicationLaunchOptionsLocationKey]) { _m_locationManager = [[LocationManager alloc] init]; [self.m_locationManager onDaemonMode]; - return YES; + return returnValue; } - // Initialize all 3party engines. - BOOL returnValue = [self initStatistics:application didFinishLaunchingWithOptions:launchOptions]; NSURL * urlUsedToLaunchMaps = launchOptions[UIApplicationLaunchOptionsURLKey]; if (urlUsedToLaunchMaps != nil) @@ -236,47 +260,20 @@ void InitLocalizedStrings() else returnValue = YES; - [HttpThread setDownloadIndicatorProtocol:self]; - - [self trackWatchUser]; - - InitLocalizedStrings(); - [self.mapViewController onEnterForeground]; - - [Preferences setup]; _m_locationManager = [[LocationManager alloc] init]; [self.m_locationManager onForeground]; - [self subscribeToStorage]; - - [self customizeAppearance]; - - self.standbyCounter = 0; - - NSTimeInterval const minimumBackgroundFetchIntervalInSeconds = 6 * 60 * 60; - [application setMinimumBackgroundFetchInterval:minimumBackgroundFetchIntervalInSeconds]; - [self registerNotifications:application launchOptions:launchOptions]; + [self commonInit]; LocalNotificationManager * notificationManager = [LocalNotificationManager sharedManager]; if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) [notificationManager processNotification:launchOptions[UIApplicationLaunchOptionsLocalNotificationKey] onLaunch:YES]; - + if ([Alohalytics isFirstSession]) - { [self firstLaunchSetup]; - } else - { - [self incrementSessionCount]; - [self showAlertIfRequired]; - } - - [self startAdServerForbiddenCheckTimer]; - - Framework & f = GetFramework(); - application.applicationIconBadgeNumber = f.GetCountryTree().GetActiveMapLayout().GetOutOfDateCount(); - f.InvalidateMyPosition(); + [self incrementSessionsCountAndCheckForAlert]; [self enableTTSForTheFirstTime]; [MWMTextToSpeech activateAudioSession]; @@ -303,12 +300,13 @@ void InitLocalizedStrings() - (void)applicationWillTerminate:(UIApplication *)application { - [self.m_locationManager beforeTerminate]; +// [self.m_locationManager beforeTerminate]; [self.mapViewController onTerminate]; } - (void)applicationDidEnterBackground:(UIApplication *)application { + [self.m_locationManager beforeTerminate]; [self.mapViewController onEnterBackground]; if (m_activeDownloadsCounter) { @@ -327,17 +325,26 @@ void InitLocalizedStrings() - (void)applicationWillEnterForeground:(UIApplication *)application { - [self.m_locationManager onForeground]; + if (self.m_locationManager.isDaemonMode) + { + [self.m_locationManager onForeground]; + [self.mapViewController initialize]; + [(EAGLView *)self.mapViewController.view initialize]; + [self.mapViewController.view setNeedsLayout]; + [self.mapViewController.view layoutIfNeeded]; + [self commonInit]; + [self incrementSessionsCountAndCheckForAlert]; + } [self.mapViewController onEnterForeground]; [MWMTextToSpeech activateAudioSession]; } - (void)applicationDidBecomeActive:(UIApplication *)application { + if (application.applicationState == UIApplicationStateBackground) + return; [self handleURLs]; - [self restoreRouteState]; - [[Statistics instance] applicationDidBecomeActive]; } @@ -625,7 +632,7 @@ void InitLocalizedStrings() NSUInteger const kMaximumSessionCountForShowingShareAlert = 50; if (sessionCount > kMaximumSessionCountForShowingShareAlert) return; - + NSDate *lastLaunchDate = [standartDefaults objectForKey:kUDLastLaunchDateKey]; NSUInteger daysFromLastLaunch = [self.class daysBetweenNowAndDate:lastLaunchDate]; if (daysFromLastLaunch > 0) @@ -649,7 +656,7 @@ void InitLocalizedStrings() { if (!Platform::IsConnected()) return; - + UIViewController * topViewController = [(UINavigationController*)self.window.rootViewController visibleViewController]; MWMAlertViewController * alert = [[MWMAlertViewController alloc] initWithViewController:topViewController]; if (isRate) @@ -672,19 +679,19 @@ void InitLocalizedStrings() NSUserDefaults const * const standartDefaults = [NSUserDefaults standardUserDefaults]; if ([standartDefaults boolForKey:kUDAlreadySharedKey]) return NO; - + NSUInteger const sessionCount = [standartDefaults integerForKey:kUDSessionsCountKey]; if (sessionCount > kMaximumSessionCountForShowingShareAlert) return NO; - + NSDate * const lastShareRequestDate = [standartDefaults objectForKey:kUDLastShareRequstDate]; NSUInteger const daysFromLastShareRequest = [MapsAppDelegate daysBetweenNowAndDate:lastShareRequestDate]; if (lastShareRequestDate != nil && daysFromLastShareRequest == 0) return NO; - + if (sessionCount == 30 || sessionCount == kMaximumSessionCountForShowingShareAlert) return YES; - + if (self.userIsNew) { if (sessionCount == 12) @@ -711,17 +718,17 @@ void InitLocalizedStrings() NSUserDefaults const * const standartDefaults = [NSUserDefaults standardUserDefaults]; if ([standartDefaults boolForKey:kUDAlreadyRatedKey]) return NO; - + NSUInteger const sessionCount = [standartDefaults integerForKey:kUDSessionsCountKey]; if (sessionCount > kMaximumSessionCountForShowingAlert) return NO; - + NSDate * const lastRateRequestDate = [standartDefaults objectForKey:kUDLastRateRequestDate]; NSUInteger const daysFromLastRateRequest = [MapsAppDelegate daysBetweenNowAndDate:lastRateRequestDate]; // Do not show more than one alert per day. if (lastRateRequestDate != nil && daysFromLastRateRequest == 0) return NO; - + if (self.userIsNew) { // It's new user. @@ -743,7 +750,7 @@ void InitLocalizedStrings() NSString *firstVersion = [[NSUserDefaults standardUserDefaults] stringForKey:kUDFirstVersionKey]; if (!firstVersion.length || firstVersionIsLessThanSecond(firstVersion, currentVersion)) return NO; - + return YES; } @@ -751,7 +758,7 @@ void InitLocalizedStrings() { if (!fromDate) return 0; - + NSDate *now = NSDate.date; NSCalendar *calendar = [NSCalendar currentCalendar]; [calendar rangeOfUnit:NSCalendarUnitDay startDate:&fromDate interval:NULL forDate:fromDate]; diff --git a/iphone/Maps/Classes/Widgets/MWMMapWidgets.mm b/iphone/Maps/Classes/Widgets/MWMMapWidgets.mm index 68ef8eec23..3fa2ddace8 100644 --- a/iphone/Maps/Classes/Widgets/MWMMapWidgets.mm +++ b/iphone/Maps/Classes/Widgets/MWMMapWidgets.mm @@ -36,6 +36,8 @@ - (void)layoutWidgets { + if (m_skin == nullptr) + return; gui::TWidgetsLayoutInfo layout; if (self.fullScreen) { diff --git a/iphone/Maps/Platform/LocationManager.h b/iphone/Maps/Platform/LocationManager.h index da31b187b4..86cb412cc7 100644 --- a/iphone/Maps/Platform/LocationManager.h +++ b/iphone/Maps/Platform/LocationManager.h @@ -23,6 +23,8 @@ BOOL m_isCourse; } +@property (nonatomic, readonly) BOOL isDaemonMode; + - (void)start:(id )observer; - (void)stop:(id )observer; - (CLLocation *)lastLocation; diff --git a/iphone/Maps/Platform/LocationManager.mm b/iphone/Maps/Platform/LocationManager.mm index 65bccf11cf..23362369de 100644 --- a/iphone/Maps/Platform/LocationManager.mm +++ b/iphone/Maps/Platform/LocationManager.mm @@ -14,12 +14,14 @@ #include "platform/settings.hpp" #include "base/math.hpp" +#include "platform/file_logging.hpp" + static CLAuthorizationStatus const kRequestAuthStatus = kCLAuthorizationStatusAuthorizedAlways; static NSString * const kAlohalyticsLocationRequestAlwaysFailed = @"$locationAlwaysRequestErrorDenied"; @interface LocationManager () -@property (nonatomic) BOOL isDaemonMode; +@property (nonatomic, readwrite) BOOL isDaemonMode; @end @@ -67,15 +69,14 @@ static NSString * const kAlohalyticsLocationRequestAlwaysFailed = @"$locationAlw - (void)onDaemonMode { self.isDaemonMode = YES; - [m_locationManager startMonitoringSignificantLocationChanges]; - m_locationManager.activityType = CLActivityTypeFitness; [m_locationManager startUpdatingLocation]; } - (void)beforeTerminate { - if (GpsTracker::Instance().IsEnabled()) - [m_locationManager startMonitoringSignificantLocationChanges]; + if (!GpsTracker::Instance().IsEnabled()) + return; + [m_locationManager startMonitoringSignificantLocationChanges]; } - (void)onForeground @@ -83,7 +84,6 @@ static NSString * const kAlohalyticsLocationRequestAlwaysFailed = @"$locationAlw self.isDaemonMode = NO; [m_locationManager stopMonitoringSignificantLocationChanges]; [m_locationManager disallowDeferredLocationUpdates]; - m_locationManager.activityType = CLActivityTypeOther; [self orientationChanged]; }