Skip to content

Commit

Permalink
Merge pull request #57 from airbrake/v4.2
Browse files Browse the repository at this point in the history
V4.2 release 
Fix issue #56 UIAlertView is deprecated in iOS 8, so use UIAlertController when it's available
Fix issue #51 Add productID as parameter in ABNotifier class method
Bug fixes
  • Loading branch information
jocelynlih committed Apr 18, 2015
2 parents c41c8da + d4ac0fb commit ae556cd
Show file tree
Hide file tree
Showing 87 changed files with 694 additions and 322 deletions.
19 changes: 16 additions & 3 deletions Airbrake/notifier/ABNotice.m
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,19 @@ + (ABNotice *)noticeWithContentsOfFile:(NSString *)path {

- (void)setPOSTUserName:(NSString *)theUserName
{
if (theUserName) {
if ([theUserName length]) {
self.userName = theUserName;
}
}

- (NSString *)getPostUserName {
NSString * uname = @"Anonymous";
if ([self.userName length]) {
uname = self.userName;
}
return uname;
}

- (NSData *)JSONString {
NSData *jsonData;
NSError *jsonSerializationError = nil;
Expand All @@ -225,16 +233,21 @@ - (NSData *)JSONString {

-(NSDictionary *)getNoticeDictionary
{
NSDictionary *notice = nil;
@try {
NSMutableArray *backtrace = [[NSMutableArray alloc] initWithCapacity:0];
for (NSArray *item in self.callStack) {
if ([item count]&& [item count]>4) {
if ([item count] && [item count]>4) {
[backtrace addObject:@{@"line":@([item[1] intValue]),@"file":item[2],@"function":item[3]}];
} else {
//if we can't format the backtrace to the format matching with server API, return nil instead.
return nil;
}
}
NSDictionary *notice = @{@"notifier": @{@"name":self.executable, @"version":ABNotifierApplicationVersion(), @"url":self.executable},@"errors":@[@{@"type":self.exceptionName,@"message":self.exceptionReason, @"backtrace":backtrace}], @"context":@{@"os": ABNotifierOperatingSystemVersion(),@"language":ABNotifierPlatformName(), @"environment":self.environmentName,@"version":ABNotifierApplicationVersion(),@"userName":self.userName},@"environment":@{@"name": self.environmentName},@"params":self.environmentInfo};
notice = @{@"notifier": @{@"name":self.executable, @"version":ABNotifierApplicationVersion(), @"url":self.executable},@"errors":@[@{@"type":self.exceptionName,@"message":self.exceptionReason, @"backtrace":backtrace}], @"context":@{@"os": ABNotifierOperatingSystemVersion(),@"language":ABNotifierPlatformName(), @"environment":self.environmentName,@"version":ABNotifierApplicationVersion(),@"userName":[self getPostUserName]},@"environment":@{@"name": self.environmentName},@"params":self.environmentInfo};
} @catch (NSException *exception) {
ABLog(@"ERROR: custom notice dictionary failed : %@", [exception reason]);
}
return notice;
}

Expand Down
21 changes: 14 additions & 7 deletions Airbrake/notifier/ABNotifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
#import <SystemConfiguration/SystemConfiguration.h>
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#ifndef __IPHONE_4_0
#error This version of the Airbrake notifier requires iOS 4.0 or later
#ifndef __IPHONE_5_0
#error This version of the Airbrake notifier requires iOS 5.0 or later
#endif
#elif TARGET_OS_MAC
#import <Cocoa/Cocoa.h>
Expand Down Expand Up @@ -69,10 +69,7 @@ extern NSString * const ABNotifierDidDismissAlertNotification;
extern NSString * const ABNotifierWillPostNoticesNotification;
extern NSString * const ABNotifierDidPostNoticesNotification;

/*
The current API also requires your Airbrake project ID. You can find your project ID from http://help.airbrake.io/kb/api-2/notifier-api-v3. Please use your own project ID.
*/
static NSString * const ABNotifierProjectID = @"95161";

/*
HTNotifier is the primary class of the notifer library. Start the notifier by
Expand All @@ -88,6 +85,7 @@ static NSString * const ABNotifierProjectID = @"95161";
here are as follows:
API Key: your Airbrake project API key
Product ID: each app should have its own product ID. You can find your project ID from http://help.airbrake.io/kb/api-2/notifier-api-v3.
Environment Name: the name of the environment to collect notices in
SSL: set this to enable secure reporting if your Airbrake account supports it
Delegate: the object that wishes to receive events from the notifier
Expand All @@ -97,22 +95,31 @@ static NSString * const ABNotifierProjectID = @"95161";
before notices are posted
*/

+ (void)startNotifierWithAPIKey:(NSString *)key
projectID:(NSString *)projectId
environmentName:(NSString *)name
useSSL:(BOOL)useSSL;
+ (void)startNotifierWithAPIKey:(NSString *)key
projectID:(NSString *)projectId
environmentName:(NSString *)name
useSSL:(BOOL)useSSL
delegate:(id<ABNotifierDelegate>)delegate;
+ (void)startNotifierWithAPIKey:(NSString *)key
projectID:(NSString *)projectId
environmentName:(NSString *)name
userName:(NSString *)username
useSSL:(BOOL)useSSL
delegate:(id<ABNotifierDelegate>)delegate;
+ (void)startNotifierWithAPIKey:(NSString *)key
projectID:(NSString *)projectId
environmentName:(NSString *)name
useSSL:(BOOL)useSSL
delegate:(id<ABNotifierDelegate>)delegate
installExceptionHandler:(BOOL)exception
installSignalHandler:(BOOL)signal;
+ (void)startNotifierWithAPIKey:(NSString *)key
projectID:(NSString *)projectId
environmentName:(NSString *)name
userName:(NSString *)username
useSSL:(BOOL)useSSL
Expand All @@ -128,7 +135,7 @@ static NSString * const ABNotifierProjectID = @"95161";
*/
+ (id<ABNotifierDelegate>)delegate;
+ (NSString *)APIKey;

+ (NSString *)projectID;
/*
Log an exception and optionally save parameters with this exception. These
Expand Down
144 changes: 103 additions & 41 deletions Airbrake/notifier/ABNotifier.m
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,20 @@ of this software and associated documentation files (the "Software"), to deal
static id<ABNotifierDelegate> __delegate = nil;
static NSMutableDictionary *__userData;
static NSString * __APIKey = nil;
static NSString * __ABProjectID = nil;
static BOOL __useSSL = NO;
static BOOL __displayPrompt = YES;
static NSString *__userName = @"Anonymous";
static NSString *__envName = nil;
static NSString *__noticePath = nil;
// constant strings
static NSString * const ABNotifierHostName = @"airbrake.io";
static NSString * const ABNotifierAlwaysSendKey = @"AlwaysSendCrashReports";
NSString * const ABNotifierWillDisplayAlertNotification = @"ABNotifierWillDisplayAlert";
NSString * const ABNotifierDidDismissAlertNotification = @"ABNotifierDidDismissAlert";
NSString * const ABNotifierWillPostNoticesNotification = @"ABNotifierWillPostNotices";
NSString * const ABNotifierDidPostNoticesNotification = @"ABNotifierDidPostNotices";
NSString * const ABNotifierVersion = @"4.1";
NSString * const ABNotifierVersion = @"4.2";
NSString * const ABNotifierDevelopmentEnvironment = @"Development";
NSString * const ABNotifierAdHocEnvironment = @"Ad Hoc";
NSString * const ABNotifierAppStoreEnvironment = @"App Store";
Expand Down Expand Up @@ -91,30 +93,32 @@ + (BOOL)isReachable:(SCNetworkReachabilityFlags)flags;
@implementation ABNotifier

#pragma mark - initialize the notifier
+ (void)startNotifierWithAPIKey:(NSString *)key environmentName:(NSString *)name useSSL:(BOOL)useSSL delegate:(id<ABNotifierDelegate>)delegate {
[self startNotifierWithAPIKey:key environmentName:name userName:__userName useSSL:useSSL delegate:delegate installExceptionHandler:YES installSignalHandler:YES displayUserPrompt:YES];
+ (void)startNotifierWithAPIKey:(NSString *)key projectID:(NSString *)projectId environmentName:(NSString *)name useSSL:(BOOL)useSSL {
[self startNotifierWithAPIKey:key projectID:projectId environmentName:name useSSL:useSSL delegate:nil];
}
+ (void)startNotifierWithAPIKey:(NSString *)key environmentName:(NSString *)name useSSL:(BOOL)useSSL delegate:(id<ABNotifierDelegate>)delegate installExceptionHandler:(BOOL)exception installSignalHandler:(BOOL)signal {
[self startNotifierWithAPIKey:key environmentName:name userName:__userName useSSL:useSSL delegate:delegate installExceptionHandler:exception installSignalHandler:signal displayUserPrompt:YES];

+ (void)startNotifierWithAPIKey:(NSString *)key projectID:(NSString *)projectId environmentName:(NSString *)name useSSL:(BOOL)useSSL delegate:(id<ABNotifierDelegate>)delegate {
[self startNotifierWithAPIKey:key projectID:projectId environmentName:name userName:__userName useSSL:useSSL delegate:delegate installExceptionHandler:YES installSignalHandler:YES displayUserPrompt:YES];
}
+ (void)startNotifierWithAPIKey:(NSString *)key projectID:(NSString *)projectId environmentName:(NSString *)name useSSL:(BOOL)useSSL delegate:(id<ABNotifierDelegate>)delegate installExceptionHandler:(BOOL)exception installSignalHandler:(BOOL)signal {
[self startNotifierWithAPIKey:key projectID:projectId environmentName:name userName:__userName useSSL:useSSL delegate:delegate installExceptionHandler:exception installSignalHandler:signal displayUserPrompt:YES];
}

+ (void)startNotifierWithAPIKey:(NSString *)key
projectID:(NSString *)projectId
environmentName:(NSString *)name
userName:(NSString *)username
useSSL:(BOOL)useSSL
delegate:(id<ABNotifierDelegate>)delegate {
[self startNotifierWithAPIKey:key
environmentName:name
userName:username
useSSL:useSSL
delegate:delegate
[self startNotifierWithAPIKey:key projectID:projectId environmentName:name userName:username useSSL:useSSL delegate:delegate
installExceptionHandler:YES
installSignalHandler:YES
displayUserPrompt:YES];
}


+ (void)startNotifierWithAPIKey:(NSString *)key
projectID:(NSString *)projectId
environmentName:(NSString *)name
userName:(NSString *)username
useSSL:(BOOL)useSSL
Expand Down Expand Up @@ -143,9 +147,10 @@ + (void)startNotifierWithAPIKey:(NSString *)key

// start crashreport
[[ABCrashReport sharedInstance] startCrashReport];
// switch on api key
if ([key length]) {
// switch on api key and project id
if ([key length] && [projectId length]) {
__APIKey = [key copy];
__ABProjectID = [projectId copy];
__reachability = SCNetworkReachabilityCreateWithName(NULL, [ABNotifierHostName UTF8String]);
if (SCNetworkReachabilitySetCallback(__reachability, ABNotifierReachabilityDidChange, nil)) {
if (!SCNetworkReachabilityScheduleWithRunLoop(__reachability, CFRunLoopGetMain(), kCFRunLoopDefaultMode)) {
Expand All @@ -154,7 +159,7 @@ + (void)startNotifierWithAPIKey:(NSString *)key
}
}
else {
ABLog(@"The API key must not be blank. No notices will be posted.");
ABLog(@"The API key and ProjectID must not be blank. No notices will be posted.");
}

// switch on environment name
Expand Down Expand Up @@ -225,6 +230,11 @@ + (NSString *)APIKey {
return __APIKey;
}
}
+ (NSString *)projectID {
@synchronized(self) {
return __ABProjectID;
}
}

#pragma mark - write data
+ (void)logException:(NSException *)exception parameters:(NSDictionary *)parameters {
Expand Down Expand Up @@ -269,7 +279,7 @@ + (void)logException:(NSException *)exception parameters:(NSDictionary *)paramet

// delegate
id<ABNotifierDelegate> delegate = [self delegate];
if ([delegate respondsToSelector:@selector(notifierDidLogException:)]) {
if (delegate && [delegate respondsToSelector:@selector(notifierDidLogException:)]) {
[delegate notifierDidLogException:exception];
}

Expand All @@ -287,6 +297,7 @@ + (void)logException:(NSException *)exception parameters:(NSDictionary *)paramet
+ (void)logException:(NSException *)exception {
[self logException:exception parameters:nil];
}

+ (void)writeTestNotice {
@try {
NSArray *array = [NSArray array];
Expand Down Expand Up @@ -361,35 +372,60 @@ + (NSString *)pathForNoticesDirectory {
attributes:nil
error:nil];
}
#if !TARGET_OS_IPHONE
__noticePath = [[NSString alloc] initWithString:path];
#endif
});
return path;
}
+ (NSString *)pathForNewNoticeWithName:(NSString *)name {
NSString *path = [self pathForNoticesDirectory];
#if !TARGET_OS_IPHONE
if (__noticePath) {
path = __noticePath;
}
#endif
path = [path stringByAppendingPathComponent:name];
return [path stringByAppendingPathExtension:ABNotifierNoticePathExtension];
}

+ (NSString *)pathForNewExceptionWithName:(NSString *)name {
NSString *path = [self pathForNoticesDirectory];
#if !TARGET_OS_IPHONE
if (__noticePath) {
path = __noticePath;
}
#endif
path = [path stringByAppendingPathComponent:name];
return [path stringByAppendingPathExtension:ABNotifierExceptionPathExtension];
}

+ (NSArray *)pathsForAllNotices {
NSString *path = [self pathForNoticesDirectory];
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
NSMutableArray *paths = [NSMutableArray arrayWithCapacity:[contents count]];
[contents enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([[obj pathExtension] isEqualToString:ABNotifierNoticePathExtension]) {
NSString *noticePath = [path stringByAppendingPathComponent:obj];
[paths addObject:noticePath];
} else if ([[obj pathExtension] isEqualToString:ABNotifierExceptionPathExtension]) {
NSString *noticePath = [path stringByAppendingPathComponent:obj];
[paths addObject:noticePath];
}
}];
return paths;
#if !TARGET_OS_IPHONE
if (__noticePath) {
path = __noticePath;
}
#endif
NSMutableArray *paths = [NSMutableArray arrayWithCapacity:0];
@try {
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
[contents enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([[obj pathExtension] isEqualToString:ABNotifierNoticePathExtension]) {
NSString *noticePath = [path stringByAppendingPathComponent:obj];
[paths addObject:noticePath];
} else if ([[obj pathExtension] isEqualToString:ABNotifierExceptionPathExtension]) {
NSString *noticePath = [path stringByAppendingPathComponent:obj];
[paths addObject:noticePath];
}
}];
}
@catch (NSException *exception) {
ABLog(@"Error when getting pathsFroAllNotices: %@", exception.description);
}
@finally {
return paths;
}
}

#pragma mark - post notices
Expand Down Expand Up @@ -476,7 +512,7 @@ + (void)postNoticeWithContentsOfFile:(NSString *)path {
NSString *URLString = [NSString stringWithFormat:
@"%@://api.airbrake.io/api/v3/projects/%@/ios-reports?key=%@",
(__useSSL ? @"https" : @"http"),
ABNotifierProjectID, [self APIKey]];
[self projectID], [self APIKey]];
NSData *jsonData;
NSString *fileType = [path pathExtension];
// create data based on file name, if it's a full crash report, will send the report as human readable string.
Expand All @@ -487,7 +523,7 @@ + (void)postNoticeWithContentsOfFile:(NSString *)path {
URLString = [NSString stringWithFormat:
@"%@://api.airbrake.io/api/v3/projects/%@/notices?key=%@",
(__useSSL ? @"https" : @"http"),
ABNotifierProjectID, [self APIKey]];
[self projectID], [self APIKey]];
// get ABNotice
ABNotice *notice = [ABNotice noticeWithContentsOfFile:path];
[notice setPOSTUserName:__userName];
Expand Down Expand Up @@ -596,7 +632,7 @@ + (void)showNoticeAlertForNoticesWithPaths:(NSArray *)paths {

// alert body
NSString *body = nil;
if ([delegate respondsToSelector:@selector(bodyForNoticeAlert)]) {
if (delegate && [delegate respondsToSelector:@selector(bodyForNoticeAlert)]) {
body = [delegate bodyForNoticeAlert];
}
if (body == nil) {
Expand Down Expand Up @@ -634,18 +670,44 @@ + (void)showNoticeAlertForNoticesWithPaths:(NSArray *)paths {
};

#if TARGET_OS_IPHONE

GCAlertView *alert = [[GCAlertView alloc] initWithTitle:title message:body];
[alert addButtonWithTitle:ABLocalizedString(@"ALWAYS_SEND") block:^{
setDefaultsBlock();
postNoticesBlock();
}];
[alert addButtonWithTitle:ABLocalizedString(@"SEND") block:postNoticesBlock];
[alert addButtonWithTitle:ABLocalizedString(@"DONT_SEND") block:deleteNoticesBlock];
[alert setDidDismissBlock:delegateDismissBlock];
[alert setDidDismissBlock:delegatePresentBlock];
[alert setCancelButtonIndex:2];
[alert show];
if ([UIAlertController class]) {
UIAlertController *alert= [UIAlertController alertControllerWithTitle:title
message:body
preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction* alwaysSend = [UIAlertAction actionWithTitle:ABLocalizedString(@"ALWAYS_SEND")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action){
postNoticesBlock();
}];
UIAlertAction* send = [UIAlertAction actionWithTitle:ABLocalizedString(@"SEND")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action){
postNoticesBlock();
}];
UIAlertAction* cancel = [UIAlertAction actionWithTitle:ABLocalizedString(@"DONT_SEND")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
deleteNoticesBlock();
[alert dismissViewControllerAnimated:YES completion:nil];
}];

[alert addAction:alwaysSend];
[alert addAction:send];
[alert addAction:cancel];
[[[UIApplication sharedApplication] delegate].window.rootViewController presentViewController:alert animated:YES completion:nil];
} else {
GCAlertView *alert = [[GCAlertView alloc] initWithTitle:title message:body];
[alert addButtonWithTitle:ABLocalizedString(@"ALWAYS_SEND") block:^{
setDefaultsBlock();
postNoticesBlock();
}];
[alert addButtonWithTitle:ABLocalizedString(@"SEND") block:postNoticesBlock];
[alert addButtonWithTitle:ABLocalizedString(@"DONT_SEND") block:deleteNoticesBlock];
[alert setDidDismissBlock:delegateDismissBlock];
[alert setDidDismissBlock:delegatePresentBlock];
[alert setCancelButtonIndex:2];
[alert show];
}

#else

Expand Down
2 changes: 1 addition & 1 deletion Airbrake/notifier/ABNotifierFunctions.m
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ void ABNotifierStopSignalHandler(void) {

#pragma mark - Info.plist accessors
NSString *ABNotifierApplicationVersion(void) {
static NSString *version = nil;
static NSString *version = @"0.0";
static dispatch_once_t token;
dispatch_once(&token, ^{
NSString *bundleVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
Expand Down
Loading

0 comments on commit ae556cd

Please sign in to comment.