Add support for in-app-updates without changing the version string

This commit is contained in:
Andreas Linde 2012-10-30 20:10:41 +01:00
parent 90f4b017af
commit 7e94d45acb
4 changed files with 90 additions and 14 deletions

View File

@ -38,6 +38,8 @@
@property (nonatomic, copy) NSDate *date;
@property (nonatomic, copy) NSNumber *size;
@property (nonatomic, copy) NSNumber *mandatory;
@property (nonatomic, copy) NSNumber *versionID;
@property (nonatomic, copy) NSDictionary *uuids;
- (NSString *)nameAndVersionString;
- (NSString *)versionString;
@ -46,6 +48,7 @@
- (NSString *)notesOrEmptyString;
- (void)setDateWithTimestamp:(NSTimeInterval)timestamp;
- (BOOL)isValid;
- (BOOL)hasUUID:(NSString *)uuid;
- (BOOL)isEqualToAppVersionMetaInfo:(BITAppVersionMetaInfo *)anAppVersionMetaInfo;
+ (BITAppVersionMetaInfo *)appVersionMetaInfoFromDict:(NSDictionary *)dict;

View File

@ -33,14 +33,6 @@
@implementation BITAppVersionMetaInfo
@synthesize name = _name;
@synthesize version = _version;
@synthesize shortVersion = _shortVersion;
@synthesize notes = _notes;
@synthesize date = _date;
@synthesize size = _size;
@synthesize mandatory = _mandatory;
#pragma mark - Static
@ -55,6 +47,8 @@
appVersionMetaInfo.size = [dict objectForKey:@"appsize"];
appVersionMetaInfo.notes = [dict objectForKey:@"notes"];
appVersionMetaInfo.mandatory = [dict objectForKey:@"mandatory"];
appVersionMetaInfo.versionID = [dict objectForKey:@"id"];
appVersionMetaInfo.uuids = [dict objectForKey:@"uuids"];
}
return appVersionMetaInfo;
@ -89,6 +83,8 @@
return NO;
if (self.mandatory != anAppVersionMetaInfo.mandatory && ![self.mandatory isEqualToNumber:anAppVersionMetaInfo.mandatory])
return NO;
if (![self.uuids isEqualToDictionary:anAppVersionMetaInfo.uuids])
return NO;
return YES;
}
@ -103,6 +99,8 @@
[encoder encodeObject:self.date forKey:@"date"];
[encoder encodeObject:self.size forKey:@"size"];
[encoder encodeObject:self.mandatory forKey:@"mandatory"];
[encoder encodeObject:self.versionID forKey:@"versionID"];
[encoder encodeObject:self.uuids forKey:@"uuids"];
}
- (id)initWithCoder:(NSCoder *)decoder {
@ -114,6 +112,8 @@
self.date = [decoder decodeObjectForKey:@"date"];
self.size = [decoder decodeObjectForKey:@"size"];
self.mandatory = [decoder decodeObjectForKey:@"mandatory"];
self.versionID = [decoder decodeObjectForKey:@"versionID"];
self.uuids = [decoder decodeObjectForKey:@"uuids"];
}
return self;
}
@ -172,4 +172,19 @@
return valid;
}
- (BOOL)hasUUID:(NSString *)uuid {
if (!uuid) return NO;
if (!self.uuids) return NO;
__block BOOL hasUUID = NO;
[self.uuids enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){
if (obj && [uuid compare:obj] == NSOrderedSame) {
hasUUID = YES;
*stop = YES;
}
}];
return hasUUID;
}
@end

View File

@ -52,7 +52,11 @@
BOOL _sendUsageData;
BOOL _didSetupDidBecomeActiveNotifications;
BOOL _firstStartAfterInstall;
NSNumber *_versionID;
NSString *_versionUUID;
NSString *_uuid;
}
@ -146,17 +150,17 @@
BOOL newVersion = NO;
if (![[NSUserDefaults standardUserDefaults] valueForKey:kBITUpdateUsageTimeForVersionString]) {
if (![[NSUserDefaults standardUserDefaults] valueForKey:kBITUpdateUsageTimeForUUID]) {
newVersion = YES;
} else {
if ([(NSString *)[[NSUserDefaults standardUserDefaults] valueForKey:kBITUpdateUsageTimeForVersionString] compare:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]] != NSOrderedSame) {
if ([(NSString *)[[NSUserDefaults standardUserDefaults] valueForKey:kBITUpdateUsageTimeForUUID] compare:_uuid] != NSOrderedSame) {
newVersion = YES;
}
}
if (newVersion) {
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithDouble:[[NSDate date] timeIntervalSinceReferenceDate]] forKey:kBITUpdateDateOfVersionInstallation];
[[NSUserDefaults standardUserDefaults] setObject:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"] forKey:kBITUpdateUsageTimeForVersionString];
[[NSUserDefaults standardUserDefaults] setObject:_uuid forKey:kBITUpdateUsageTimeForUUID];
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithDouble:0] forKey:kBITUpdateUsageTimeOfCurrentVersion];
[[NSUserDefaults standardUserDefaults] synchronize];
}
@ -240,10 +244,55 @@
- (void)checkUpdateAvailable {
// check if there is an update available
self.updateAvailable = (bit_versionCompare(self.newestAppVersion.version, self.currentAppVersion) == NSOrderedDescending);
NSComparisonResult comparissonResult = bit_versionCompare(self.newestAppVersion.version, self.currentAppVersion);
if (comparissonResult == NSOrderedDescending) {
self.updateAvailable = YES;
} else if (comparissonResult == NSOrderedSame) {
// compare using the binary UUID and stored version id
self.updateAvailable = NO;
if (_firstStartAfterInstall) {
if ([self.newestAppVersion hasUUID:_uuid]) {
_versionUUID = [_uuid copy];
_versionID = [self.newestAppVersion.versionID copy];
[self saveAppCache];
} else {
[self.appVersions enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (idx > 0 && [obj isKindOfClass:[BITAppVersionMetaInfo class]]) {
NSComparisonResult compareVersions = bit_versionCompare([(BITAppVersionMetaInfo *)obj version], self.currentAppVersion);
BOOL uuidFound = [(BITAppVersionMetaInfo *)obj hasUUID:_uuid];
if (uuidFound) {
_versionUUID = [_uuid copy];
_versionID = [[(BITAppVersionMetaInfo *)obj versionID] copy];
[self saveAppCache];
self.updateAvailable = YES;
}
if (compareVersions != NSOrderedSame || uuidFound) {
*stop = YES;
}
}
}];
}
} else {
if ([self.newestAppVersion.versionID compare:_versionID] == NSOrderedDescending)
self.updateAvailable = YES;
}
}
}
- (void)loadAppCache {
_firstStartAfterInstall = NO;
_versionUUID = [[NSUserDefaults standardUserDefaults] objectForKey:kBITUpdateInstalledUUID];
if (!_versionUUID) {
_firstStartAfterInstall = YES;
} else {
if ([_uuid compare:_versionUUID] != NSOrderedSame)
_firstStartAfterInstall = YES;
}
_versionID = [[NSUserDefaults standardUserDefaults] objectForKey:kBITUpdateInstalledVersionID];
_companyName = [[NSUserDefaults standardUserDefaults] objectForKey:kBITUpdateCurrentCompanyName];
NSData *savedHockeyData = [[NSUserDefaults standardUserDefaults] objectForKey:kBITUpdateArrayOfLastCheck];
@ -262,6 +311,10 @@
- (void)saveAppCache {
if (_companyName)
[[NSUserDefaults standardUserDefaults] setObject:_companyName forKey:kBITUpdateCurrentCompanyName];
if (_versionUUID)
[[NSUserDefaults standardUserDefaults] setObject:_versionUUID forKey:kBITUpdateInstalledUUID];
if (_versionID)
[[NSUserDefaults standardUserDefaults] setObject:_versionID forKey:kBITUpdateInstalledVersionID];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.appVersions];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:kBITUpdateArrayOfLastCheck];
[[NSUserDefaults standardUserDefaults] synchronize];
@ -307,10 +360,13 @@
_authenticationSecret = nil;
_lastCheck = nil;
_uuid = [[self executableUUID] copy];
_versionUUID = nil;
_versionID = nil;
_sendUsageData = YES;
_disableUpdateManager = NO;
_checkForTracker = NO;
_didSetupDidBecomeActiveNotifications = NO;
_firstStartAfterInstall = NO;
_companyName = nil;
// set defaults
@ -791,7 +847,7 @@
self.companyName = (([[json valueForKey:@"company"] isKindOfClass:[NSString class]]) ? [json valueForKey:@"company"] : nil);
if (![self isAppStoreEnvironment]) {
NSArray *feedArray = (NSArray *)([self checkForTracker] ? [json valueForKey:@"versions"] : json);
NSArray *feedArray = (NSArray *)[json valueForKey:@"versions"];
self.receivedData = nil;
self.urlConnection = nil;

View File

@ -41,12 +41,14 @@
#define BITHOCKEY_FEEDBACK_SETTINGS @"BITFeedbackManager.plist"
#define kBITUpdateInstalledUUID @"BITUpdateInstalledUUID"
#define kBITUpdateInstalledVersionID @"BITUpdateInstalledVersionID"
#define kBITUpdateCurrentCompanyName @"BITUpdateCurrentCompanyName"
#define kBITUpdateArrayOfLastCheck @"BITUpdateArrayOfLastCheck"
#define kBITUpdateDateOfLastCheck @"BITUpdateDateOfLastCheck"
#define kBITUpdateDateOfVersionInstallation @"BITUpdateDateOfVersionInstallation"
#define kBITUpdateUsageTimeOfCurrentVersion @"BITUpdateUsageTimeOfCurrentVersion"
#define kBITUpdateUsageTimeForVersionString @"BITUpdateUsageTimeForVersionString"
#define kBITUpdateUsageTimeForUUID @"BITUpdateUsageTimeForUUID"
#define kBITUpdateAuthorizedVersion @"BITUpdateAuthorizedVersion"
#define kBITUpdateAuthorizedToken @"BITUpdateAuthorizedToken"