Last active
January 7, 2016 02:14
-
-
Save rupey/fb2277135c1a300b8753 to your computer and use it in GitHub Desktop.
Capturing customer feedback with a device log on iOS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <UIKit/UIKit.h> | |
#import <MessageUI/MessageUI.h> | |
#include <asl.h> | |
@interface FeedbackViewController : UIViewController <MFMailComposeViewControllerDelegate> | |
@property (nonatomic, strong) IBOutlet UITextView *textView; | |
@property (nonatomic, strong) NSString *feedbackType; | |
@end | |
@implementation FeedbackViewController | |
- (void)sendMail | |
{ | |
if ([MFMailComposeViewController canSendMail]) | |
{ | |
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init]; | |
mailer.mailComposeDelegate = self; | |
[mailer setSubject:[@"AppName - " stringByAppendingString:self.feedbackType]]; | |
NSArray *toRecipients = @[@"[email protected]"]; | |
[mailer setToRecipients:toRecipients]; | |
// Generate body | |
NSString *appShortVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; | |
NSString *appVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; | |
NSString *emailBody = [NSString stringWithFormat:@"%@\n\nVersion: %@ (%@)", self.textView.text, appShortVersion, appVersion]; | |
[mailer setMessageBody:emailBody isHTML:NO]; | |
#if !TARGET_IPHONE_SIMULATOR | |
[mailer addAttachmentData:[self getConsoleLog] mimeType:@"text/plain" fileName:@"application.log"]; | |
#endif | |
[self presentViewController:mailer animated:YES completion:^{}]; | |
} | |
else | |
{ | |
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Mail is unavailable" | |
message:@"Check your device is connected to the Internet and you have set up a Mail account in the Settings app." | |
delegate:nil | |
cancelButtonTitle:@"OK" | |
otherButtonTitles:nil]; | |
[alert show]; | |
} | |
} | |
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error | |
{ | |
switch (result) | |
{ | |
case MFMailComposeResultCancelled: | |
NSLog(@"Mail cancelled: you cancelled the operation and no email message was queued."); | |
break; | |
case MFMailComposeResultSaved: | |
NSLog(@"Mail saved: you saved the email message in the drafts folder."); | |
break; | |
case MFMailComposeResultSent: | |
NSLog(@"Mail send: the email message is queued in the outbox. It is ready to send."); | |
break; | |
case MFMailComposeResultFailed: | |
NSLog(@"Mail failed: the email message was not saved or queued, possibly due to an error."); | |
break; | |
default: | |
NSLog(@"Mail not sent."); | |
break; | |
} | |
// Remove the mail view | |
[self dismissViewControllerAnimated:YES completion:^{ | |
if (result == MFMailComposeResultSent) | |
[self.navigationController popViewControllerAnimated:YES]; | |
}]; | |
} | |
// Get the app's console log | |
- (NSData *)getConsoleLog | |
{ | |
// Create an Apple System Log query. | |
aslmsg query = asl_new(ASL_TYPE_QUERY); | |
aslresponse response = asl_search(NULL, query); | |
// Iterate through the query responses and assemble them into a log string. | |
NSString* logString = [NSString new]; | |
aslmsg message; | |
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) | |
{ | |
#pragma GCC diagnostic push | |
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" | |
while ((message = aslresponse_next(response)) != NULL) { | |
@autoreleasepool { | |
NSMutableDictionary *tmpDict = [NSMutableDictionary dictionary]; | |
const char *key, *val; | |
// Get all the key/value pairs from the response message. We don't really need them all, but it's a little simpler to just get them all in C. | |
for (int i = 0; (key = asl_key(message, i)) != NULL; i++) { | |
NSString *keyString = [NSString stringWithUTF8String:(char *)key]; | |
val = asl_get(message, key); | |
NSString *string = val ? [NSString stringWithUTF8String:val] : @""; | |
[tmpDict setObject:string forKey:keyString]; | |
} | |
// Get the key/value pairs that we want and append them to the log string. | |
NSDate* date = [NSDate dateWithTimeIntervalSince1970:((NSNumber*)tmpDict[@"Time"]).doubleValue]; | |
NSString* dateString = [NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterLongStyle]; | |
logString = [logString stringByAppendingFormat:@"%@ %@\n",dateString, tmpDict[@"Message"]]; | |
} | |
} | |
aslresponse_free(response); | |
#pragma GCC diagnostic pop | |
} | |
else { | |
while ((message = asl_next(response)) != NULL) { | |
@autoreleasepool { | |
NSMutableDictionary *tmpDict = [NSMutableDictionary dictionary]; | |
const char *key, *val; | |
// Get all the key/value pairs from the response message. We don't really need them all, but it's a little simpler to just get them all in C. | |
for (int i = 0; (key = asl_key(message, i)) != NULL; i++) { | |
NSString *keyString = [NSString stringWithUTF8String:(char *)key]; | |
val = asl_get(message, key); | |
NSString *string = val ? [NSString stringWithUTF8String:val] : @""; | |
[tmpDict setObject:string forKey:keyString]; | |
} | |
// Get the key/value pairs that we want and append them to the log string. | |
NSDate* date = [NSDate dateWithTimeIntervalSince1970:((NSNumber*)tmpDict[@"Time"]).doubleValue]; | |
NSString* dateString = [NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterLongStyle]; | |
logString = [logString stringByAppendingFormat:@"%@ %@\n",dateString, tmpDict[@"Message"]]; | |
} | |
} | |
asl_free(response); | |
} | |
return [logString dataUsingEncoding:NSUTF8StringEncoding]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment