From 29c808b56a463f722b821011fcd75540e92662bf Mon Sep 17 00:00:00 2001 From: Alex Zolotarev Date: Sun, 4 Dec 2011 23:03:43 +0300 Subject: [PATCH] [ios] Added Search Banner check on entering foreground --- defines.hpp | 2 + iphone/Common/GetActiveConnectionType.h | 34 +------- iphone/Common/GetActiveConnectionType.mm | 34 ++++++++ iphone/Maps/Classes/MapViewController.h | 3 + iphone/Maps/Classes/MapViewController.mm | 10 ++- iphone/Maps/Classes/SearchBannerChecker.h | 10 +++ iphone/Maps/Classes/SearchBannerChecker.mm | 97 ++++++++++++++++++++++ iphone/Maps/Maps.xcodeproj/project.pbxproj | 14 +++- 8 files changed, 166 insertions(+), 38 deletions(-) create mode 100644 iphone/Common/GetActiveConnectionType.mm create mode 100644 iphone/Maps/Classes/SearchBannerChecker.h create mode 100644 iphone/Maps/Classes/SearchBannerChecker.mm diff --git a/defines.hpp b/defines.hpp index c5659ab818..bba9a97089 100644 --- a/defines.hpp +++ b/defines.hpp @@ -35,3 +35,5 @@ #define URL_SERVERS_LIST "http://metaserver-dev.mapswithme.com/server_data/active_servers" #define DEFAULT_SERVERS_JSON "[\"http://svobodu404popugajam.mapswithme.com:34568/maps/\",\"http://svobodu404popugajam.mapswithme.com:34568/maps/\"]" #endif + +#define REDBUTTON_SERVER_URL "http://redbutton.mapswithme.com/enable_search_banner" diff --git a/iphone/Common/GetActiveConnectionType.h b/iphone/Common/GetActiveConnectionType.h index a93c054771..41251a618d 100644 --- a/iphone/Common/GetActiveConnectionType.h +++ b/iphone/Common/GetActiveConnectionType.h @@ -1,7 +1,4 @@ -#import - -#include -#include +#pragma once enum TActiveConnectionType { @@ -10,31 +7,4 @@ enum TActiveConnectionType EConnectedBy3G }; -TActiveConnectionType GetActiveConnectionType() -{ - struct sockaddr_in zeroAddress; - bzero(&zeroAddress, sizeof(zeroAddress)); - zeroAddress.sin_len = sizeof(zeroAddress); - zeroAddress.sin_family = AF_INET; - - // Recover reachability flags - SCNetworkReachabilityRef defaultRoute = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress); - SCNetworkReachabilityFlags flags; - BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRoute, &flags); - CFRelease(defaultRoute); - if (!didRetrieveFlags) - return ENotConnected; - - BOOL isReachable = flags & kSCNetworkFlagsReachable; - BOOL isWifi = !(flags & kSCNetworkReachabilityFlagsIsWWAN); - BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired; - BOOL isConnected = isReachable && !needsConnection; - if (isConnected) - { - if (isWifi) - return EConnectedByWiFi; - else - return EConnectedBy3G; - } - return ENotConnected; -} +TActiveConnectionType GetActiveConnectionType(); diff --git a/iphone/Common/GetActiveConnectionType.mm b/iphone/Common/GetActiveConnectionType.mm new file mode 100644 index 0000000000..ee9f91b242 --- /dev/null +++ b/iphone/Common/GetActiveConnectionType.mm @@ -0,0 +1,34 @@ +#import "GetActiveConnectionType.h" +#import + +#include +#include + +TActiveConnectionType GetActiveConnectionType() +{ + struct sockaddr_in zeroAddress; + bzero(&zeroAddress, sizeof(zeroAddress)); + zeroAddress.sin_len = sizeof(zeroAddress); + zeroAddress.sin_family = AF_INET; + + // Recover reachability flags + SCNetworkReachabilityRef defaultRoute = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress); + SCNetworkReachabilityFlags flags; + Boolean didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRoute, &flags); + CFRelease(defaultRoute); + if (!didRetrieveFlags) + return ENotConnected; + + Boolean isReachable = flags & kSCNetworkFlagsReachable; + Boolean isWifi = !(flags & kSCNetworkReachabilityFlagsIsWWAN); + Boolean needsConnection = flags & kSCNetworkFlagsConnectionRequired; + Boolean isConnected = isReachable && !needsConnection; + if (isConnected) + { + if (isWifi) + return EConnectedByWiFi; + else + return EConnectedBy3G; + } + return ENotConnected; +} diff --git a/iphone/Maps/Classes/MapViewController.h b/iphone/Maps/Classes/MapViewController.h index 09083542c1..94b9a4d6ce 100644 --- a/iphone/Maps/Classes/MapViewController.h +++ b/iphone/Maps/Classes/MapViewController.h @@ -4,6 +4,8 @@ #include "../../geometry/point2d.hpp" #include "../../geometry/rect2d.hpp" +@class SearchBannerChecker; + @interface MapViewController : UIViewController { enum Action @@ -20,6 +22,7 @@ m2::PointD m_Pt1, m_Pt2; NSTimer * m_iconTimer; + SearchBannerChecker * m_searchBannerChecker; } - (void) ZoomToRect: (m2::RectD const &) rect; diff --git a/iphone/Maps/Classes/MapViewController.mm b/iphone/Maps/Classes/MapViewController.mm index 69683f09ac..5baebb482b 100644 --- a/iphone/Maps/Classes/MapViewController.mm +++ b/iphone/Maps/Classes/MapViewController.mm @@ -2,6 +2,7 @@ #import "SearchVC.h" #import "MapsAppDelegate.h" #import "EAGLView.h" +#import "SearchBannerChecker.h" #import "../Settings/SettingsManager.h" #include "RenderContext.hpp" @@ -103,6 +104,7 @@ Framework * m_framework = NULL; - (void) dealloc { + [m_searchBannerChecker release]; delete m_framework; [super dealloc]; } @@ -111,6 +113,8 @@ Framework * m_framework = NULL; { if ((self = [super initWithCoder:coder])) { + m_searchBannerChecker = [[SearchBannerChecker alloc] init]; + // cyclic dependence, @TODO refactor. // Here we're creating view and window handle in it, and later we should pass framework to the view EAGLView * v = (EAGLView *)self.view; @@ -318,14 +322,12 @@ NSInteger compareAddress(id l, id r, void * context) m_framework->EnterForeground(); if (self.isViewLoaded && self.view.window) [self Invalidate]; // only invalidate when map is displayed on the screen + // Perform redbutton check + [m_searchBannerChecker checkForBannerAndEnableButton:m_myPositionButton]; } - (void)viewWillAppear:(BOOL)animated { - // needed to correctly handle startup landscape orientation - // and orientation changes when mapVC is not visible -// [self.view layoutSubviews]; - [self Invalidate]; [self.navigationController setNavigationBarHidden:YES animated:YES]; [super viewWillAppear:animated]; diff --git a/iphone/Maps/Classes/SearchBannerChecker.h b/iphone/Maps/Classes/SearchBannerChecker.h new file mode 100644 index 0000000000..5d26ad926d --- /dev/null +++ b/iphone/Maps/Classes/SearchBannerChecker.h @@ -0,0 +1,10 @@ +#import + +#define SETTINGS_REDBUTTON_URL_KEY "RedbuttonUrl" + +@interface SearchBannerChecker : NSObject +{ + id m_searchButton; +} +-(void) checkForBannerAndEnableButton:(id)searchButton; +@end \ No newline at end of file diff --git a/iphone/Maps/Classes/SearchBannerChecker.mm b/iphone/Maps/Classes/SearchBannerChecker.mm new file mode 100644 index 0000000000..b308c8d347 --- /dev/null +++ b/iphone/Maps/Classes/SearchBannerChecker.mm @@ -0,0 +1,97 @@ +#import +#import "SearchBannerChecker.h" +#import "../../Common/GetActiveConnectionType.h" + +#include "../../../defines.hpp" + +#include "../../../platform/settings.hpp" +#include "../../../platform/http_request.hpp" + +#include "../../../base/string_utils.cpp" + +#include "../../../std/bind.hpp" +#include "../../../std/string.hpp" + +#define SETTINGS_REDBUTTON_LAST_CHECK_TIME "RedbuttonLastCheck" +// at least 2 hours between next request to the server +#ifndef DEBUG + #define MIN_SECONDS_ELAPSED_FOR_NEXT_CHECK 2*60*60 +#else + #define MIN_SECONDS_ELAPSED_FOR_NEXT_CHECK 10 +#endif + +// Return true if time passed from the last check is long enough +static bool ShouldCheckAgain() +{ + string strSecondsFrom1970; + if (!Settings::Get(SETTINGS_REDBUTTON_LAST_CHECK_TIME, strSecondsFrom1970)) + return true; + + uint64_t secondsLastCheck; + if (!strings::to_uint64(strSecondsFrom1970, secondsLastCheck)) + return true; + + uint64_t const secondsNow = (uint64_t)[[NSDate date] timeIntervalSince1970]; + + if (secondsNow - secondsLastCheck > MIN_SECONDS_ELAPSED_FOR_NEXT_CHECK) + return true; + + return false; +} + +@implementation SearchBannerChecker + +-(void) onRedbuttonServerReply:(downloader::HttpRequest &) r +{ + if (r.Status() == downloader::HttpRequest::ECompleted + && r.Data().find("http") == 0) + { + // Redbutton is activated!!! + // 1. Always enable search button + // 2. Search button click displays banner + // 3. Stop all future requests + Settings::Set(SETTINGS_REDBUTTON_URL_KEY, r.Data()); + UIButton * searchButton = (UIButton *)m_searchButton; + if (searchButton.hidden == YES) + { + searchButton.hidden = NO; + // Display banner + } + } + + delete &r; + // Save timestamp of the last check + uint64_t const secondsNow = (uint64_t)[[NSDate date] timeIntervalSince1970]; + Settings::Set(SETTINGS_REDBUTTON_LAST_CHECK_TIME, strings::to_string(secondsNow)); +} + +-(void) checkForBannerAndEnableButton:(id)searchButton +{ + m_searchButton = searchButton; + + // Check if we alredy should display the button + string bannerUrl; + if (Settings::Get(SETTINGS_REDBUTTON_URL_KEY, bannerUrl) + && bannerUrl.find("http") == 0) + { + // Redbutton is activated. Enable Search button in the UI + UIButton * button = (UIButton *)searchButton; + button.hidden = NO; + } + else // Redbutton still is not activated. + { + // Check last timestamp to avoid often checks + // and check if WiFi connection is active + if (ShouldCheckAgain() && GetActiveConnectionType() == EConnectedByWiFi) + { + // Send request to the server + // tricky boost::bind for objC class methods + typedef void (*OnResultFuncT)(id, SEL, downloader::HttpRequest &); + SEL onResultSel = @selector(onRedbuttonServerReply:); + OnResultFuncT onResultImpl = (OnResultFuncT)[self methodForSelector:onResultSel]; + downloader::HttpRequest::Get(REDBUTTON_SERVER_URL, bind(onResultImpl, self, onResultSel, _1)); + } + } +} + +@end diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index 322d4edc39..392c537038 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -58,6 +58,8 @@ FA0660031286168700FEA989 /* Default-Portrait.png in Resources */ = {isa = PBXBuildFile; fileRef = FA0660011286168700FEA989 /* Default-Portrait.png */; }; FA0660041286168700FEA989 /* Default-Landscape.png in Resources */ = {isa = PBXBuildFile; fileRef = FA0660021286168700FEA989 /* Default-Landscape.png */; }; FA09E01113F71F6C007E69CA /* SearchVC.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA09E01013F71F6C007E69CA /* SearchVC.mm */; }; + FA0B7E611487736200CAB3F2 /* SearchBannerChecker.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7E601487736200CAB3F2 /* SearchBannerChecker.mm */; }; + FA0B7E631487747B00CAB3F2 /* GetActiveConnectionType.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7E621487747B00CAB3F2 /* GetActiveConnectionType.mm */; }; FA0E845E138554CF008CEABB /* languages.txt in Resources */ = {isa = PBXBuildFile; fileRef = FA0E845D138554CF008CEABB /* languages.txt */; }; FA1FB8A1147E8CA50052848B /* downloader-highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = FA1FB89B147E8CA50052848B /* downloader-highlighted.png */; }; FA1FB8A2147E8CA50052848B /* downloader-highlighted@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FA1FB89C147E8CA50052848B /* downloader-highlighted@2x.png */; }; @@ -613,7 +615,7 @@ 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 1D3623240D0F684500981E51 /* MapsAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapsAppDelegate.h; sourceTree = ""; }; 1D3623250D0F684500981E51 /* MapsAppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = MapsAppDelegate.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - 1D6058910D05DD3D006BFB54 /* MapsWithMe.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; name = MapsWithMe.app; path = "MapsWithMe Debug.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1D6058910D05DD3D006BFB54 /* MapsWithMe.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MapsWithMe.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 288765070DF74369002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 28A0AB4B0D9B1048005BE974 /* Maps_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = Maps_Prefix.pch; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; @@ -670,6 +672,9 @@ FA0660021286168700FEA989 /* Default-Landscape.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Landscape.png"; sourceTree = SOURCE_ROOT; }; FA09E00F13F71F6C007E69CA /* SearchVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SearchVC.h; sourceTree = ""; }; FA09E01013F71F6C007E69CA /* SearchVC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SearchVC.mm; sourceTree = ""; }; + FA0B7E5F1487736200CAB3F2 /* SearchBannerChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SearchBannerChecker.h; sourceTree = ""; }; + FA0B7E601487736200CAB3F2 /* SearchBannerChecker.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SearchBannerChecker.mm; sourceTree = ""; }; + FA0B7E621487747B00CAB3F2 /* GetActiveConnectionType.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GetActiveConnectionType.mm; sourceTree = ""; }; FA0E845D138554CF008CEABB /* languages.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = languages.txt; path = ../../data/languages.txt; sourceTree = SOURCE_ROOT; }; FA1FB89B147E8CA50052848B /* downloader-highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "downloader-highlighted.png"; sourceTree = ""; }; FA1FB89C147E8CA50052848B /* downloader-highlighted@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "downloader-highlighted@2x.png"; sourceTree = ""; }; @@ -1281,6 +1286,8 @@ 1D3623250D0F684500981E51 /* MapsAppDelegate.mm */, 46F8A2EB10EB63040045521A /* MapViewController.h */, EED10A4411F78D120095FAD4 /* MapViewController.mm */, + FA0B7E5F1487736200CAB3F2 /* SearchBannerChecker.h */, + FA0B7E601487736200CAB3F2 /* SearchBannerChecker.mm */, ); path = Classes; sourceTree = ""; @@ -1438,11 +1445,12 @@ FA34BEC71338D6DB00FFB2A7 /* Common */ = { isa = PBXGroup; children = ( + FAAE8D5D1338FF8B003ECAD5 /* GetActiveConnectionType.h */, + FA0B7E621487747B00CAB3F2 /* GetActiveConnectionType.mm */, FAFCB63413366E78001A5C59 /* WebViewController.h */, FAFCB63513366E78001A5C59 /* WebViewController.mm */, FA34BEC81338D72F00FFB2A7 /* CustomAlertView.mm */, FA34BEC91338D72F00FFB2A7 /* CustomAlertView.h */, - FAAE8D5D1338FF8B003ECAD5 /* GetActiveConnectionType.h */, FAA4B13E13EC1C8C00BCAB63 /* DiskFreeSpace.h */, ); name = Common; @@ -2628,6 +2636,8 @@ FABF223E13FAA97A003D4D49 /* CompassView.mm in Sources */, FA29FDAA141E77F8004ADF66 /* Preferences.mm in Sources */, FAA5C2A2144F135F005337F6 /* LocationManager.mm in Sources */, + FA0B7E611487736200CAB3F2 /* SearchBannerChecker.mm in Sources */, + FA0B7E631487747B00CAB3F2 /* GetActiveConnectionType.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };