From 0e905a011baae58a4efef29ccec1fd9c691e0db4 Mon Sep 17 00:00:00 2001 From: Thomas Dohmke Date: Sat, 3 Dec 2011 15:24:04 +0100 Subject: [PATCH] Merged changes from HockeyKit repo. --- Classes/BWApp.m | 2 +- Classes/BWGlobal.h | 2 + Classes/BWHockeyManager.h | 4 + Classes/BWHockeyManager.m | 149 +++++++++++++++++++---------- Classes/BWHockeyViewController.m | 6 +- Classes/NSString+HockeyAdditions.h | 2 + Classes/NSString+HockeyAdditions.m | 25 +++++ 7 files changed, 138 insertions(+), 52 deletions(-) mode change 100644 => 100755 Classes/NSString+HockeyAdditions.h mode change 100644 => 100755 Classes/NSString+HockeyAdditions.m diff --git a/Classes/BWApp.m b/Classes/BWApp.m index 598a370d7c..49d5db38f3 100644 --- a/Classes/BWApp.m +++ b/Classes/BWApp.m @@ -151,7 +151,7 @@ } - (NSString *)sizeInMB { - if ([[size_ class] isKindOfClass: [NSNumber class]] && [size_ doubleValue] > 0) { + if ([size_ isKindOfClass: [NSNumber class]] && [size_ doubleValue] > 0) { double appSizeInMB = [size_ doubleValue]/(1024*1024); NSString *appSizeString = [NSString stringWithFormat:@"%.1f MB", appSizeInMB]; return appSizeString; diff --git a/Classes/BWGlobal.h b/Classes/BWGlobal.h index 5316ff352c..f04bc5a4ea 100644 --- a/Classes/BWGlobal.h +++ b/Classes/BWGlobal.h @@ -57,6 +57,8 @@ NSString *BWmd5(NSString *str); // compatibility helper +#define BW_NATIVE_JSON_AVAILABLE __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000 + #ifndef kCFCoreFoundationVersionNumber_iPhoneOS_3_2 #define kCFCoreFoundationVersionNumber_iPhoneOS_3_2 478.61 #endif diff --git a/Classes/BWHockeyManager.h b/Classes/BWHockeyManager.h index ce76e4b31c..41c3f56cbe 100644 --- a/Classes/BWHockeyManager.h +++ b/Classes/BWHockeyManager.h @@ -70,6 +70,8 @@ typedef enum { BOOL updateAlertShowing_; BOOL lastCheckFailed_; + BOOL isAppStoreEnvironment_; + NSURLConnection *urlConnection_; NSDate *lastCheck_; NSDate *usageStartTimestamp_; @@ -171,6 +173,8 @@ typedef enum { /////////////////////////////////////////////////////////////////////////////////////////////////// +@property (nonatomic, readonly) BOOL isAppStoreEnvironment; + // is an update available? - (BOOL)isUpdateAvailable; diff --git a/Classes/BWHockeyManager.m b/Classes/BWHockeyManager.m index 0f3a33abb3..fb4aca601d 100644 --- a/Classes/BWHockeyManager.m +++ b/Classes/BWHockeyManager.m @@ -49,7 +49,6 @@ - (void)startUsage; - (void)stopUsage; - (void)startManager; -- (void)wentOnline; - (void)showAuthorizationScreen:(NSString *)message image:(NSString *)image; - (BOOL)canSendUserData; - (BOOL)canSendUsageTime; @@ -110,6 +109,7 @@ static NSString *kHockeyErrorDomain = @"HockeyErrorDomain"; @synthesize requireAuthorization = requireAuthorization_; @synthesize authenticationSecret = authenticationSecret_; @synthesize authorizeView = authorizeView_; +@synthesize isAppStoreEnvironment = isAppStoreEnvironment_; /////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - @@ -271,7 +271,7 @@ static NSString *kHockeyErrorDomain = @"HockeyErrorDomain"; - (void)checkUpdateAvailable_ { // check if there is an update available if (self.compareVersionType == HockeyComparisonResultGreater) { - self.updateAvailable = ([self.app.version compare:self.currentAppVersion options:NSNumericSearch] == NSOrderedDescending); + self.updateAvailable = ([self.app.version versionCompare:self.currentAppVersion] == NSOrderedDescending); } else { self.updateAvailable = ([self.app.version compare:self.currentAppVersion] != NSOrderedSame); } @@ -361,6 +361,17 @@ static NSString *kHockeyErrorDomain = @"HockeyErrorDomain"; requireAuthorization_ = NO; authenticationSecret_= nil; loggingEnabled_ = NO; + + // check if we are really not in an app store environment + if ([[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"]) { + isAppStoreEnvironment_ = NO; + } else { + isAppStoreEnvironment_ = YES; + } + +#if TARGET_IPHONE_SIMULATOR + isAppStoreEnvironment_ = NO; +#endif // set defaults self.showDirectInstallOption = NO; @@ -392,31 +403,36 @@ static NSString *kHockeyErrorDomain = @"HockeyErrorDomain"; self.userAllowsSendUsageTime = YES; } - [self loadAppCache_]; + if (!isAppStoreEnvironment_) { - [self startUsage]; + [self loadAppCache_]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(startManager) - name:BWHockeyNetworkBecomeReachable - object:nil]; + [self startUsage]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(startManager) + name:BWHockeyNetworkBecomeReachable + object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(stopUsage) - name:UIApplicationWillTerminateNotification - object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(stopUsage) + name:UIApplicationWillTerminateNotification + object:nil]; + } } return self; } - (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self name:BWHockeyNetworkBecomeReachable object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillTerminateNotification object:nil]; + if (!isAppStoreEnvironment_) { + [[NSNotificationCenter defaultCenter] removeObserver:self name:BWHockeyNetworkBecomeReachable object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillTerminateNotification object:nil]; - BW_IF_IOS4_OR_GREATER( - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil]; - ) + BW_IF_IOS4_OR_GREATER( + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil]; + ) + } self.delegate = nil; [urlConnection_ cancel]; @@ -444,6 +460,11 @@ static NSString *kHockeyErrorDomain = @"HockeyErrorDomain"; } - (void)showUpdateView { + if (isAppStoreEnvironment_) { + BWHockeyLog(@"this should not be called from an app store build."); + return; + } + if (currentHockeyViewController_) { BWHockeyLog(@"update view already visible, aborting"); return; @@ -593,10 +614,27 @@ static NSString *kHockeyErrorDomain = @"HockeyErrorDomain"; NSError *error = nil; id feedResult = nil; +#if BW_NATIVE_JSON_AVAILABLE + feedResult = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error]; +#else + id nsjsonClass = NSClassFromString(@"NSJSONSerialization"); + SEL nsjsonSelect = NSSelectorFromString(@"JSONObjectWithData:options:error:"); SEL sbJSONSelector = NSSelectorFromString(@"JSONValue"); SEL jsonKitSelector = NSSelectorFromString(@"objectFromJSONStringWithParseOptions:error:"); + SEL yajlSelector = NSSelectorFromString(@"yajl_JSONWithOptions:error:"); - if (jsonKitSelector && [jsonString respondsToSelector:jsonKitSelector]) { + if (nsjsonClass && [nsjsonClass respondsToSelector:nsjsonSelect]) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[nsjsonClass methodSignatureForSelector:nsjsonSelect]]; + invocation.target = nsjsonClass; + invocation.selector = nsjsonSelect; + NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; + [invocation setArgument:&jsonData atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation + NSUInteger readOptions = kNilOptions; + [invocation setArgument:&readOptions atIndex:3]; + [invocation setArgument:&error atIndex:4]; + [invocation invoke]; + [invocation getReturnValue:&feedResult]; + } else if (jsonKitSelector && [jsonString respondsToSelector:jsonKitSelector]) { // first try JSONkit NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[jsonString methodSignatureForSelector:jsonKitSelector]]; invocation.target = jsonString; @@ -611,12 +649,25 @@ static NSString *kHockeyErrorDomain = @"HockeyErrorDomain"; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[jsonString methodSignatureForSelector:sbJSONSelector]]; invocation.target = jsonString; invocation.selector = sbJSONSelector; + [invocation invoke]; + [invocation getReturnValue:&feedResult]; + } else if (yajlSelector && [jsonString respondsToSelector:yajlSelector]) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[jsonString methodSignatureForSelector:yajlSelector]]; + invocation.target = jsonString; + invocation.selector = yajlSelector; + + NSUInteger yajlParserOptions = 0; + [invocation setArgument:&yajlParserOptions atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation + [invocation setArgument:&error atIndex:3]; + [invocation invoke]; [invocation getReturnValue:&feedResult]; } else { BWHockeyLog(@"Error: You need a JSON Framework in your runtime!"); [self doesNotRecognizeSelector:_cmd]; - } + } +#endif + if (error) { BWHockeyLog(@"Error while parsing response feed: %@", [error localizedDescription]); [self reportError_:error]; @@ -631,6 +682,7 @@ static NSString *kHockeyErrorDomain = @"HockeyErrorDomain"; #pragma mark RequestComments - (BOOL)shouldCheckForUpdates { + if (isAppStoreEnvironment_) return NO; BOOL checkForUpdate = NO; switch (self.updateSetting) { case HockeyUpdateCheckStartup: @@ -720,6 +772,7 @@ static NSString *kHockeyErrorDomain = @"HockeyErrorDomain"; } - (void)checkForUpdate { + if (isAppStoreEnvironment_) return; if (self.requireAuthorization) return; if (self.isUpdateAvailable && [self.app.mandatory boolValue]) { [self showCheckForUpdateAlert_]; @@ -729,6 +782,7 @@ static NSString *kHockeyErrorDomain = @"HockeyErrorDomain"; } - (void)checkForUpdateShowFeedback:(BOOL)feedback { + if (isAppStoreEnvironment_) return; if (self.isCheckInProgress) return; showFeedback_ = feedback; @@ -845,6 +899,8 @@ static NSString *kHockeyErrorDomain = @"HockeyErrorDomain"; // begin the startup process - (void)startManager { + if (isAppStoreEnvironment_) return; + if (![self appVersionIsAuthorized]) { if ([self authorizationState] == HockeyAuthorizationPending) { [self showAuthorizationScreen:BWHockeyLocalize(@"HockeyAuthorizationProgress") image:@"authorize_request.png"]; @@ -859,19 +915,6 @@ static NSString *kHockeyErrorDomain = @"HockeyErrorDomain"; } -- (void)wentOnline { - if (![self appVersionIsAuthorized]) { - if ([self authorizationState] == HockeyAuthorizationPending) { - [self checkForAuthorization]; - } - } else { - if (lastCheckFailed_) { - [self checkForUpdate]; - } - } -} - - /////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - #pragma mark NSURLRequest @@ -1011,23 +1054,27 @@ static NSString *kHockeyErrorDomain = @"HockeyErrorDomain"; } BW_IF_IOS4_OR_GREATER( - // register/deregister logic - NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; - if (!updateURL_ && anUpdateURL) { - [dnc addObserver:self selector:@selector(startUsage) name:UIApplicationDidBecomeActiveNotification object:nil]; - [dnc addObserver:self selector:@selector(stopUsage) name:UIApplicationWillResignActiveNotification object:nil]; - } else if (updateURL_ && !anUpdateURL) { - [dnc removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; - [dnc removeObserver:self name:UIApplicationWillResignActiveNotification object:nil]; - } - ) + if (!isAppStoreEnvironment_) { + // register/deregister logic + NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; + if (!updateURL_ && anUpdateURL) { + [dnc addObserver:self selector:@selector(startUsage) name:UIApplicationDidBecomeActiveNotification object:nil]; + [dnc addObserver:self selector:@selector(stopUsage) name:UIApplicationWillResignActiveNotification object:nil]; + } else if (updateURL_ && !anUpdateURL) { + [dnc removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; + [dnc removeObserver:self name:UIApplicationWillResignActiveNotification object:nil]; + } + } + ) if (updateURL_ != anUpdateURL) { [updateURL_ release]; updateURL_ = [anUpdateURL copy]; } - [self performSelector:@selector(startManager) withObject:nil afterDelay:0.0f]; + if (!isAppStoreEnvironment_) { + [self performSelector:@selector(startManager) withObject:nil afterDelay:0.0f]; + } } - (void)setAppIdentifier:(NSString *)anAppIdentifier { @@ -1043,12 +1090,14 @@ static NSString *kHockeyErrorDomain = @"HockeyErrorDomain"; if (checkForUpdateOnLaunch_ != flag) { checkForUpdateOnLaunch_ = flag; BW_IF_IOS4_OR_GREATER( - NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; - if (flag) { - [dnc addObserver:self selector:@selector(checkForUpdate) name:UIApplicationDidBecomeActiveNotification object:nil]; - } else { - [dnc removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; - } + if (!isAppStoreEnvironment_) { + NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; + if (flag) { + [dnc addObserver:self selector:@selector(checkForUpdate) name:UIApplicationDidBecomeActiveNotification object:nil]; + } else { + [dnc removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; + } + } ) } } diff --git a/Classes/BWHockeyViewController.m b/Classes/BWHockeyViewController.m index 42e5ed6e60..05f4216878 100644 --- a/Classes/BWHockeyViewController.m +++ b/Classes/BWHockeyViewController.m @@ -55,7 +55,9 @@ #pragma mark private - (void)restoreStoreButtonStateAnimated_:(BOOL)animated { - if ([self.hockeyManager isUpdateAvailable]) { + if ([self.hockeyManager isAppStoreEnvironment]) { + [self setAppStoreButtonState:AppStoreButtonStateOffline animated:animated]; + } else if ([self.hockeyManager isUpdateAvailable]) { [self setAppStoreButtonState:AppStoreButtonStateUpdate animated:animated]; } else { [self setAppStoreButtonState:AppStoreButtonStateCheck animated:animated]; @@ -390,6 +392,8 @@ } - (void)viewWillAppear:(BOOL)animated { + if ([self.hockeyManager isAppStoreEnvironment]) + self.appStoreButtonState = AppStoreButtonStateOffline; self.hockeyManager.currentHockeyViewController = self; [super viewWillAppear:animated]; statusBarStyle_ = [[UIApplication sharedApplication] statusBarStyle]; diff --git a/Classes/NSString+HockeyAdditions.h b/Classes/NSString+HockeyAdditions.h old mode 100644 new mode 100755 index d32e13d4a6..e56df48e02 --- a/Classes/NSString+HockeyAdditions.h +++ b/Classes/NSString+HockeyAdditions.h @@ -30,4 +30,6 @@ - (NSString *)bw_URLEncodedString; - (NSString *)bw_URLDecodedString; +- (NSComparisonResult)versionCompare:(NSString *)other; + @end diff --git a/Classes/NSString+HockeyAdditions.m b/Classes/NSString+HockeyAdditions.m old mode 100644 new mode 100755 index 5db3528dfe..168cd65016 --- a/Classes/NSString+HockeyAdditions.m +++ b/Classes/NSString+HockeyAdditions.m @@ -47,4 +47,29 @@ return result; } +- (NSComparisonResult)versionCompare:(NSString *)other +{ + // Extract plain version number from self + NSString *plainSelf = self; + NSRange letterRange = [plainSelf rangeOfCharacterFromSet: [NSCharacterSet letterCharacterSet]]; + if (letterRange.length) + plainSelf = [plainSelf substringToIndex: letterRange.location]; + + // Extract plain version number from other + NSString *plainOther = other; + letterRange = [plainOther rangeOfCharacterFromSet: [NSCharacterSet letterCharacterSet]]; + if (letterRange.length) + plainOther = [plainOther substringToIndex: letterRange.location]; + + // Compare plain versions + NSComparisonResult result = [plainSelf compare:plainOther options:NSNumericSearch]; + + // If plain versions are equal, compare full versions + if (result == NSOrderedSame) + result = [self compare:other options:NSNumericSearch]; + + // Done + return result; +} + @end