ios Crash闪退日志获取和上传至服务器(NSSetUncaughtExceptionHandler)
2014-06-30 16:50
204 查看
最近客户有个要求:人家谁谁有crash日志捕获和上传,我们是不是也要做一个... 人家谁谁.....还有什么什么功能........
正好最近也在研究这方面东东,所以整理一下分享给大家:如何用程序获取Crash日志 并 可以上传Crash日志。
首先我们整理经常会闪退的异常哪些:数组越界、空引用、引用未定义方法、内存空间不足等等。
友盟分享后台是可以看到crash的日志,如下图:
开始研究的时候,我有两个疑问:
1.如何获取crash闪退日志(工具和程序两种方法);
2.解析crash;
说明:这里说的crash日志不是在联调的情况下(是生产环境,通俗的说就是发布了的产品)。
如何获取crash闪退日志 -- 工具查看
先看第一个问题如何查看,我搜索的方法有以下几个:
第一个方法:XCode 的菜单Window->Organizer 选择Devices -> 选中的手机 -> 点击手机名称左边的箭头 会等到如下图
在右边竖蓝色矩形框中 Type里面出现两种类型:Unknown和Crash 这两种类型分别是 内存不够回收内存kill应用程序导致Crash和程序异常Crash的日志。
上图是我在刚打开日志(立马、马上)截的图,否则过了5秒中,会变成这样(自动解析):
注意对比一下红色框框内容,这个日志也基本上上告诉你crash的原因了。
第二种方法 打开手机 - > 设置 -> 通用 - > 关于本机 - > 诊断与用量 - > 诊断与用量数据 这里面就是所有应用的Crash日志。
第三种方法 通过iTunes Connect(Manage Your Applications - View Details - Crash Reports)获取用户的crash日志。方法很多这里不多列了。
解析crash
参见:http://stackoverflow.com/questions/1460892/symbolicating-iphone-app-crash-reports )
用程序获取crash日志
但是这里都是工具,没有用到程序获取,经过千方百计的查询(思路是:先找到存放crash的iphone系统路径:var/mobile/Library/Logs/CrashReporter)找到了crash存放的路径,唉,苦于无法读取(用程序读出来都是nil),当然如果是越狱手机就不一样是可以读取的。这个思路断掉了。
换个思路:自己用程序捕获crash,保存到本地可以吗?这么一试,果然........
第一步:新建一个继承自NSObject的类(Xcode新建一个空项目过程略),取名字CatchCrash,在h和m文件中写下:
.h文件
.m(m)文件
第二步:添加一个继承自UIViewcontroller的类,取名字为TestViewController。
第三步:注册CatchCrash异常处理方法,在Appdelegate写下如下代码:
第四部:在TestViewController的Xib上面添加一个按钮并给其添加一个单击事件,TestViewController.m文件中有如下代码:
运行代码:可以看到闪退,我们用iExplorer打开:
导出error日志,我们可以看到:
太清楚了,对吧,下次启动应用程序的时候可以把这个error.log(这个名字我临时写的,用什么日期也可以的)上传。可以在日志中加上类似与友盟的 iphone 的UUID、Bundle ID 等等。
现在猜测一下,友盟是不是这么做的呢?
进入一个引用友盟sdk项目的根目录,打开mac终端输入命令 grep -r NSSetUncaughtExceptionHandler .(这个点不能少或者绝对路径替换这个点),得到如下图:
真的就找到了,什么什么 matches。当然这只是猜测。
点击下载源文件
更多iOS交流:28926427
正好最近也在研究这方面东东,所以整理一下分享给大家:如何用程序获取Crash日志 并 可以上传Crash日志。
首先我们整理经常会闪退的异常哪些:数组越界、空引用、引用未定义方法、内存空间不足等等。
友盟分享后台是可以看到crash的日志,如下图:
开始研究的时候,我有两个疑问:
1.如何获取crash闪退日志(工具和程序两种方法);
2.解析crash;
说明:这里说的crash日志不是在联调的情况下(是生产环境,通俗的说就是发布了的产品)。
如何获取crash闪退日志 -- 工具查看
先看第一个问题如何查看,我搜索的方法有以下几个:
第一个方法:XCode 的菜单Window->Organizer 选择Devices -> 选中的手机 -> 点击手机名称左边的箭头 会等到如下图
在右边竖蓝色矩形框中 Type里面出现两种类型:Unknown和Crash 这两种类型分别是 内存不够回收内存kill应用程序导致Crash和程序异常Crash的日志。
上图是我在刚打开日志(立马、马上)截的图,否则过了5秒中,会变成这样(自动解析):
注意对比一下红色框框内容,这个日志也基本上上告诉你crash的原因了。
第二种方法 打开手机 - > 设置 -> 通用 - > 关于本机 - > 诊断与用量 - > 诊断与用量数据 这里面就是所有应用的Crash日志。
第三种方法 通过iTunes Connect(Manage Your Applications - View Details - Crash Reports)获取用户的crash日志。方法很多这里不多列了。
解析crash
参见:http://stackoverflow.com/questions/1460892/symbolicating-iphone-app-crash-reports )
用程序获取crash日志
但是这里都是工具,没有用到程序获取,经过千方百计的查询(思路是:先找到存放crash的iphone系统路径:var/mobile/Library/Logs/CrashReporter)找到了crash存放的路径,唉,苦于无法读取(用程序读出来都是nil),当然如果是越狱手机就不一样是可以读取的。这个思路断掉了。
换个思路:自己用程序捕获crash,保存到本地可以吗?这么一试,果然........
第一步:新建一个继承自NSObject的类(Xcode新建一个空项目过程略),取名字CatchCrash,在h和m文件中写下:
.h文件
#import <Foundation/Foundation.h> @interface CatchCrash : NSObject void uncaughtExceptionHandler(NSException *exception); @end
.m(m)文件
#import "CatchCrash.h" @implementation CatchCrash void uncaughtExceptionHandler(NSException *exception) { // 异常的堆栈信息 NSArray *stackArray = [exception callStackSymbols]; // 出现异常的原因 NSString *reason = [exception reason]; // 异常名称 NSString *name = [exception name]; NSString *exceptionInfo = [NSString stringWithFormat:@"Exception reason:%@\nException name:%@\nException stack:%@",name, reason, stackArray]; NSLog(@"%@", exceptionInfo); NSMutableArray *tmpArr = [NSMutableArray arrayWithArray:stackArray]; [tmpArr insertObject:reason atIndex:0]; //保存到本地 -- 当然你可以在下次启动的时候,上传这个log [exceptionInfo writeToFile:[NSString stringWithFormat:@"%@/Documents/error.log",NSHomeDirectory()] atomically:YES encoding:NSUTF8StringEncoding error:nil]; } @end
第二步:添加一个继承自UIViewcontroller的类,取名字为TestViewController。
第三步:注册CatchCrash异常处理方法,在Appdelegate写下如下代码:
#import "AppDelegate.h" #import "CatchCrash.h" #import "TestViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. //注册消息处理函数的处理方法 NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler); TestViewController *testVc = [[TestViewController alloc] init]; self.window.rootViewController = testVc; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; } - (void)applicationWillResignActive:(UIApplication *)application {} - (void)applicationDidEnterBackground:(UIApplication *)application {} - (void)applicationWillEnterForeground:(UIApplication *)application {} - (void)applicationDidBecomeActive:(UIApplication *)application {} - (void)applicationWillTerminate:(UIApplication *)application {}
第四部:在TestViewController的Xib上面添加一个按钮并给其添加一个单击事件,TestViewController.m文件中有如下代码:
#import "TestViewController.h" @interface TestViewController () @end @implementation TestViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - 单击事件 - (IBAction)crashTapped:(id)sender { //常见异常1---不存在方法引用 // [self performSelector:@selector(thisMthodDoesNotExist) withObject:nil]; //常见异常2---键值对引用nil // [[NSMutableDictionary dictionary] setObject:nil forKey:@"nil"]; //常见异常3---数组越界 [[NSArray array] objectAtIndex:1]; //常见异常4---memory warning 级别3以上 // [self performSelector:@selector(killMemory) withObject:nil]; //其他大家去想吧 } #pragma mark - custom method - (void) killMemory { for (int i = 0; i < 300; i ++) { UILabel *tmpLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 200)]; tmpLabel.layer.masksToBounds = YES; tmpLabel.layer.cornerRadius = 10; tmpLabel.backgroundColor = [UIColor redColor]; [self.view addSubview:tmpLabel]; } } @end
运行代码:可以看到闪退,我们用iExplorer打开:
导出error日志,我们可以看到:
Exception reason:NSRangeException <span style="color:#FF0000;">Exception name:*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds for empty array</span> Exception stack:( 0 CoreFoundation 0x2f2edfeb <redacted> + 154 1 libobjc.A.dylib 0x39b66ccf objc_exception_throw + 38 2 CoreFoundation 0x2f224a89 <redacted> + 176 <span style="color:#FF0000;"> 3 TestCrash 0x000e8077 -[TestViewController crashTapped:] + 126</span> 4 UIKit 0x31b3f057 <redacted> + 90 5 UIKit 0x31b3eff7 <redacted> + 30 6 UIKit 0x31b3efd1 <redacted> + 44 7 UIKit 0x31b2a737 <redacted> + 374 8 UIKit 0x31b3ea4f <redacted> + 590 9 UIKit 0x31b3e721 <redacted> + 528 10 UIKit 0x31b396eb <redacted> + 758 11 UIKit 0x31b0e8ed <redacted> + 196 12 UIKit 0x31b0cf97 <redacted> + 7102 13 CoreFoundation 0x2f2b925b <redacted> + 14 14 CoreFoundation 0x2f2b872b <redacted> + 206 15 CoreFoundation 0x2f2b6f1f <redacted> + 622 16 CoreFoundation 0x2f221f0f CFRunLoopRunSpecific + 522 17 CoreFoundation 0x2f221cf3 CFRunLoopRunInMode + 106 18 GraphicsServices 0x3417a663 GSEventRunModal + 138 19 UIKit 0x31b6d16d UIApplicationMain + 1136 20 TestCrash 0x000e810d main + 116 21 libdyld.dylib 0x3a073ab7 <redacted> + 2 )
太清楚了,对吧,下次启动应用程序的时候可以把这个error.log(这个名字我临时写的,用什么日期也可以的)上传。可以在日志中加上类似与友盟的 iphone 的UUID、Bundle ID 等等。
现在猜测一下,友盟是不是这么做的呢?
进入一个引用友盟sdk项目的根目录,打开mac终端输入命令 grep -r NSSetUncaughtExceptionHandler .(这个点不能少或者绝对路径替换这个点),得到如下图:
真的就找到了,什么什么 matches。当然这只是猜测。
点击下载源文件
更多iOS交流:28926427
相关文章推荐
- iOS Crash闪退日志获取和上传至服务器(NSSetUncaughtExceptionHandler)
- ios Crash闪退日志获取和上传至服务器(NSSetUncaughtExceptionHandler)
- ios Crash闪退日志获取和上传至服务器(NSSetUncaughtExceptionHandler)
- iOS Crash闪退日志获取和上传至服务器(NSSetUncaughtExceptionHandler)
- ios Crash闪退日志获取和上传至服务器(NSSetUncaughtExceptionHandler)
- iOS Crash闪退日志获取和上传至服务器
- ios Crash闪退日志获取和上传至服务器
- iOS-中捕获程序崩溃日志-NSSetUncaughtExceptionHandler
- iOS Crash闪退日志的捕获和上传至服务器
- iOS —— 发布应用的异常信息捕获和处理 NSSetUncaughtExceptionHandler()
- 实现UncaughtExceptionHandler来实现获取应用全局的crash信息
- IOS崩溃 异常处理(NSSetUncaughtExceptionHandler)
- NSSetUncaughtExceptionHandler在iOS 5.0 模拟器上未被调用
- IOS崩溃 异常处理(NSSetUncaughtExceptionHandler)
- IOS崩溃 异常处理(NSSetUncaughtExceptionHandler)
- android 通过UncaughtExceptionHandler处理和上传错误日志
- IOS崩溃 异常处理(NSSetUncaughtExceptionHandler)
- Android日志打印与处理 UncaughtExceptionHandler 提交服务器
- ios Crash闪退日志获取和上传至服务器
- Android使用UncaughtExceptionHandler获取crash信息