Arclin

Advocate Technology. Enjoy Technology.

0%

Dankal_iOS崩溃信息提交

Dankal_iOS 崩溃信息提交

  1. 获取到崩溃信息(异常原因,异常方法,异常类名,堆栈)
  2. 获取到本机信息(型号,系统)
  3. 保存为 plist到本地
  4. 下次启动应用的时候发送信息到服务器(POST发送,记得添加 token 到HEADER)
  5. 发送完之后删除掉 plist 文件

如何捕获崩溃信息

C 语言捕获

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <libkern/OSAtomic.h>
#include <execinfo.h>

// 系统信号截获处理方法
void signalHandler(int signal);
// 异常截获处理方法
void exceptionHandler(NSException *exception);
const int32_t _uncaughtExceptionMaximum = 20;

NSString * const UncaughtExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey";
NSString *const SingalExceptionHandlerAddressesKey = @"SingalExceptionHandlerAddressesKey";
NSString *const ExceptionHandlerAddressesKey = @"ExceptionHandlerAddressesKey";

void signalHandler(int signal)
{
volatile int32_t _uncaughtExceptionCount = 0;
int32_t exceptionCount = OSAtomicIncrement32(&_uncaughtExceptionCount);
if (exceptionCount > _uncaughtExceptionMaximum) // 如果太多不用处理
{
return;
}
// 获取信息
NSMutableDictionary *userInfo =
[NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:signal] forKey:UncaughtExceptionHandlerSignalKey];

NSArray *callStack = [DKUncaughtExceptionHandler backtrace];
[userInfo setObject:callStack forKey:SingalExceptionHandlerAddressesKey];

}

void exceptionHandler(NSException *exception)
{
volatile int32_t _uncaughtExceptionCount = 0;
int32_t exceptionCount = OSAtomicIncrement32(&_uncaughtExceptionCount);
if (exceptionCount > _uncaughtExceptionMaximum) // 如果太多不用处理
{
return;
}

NSArray *callStack = [DKUncaughtExceptionHandler backtrace];
NSMutableDictionary *userInfo =[NSMutableDictionary dictionaryWithDictionary:[exception userInfo]];
[userInfo setObject:callStack forKey:ExceptionHandlerAddressesKey];

// 保存信息到本地
NSString *path = [[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:@"crash.plist"];

// 获取本机信息
struct utsname systemInfo;
uname(&systemInfo);

NSDictionary *crashInfo = @{@"crash_time":[NSDate dateStringWithDateFormat:@"yyyy-MM-dd HH:mm:ss"],
@"device_type": [DKUncaughtExceptionHandler deviceVersion:[NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]],
@"device_system": [UIDevice currentDevice].systemVersion,
@"crash_type":exception.name,
@"crash_reason":exception.reason,
@"crash_stack":userInfo.descriptionInStringsFileFormat};
[crashInfo writeToFile:path atomically:YES];
}

OC 部分获取调用堆栈和注册崩溃拦截

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//获取调用堆栈
+ (NSArray *)backtrace
{
void* callstack[128];
int frames = backtrace(callstack, 128);
char **strs = backtrace_symbols(callstack,frames);

NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
for (int i=0;i<frames;i++)
{
[backtrace addObject:[NSString stringWithUTF8String:strs[i]]];
}
free(strs);

return backtrace;
}

// 注册崩溃拦截
- (void)installExceptionHandler
{
NSSetUncaughtExceptionHandler(&exceptionHandler);
signal(SIGHUP, signalHandler);
signal(SIGINT, signalHandler);
signal(SIGQUIT, signalHandler);

signal(SIGABRT, signalHandler);
signal(SIGILL, signalHandler);
signal(SIGSEGV, signalHandler);
signal(SIGFPE, signalHandler);
signal(SIGBUS, signalHandler);
signal(SIGPIPE, signalHandler);

NSString *path = [[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:@"crash.plist"];
if([[NSFileManager defaultManager] fileExistsAtPath:path]){
NSDictionary *params = [[NSDictionary alloc] initWithContentsOfFile:path];
[DKHTTPTool POST:去看 Coding 的Crash Reporter项目说明文档 parameters:params header:@{@"token":去看 Coding的Crash Reporter项目说明文档} responseBlock:^(DKResponse *response) {
if (!response.error) {
NSError *error;
[[NSFileManager defaultManager] removeItemAtPath:path error:&error];
if(error)DKLog(@"%@",error);
}
}];
}
}

发送请求的AFN封装方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
+ (void)POST:(NSString *)URLString parameters:(id)parameters header:(NSDictionary *)headerField responseBlock:(DKHTTPResponseBlock)block
{
AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];
AFHTTPRequestSerializer *requestSerializer = [AFJSONRequestSerializer serializer];
[headerField enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
[requestSerializer setValue:obj forHTTPHeaderField:key];
}];
mgr.requestSerializer = requestSerializer;
[mgr POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
DKResponse *resp = [DKResponse mj_objectWithKeyValues:responseObject];
resp.rawData = responseObject;
if(block){
block(resp);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
DKResponse *resp = [[DKResponse alloc] init];
resp.error = error;
if (block) {
block(resp);
}
}];
}
```

## 在 AppDelegte内注册

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    [[[DKUncaughtExceptionHandler alloc] init] installExceptionHandler];
    return YES:
    }
    1
    2
    3

    ## iOS设备测试编号转机型

  • (NSString *) deviceVersion:(NSString *)deviceString
    {
    //iPhone
    if ([deviceString isEqualToString:@”iPhone1,1”]) return @”iPhone 1G”;
    if ([deviceString isEqualToString:@”iPhone1,2”]) return @”iPhone 3G”;
    if ([deviceString isEqualToString:@”iPhone2,1”]) return @”iPhone 3GS”;
    if ([deviceString isEqualToString:@”iPhone3,1”]) return @”iPhone 4”;
    if ([deviceString isEqualToString:@”iPhone3,2”]) return @”Verizon iPhone 4”;
    if ([deviceString isEqualToString:@”iPhone4,1”]) return @”iPhone 4S”;
    if ([deviceString isEqualToString:@”iPhone5,1”]) return @”iPhone 5”;
    if ([deviceString isEqualToString:@”iPhone5,2”]) return @”iPhone 5”;
    if ([deviceString isEqualToString:@”iPhone5,3”]) return @”iPhone 5C”;
    if ([deviceString isEqualToString:@”iPhone5,4”]) return @”iPhone 5C”;
    if ([deviceString isEqualToString:@”iPhone6,1”]) return @”iPhone 5S”;
    if ([deviceString isEqualToString:@”iPhone6,2”]) return @”iPhone 5S”;
    if ([deviceString isEqualToString:@”iPhone7,1”]) return @”iPhone 6 Plus”;
    if ([deviceString isEqualToString:@”iPhone7,2”]) return @”iPhone 6”;
    if ([deviceString isEqualToString:@”iPhone8,1”]) return @”iPhone 6s”;
    if ([deviceString isEqualToString:@”iPhone8,2”]) return @”iPhone 6s Plus”;
    if ([deviceString isEqualToString:@”iPhone8,4”]) return @”iPhone SE”;
    if ([deviceString isEqualToString:@”iPhone9,1”]) return @”iPhone 7”;
    if ([deviceString isEqualToString:@”iPhone9,3”]) return @”iPhone 7”;
    if ([deviceString isEqualToString:@”iPhone9,2”]) return @”iPhone 7 Plus”;
    if ([deviceString isEqualToString:@”iPhone9,4”]) return @”iPhone 7 Plus”; //iPod
    if ([deviceString isEqualToString:@”iPod1,1”]) return @”iPod Touch 1G”;
    if ([deviceString isEqualToString:@”iPod2,1”]) return @”iPod Touch 2G”;
    if ([deviceString isEqualToString:@”iPod3,1”]) return @”iPod Touch 3G”;
    if ([deviceString isEqualToString:@”iPod4,1”]) return @”iPod Touch 4G”;
    if ([deviceString isEqualToString:@”iPod5,1”]) return @”iPod Touch 5G”; //iPad
    if ([deviceString isEqualToString:@”iPad1,1”]) return @”iPad”;
    if ([deviceString isEqualToString:@”iPad2,1”]) return @”iPad 2 (WiFi)”;
    if ([deviceString isEqualToString:@”iPad2,2”]) return @”iPad 2 (GSM)”;
    if ([deviceString isEqualToString:@”iPad2,3”]) return @”iPad 2 (CDMA)”;
    if ([deviceString isEqualToString:@”iPad2,4”]) return @”iPad 2 (32nm)”;
    if ([deviceString isEqualToString:@”iPad2,5”]) return @”iPad mini (WiFi)”;
    if ([deviceString isEqualToString:@”iPad2,6”]) return @”iPad mini (GSM)”;
    if ([deviceString isEqualToString:@”iPad2,7”]) return @”iPad mini (CDMA)”; if ([deviceString isEqualToString:@”iPad3,1”]) return @”iPad 3(WiFi)”;
    if ([deviceString isEqualToString:@”iPad3,2”]) return @”iPad 3(CDMA)”;
    if ([deviceString isEqualToString:@”iPad3,3”]) return @”iPad 3(4G)”;
    if ([deviceString isEqualToString:@”iPad3,4”]) return @”iPad 4 (WiFi)”;
    if ([deviceString isEqualToString:@”iPad3,5”]) return @”iPad 4 (4G)”;
    if ([deviceString isEqualToString:@”iPad3,6”]) return @”iPad 4 (CDMA)”; if ([deviceString isEqualToString:@”iPad4,1”]) return @”iPad Air”;
    if ([deviceString isEqualToString:@”iPad4,2”]) return @”iPad Air”;
    if ([deviceString isEqualToString:@”iPad4,3”]) return @”iPad Air”;
    if ([deviceString isEqualToString:@”iPad5,3”]) return @”iPad Air 2”;
    if ([deviceString isEqualToString:@”iPad5,4”]) return @”iPad Air 2”;
    if ([deviceString isEqualToString:@”i386”]) return @”Simulator”;
    if ([deviceString isEqualToString:@”x86_64”]) return @”Simulator”; if ([deviceString isEqualToString:@”iPad4,4”]
      ||[deviceString isEqualToString:@"iPad4,5"]
      ||[deviceString isEqualToString:@"iPad4,6"])      return @"iPad mini 2";
    
    if ([deviceString isEqualToString:@”iPad4,7”]
      ||[deviceString isEqualToString:@"iPad4,8"]
      ||[deviceString isEqualToString:@"iPad4,9"])      return @"iPad mini 3";
    
    return deviceString;
    }
    ```