Add installationIDs to crash reports, so the amount of affected users of a crash can be determined

Uses iOS 6 ASIdentifierManager class or identifierForVendor if the class is not available. Fallback on iOS 5 is to use app path UUID which is generated by iOS when installing the app

Conflicts:
	Classes/BITCrashManager.m
	Classes/BITHockeyHelper.h
	Classes/BITHockeyHelper.m
This commit is contained in:
Andreas Linde 2012-12-06 17:56:35 +01:00
parent f673a014d6
commit eea38c3c8a
3 changed files with 46 additions and 5 deletions

View File

@ -33,6 +33,7 @@
#import <UIKit/UIKit.h>
#import "HockeySDK.h"
#import "HockeySDKPrivate.h"
#import "BITHockeyHelper.h"
#import "BITCrashManagerPrivate.h"
#import "BITCrashReportTextFormatter.h"
@ -64,7 +65,6 @@
@synthesize fileManager = _fileManager;
- (id)initWithAppIdentifier:(NSString *)appIdentifier {
if ((self = [super init])) {
_updateURL = BITHOCKEYSDK_URL;
@ -398,9 +398,7 @@
[self.delegate crashManagerWillShowSubmitCrashReportAlert:self];
}
NSString *appName = [[[NSBundle mainBundle] localizedInfoDictionary] objectForKey:@"CFBundleDisplayName"];
if (!appName)
appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"] ?: BITHockeyLocalizedString(@"HockeyAppNamePlaceholder");
NSString *appName = bit_appName(BITHockeyLocalizedString(@"HockeyAppNamePlaceholder"));
NSString *alertDescription = [NSString stringWithFormat:BITHockeyLocalizedString(@"CrashDataFoundAnonymousDescription"), appName];
// the crash report is not anynomous any more if username or useremail are not nil
@ -546,6 +544,7 @@
NSString *useremail = @"";
NSString *applicationLog = @"";
NSString *description = @"";
NSString *installString = bit_appAnonID() ?: @"";
NSString *errorString = nil;
NSPropertyListFormat format;
@ -569,7 +568,7 @@
description = [NSString stringWithFormat:@"%@", applicationLog];
}
[crashes appendFormat:@"<crash><applicationname>%s</applicationname><uuids>%@</uuids><bundleidentifier>%@</bundleidentifier><systemversion>%@</systemversion><platform>%@</platform><senderversion>%@</senderversion><version>%@</version><uuid>%@</uuid><log><![CDATA[%@]]></log><userid>%@</userid><contact>%@</contact><description><![CDATA[%@]]></description></crash>",
[crashes appendFormat:@"<crash><applicationname>%s</applicationname><uuids>%@</uuids><bundleidentifier>%@</bundleidentifier><systemversion>%@</systemversion><platform>%@</platform><senderversion>%@</senderversion><version>%@</version><uuid>%@</uuid><log><![CDATA[%@]]></log><username>%@</username><contact>%@</contact><installstring>%@</installstring><description><![CDATA[%@]]></description></crash>",
[[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleExecutable"] UTF8String],
[self extractAppUUIDs:report],
report.applicationInfo.applicationIdentifier,
@ -581,6 +580,7 @@
[crashLogString stringByReplacingOccurrencesOfString:@"]]>" withString:@"]]" @"]]><![CDATA[" @">" options:NSLiteralSearch range:NSMakeRange(0,crashLogString.length)],
username,
useremail,
installString,
[description stringByReplacingOccurrencesOfString:@"]]>" withString:@"]]" @"]]><![CDATA[" @">" options:NSLiteralSearch range:NSMakeRange(0,description.length)]];

View File

@ -33,6 +33,9 @@
NSString *bit_URLEncodedString(NSString *inputString);
NSString *bit_URLDecodedString(NSString *inputString);
NSComparisonResult bit_versionCompare(NSString *stringA, NSString *stringB);
NSString *bit_encodeAppIdentifier(NSString *inputString);
NSString *bit_appName(NSString *placeHolderString);
NSString *bit_appAnonID(void);
/* UIImage helpers */
UIImage *bit_roundedCornerImage(UIImage *inputImage, NSInteger cornerSize, NSInteger borderSize);

View File

@ -74,6 +74,44 @@ NSComparisonResult bit_versionCompare(NSString *stringA, NSString *stringB) {
return result;
}
NSString *bit_encodeAppIdentifier(NSString *inputString) {
return (inputString ? bit_URLEncodedString(inputString) : bit_URLEncodedString([[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"]));
}
NSString *bit_appName(NSString *placeHolderString) {
NSString *appName = [[[NSBundle mainBundle] localizedInfoDictionary] objectForKey:@"CFBundleDisplayName"];
if (!appName)
appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"] ?: placeHolderString;
return appName;
}
NSString *bit_appAnonID(void) {
// try to new iOS6 identifierForAdvertising
Class advertisingClass = NSClassFromString(@"ASIdentifierManager");
if (advertisingClass) {
id adInstance = [advertisingClass performSelector:NSSelectorFromString(@"sharedManager")];
SEL adidSelector = NSSelectorFromString(@"advertisingIdentifier");
return [[adInstance performSelector:adidSelector] performSelector:NSSelectorFromString(@"UUIDString")];
}
// try to new iOS6 identifierForVendor, in case ASIdentifierManager is not linked
SEL vendoridSelector = NSSelectorFromString(@"identifierForVendor");
if ([[UIDevice currentDevice] respondsToSelector:vendoridSelector]) {
return [[[UIDevice currentDevice] performSelector:vendoridSelector] performSelector:NSSelectorFromString(@"UUIDString")];
}
// use app bundle path
NSArray *pathComponents = [[[NSBundle mainBundle] bundlePath] pathComponents];
if ([pathComponents count] > 1) {
return [pathComponents objectAtIndex:(pathComponents.count - 2)];
}
return nil;
}
#pragma mark UIImage private helpers