mirror of
https://gitee.com/shuto/CrashLog.git
synced 2024-10-06 02:52:07 +08:00
添加 ios 相关代码
This commit is contained in:
parent
a18262c7b6
commit
22344d2d41
18
plugin.xml
18
plugin.xml
@ -3,9 +3,6 @@
|
||||
xmlns="http://apache.org/cordova/ns/plugins/1.0"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<name>CrashLog</name>
|
||||
<!-- js-module name="CrashLog" src="www/crash-log.js">
|
||||
<clobbers target="CrashLog" />
|
||||
</js-module -->
|
||||
<platform name="android">
|
||||
<config-file parent="/*" target="res/xml/config.xml">
|
||||
<feature name="CrashLog">
|
||||
@ -13,11 +10,22 @@
|
||||
<param name="onload" value="true" />
|
||||
</feature>
|
||||
</config-file>
|
||||
<config-file target="AndroidManifest.xml" parent="/manifest">
|
||||
<config-file parent="/manifest" target="AndroidManifest.xml">
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
</config-file>
|
||||
|
||||
<source-file src="src/android/cn/shuto/crash/CrashLogPlugin.java" target-dir="src/cn/shuto/crash" />
|
||||
<source-file src="src/android/cn/shuto/crash/CrashHandler.java" target-dir="src/cn/shuto/crash" />
|
||||
</platform>
|
||||
<platform name="ios">
|
||||
<config-file parent="/*" target="config.xml">
|
||||
<feature name="CrashLog">
|
||||
<param name="ios-package" value="CrashLogPlugin" />
|
||||
<param name="onload" value="true" />
|
||||
</feature>
|
||||
</config-file>
|
||||
<header-file src="src/ios/CrashLogPlugin.h" />
|
||||
<source-file src="src/ios/CrashLogPlugin.m" />
|
||||
<header-file src="src/ios/CrashHandler.h" />
|
||||
<source-file src="src/ios/CrashHandler.m" />
|
||||
</platform>
|
||||
</plugin>
|
12
src/ios/CrashHandler.h
Normal file
12
src/ios/CrashHandler.h
Normal file
@ -0,0 +1,12 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface CrashHandler : NSObject {
|
||||
BOOL dismissed;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
void HandleException(NSException *exception);
|
||||
void SignalHandler(int signal);
|
||||
|
||||
void RegistUncauthExceptionHandler(void);
|
181
src/ios/CrashHandler.m
Normal file
181
src/ios/CrashHandler.m
Normal file
@ -0,0 +1,181 @@
|
||||
#import "CrashHandler.h"
|
||||
//#include <libkern/OSAtomic.h>
|
||||
#include <execinfo.h>
|
||||
|
||||
NSString * const UncaughtExceptionHandlerSignalExceptionName = @"UncaughtExceptionHandlerSignalExceptionName";
|
||||
NSString * const UncaughtExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey";
|
||||
NSString * const UncaughtExceptionHandlerAddressesKey = @"UncaughtExceptionHandlerAddressesKey";
|
||||
|
||||
//volatile int32_t UncaughtExceptionCount = 0;
|
||||
//const int32_t UncaughtExceptionMaximum = 10;
|
||||
|
||||
const NSInteger UncaughtExceptionHandlerSkipAddressCount = 4;
|
||||
const NSInteger UncaughtExceptionHandlerReportAddressCount = 5;
|
||||
|
||||
@implementation CrashHandler
|
||||
|
||||
NSDateFormatter *dateFormatter;
|
||||
|
||||
+ (NSArray *)backtrace {
|
||||
void* callstack[128];
|
||||
int frames = backtrace(callstack, 128);
|
||||
char **strs = backtrace_symbols(callstack, frames);
|
||||
|
||||
int i;
|
||||
NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
|
||||
for (
|
||||
i = UncaughtExceptionHandlerSkipAddressCount;
|
||||
i < UncaughtExceptionHandlerSkipAddressCount +
|
||||
UncaughtExceptionHandlerReportAddressCount;
|
||||
i++)
|
||||
{
|
||||
[backtrace addObject:[NSString stringWithUTF8String:strs[i]]];
|
||||
}
|
||||
free(strs);
|
||||
|
||||
return backtrace;
|
||||
}
|
||||
|
||||
+ (NSString *)applicationDocumentsDirectory {
|
||||
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
|
||||
}
|
||||
|
||||
+ (NSString *)filename {
|
||||
NSString * date = [dateFormatter stringFromDate:[NSDate date]];
|
||||
long timeStamp = (long)(NSTimeInterval)([[NSDate date] timeIntervalSince1970]);
|
||||
return [NSString stringWithFormat:@"crash-%@-%ld.log", date, timeStamp];
|
||||
}
|
||||
|
||||
- (void)handleException:(NSException *)exception {
|
||||
NSLog(@" 崩溃 handleException ================================== ");
|
||||
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"错误" message:@"很抱歉,程序出现异常,即将退出." preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction *sure =[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
|
||||
dismissed = YES;
|
||||
}];
|
||||
|
||||
[alertController addAction:sure];
|
||||
|
||||
id rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
|
||||
if([rootViewController isKindOfClass:[UINavigationController class]])
|
||||
{
|
||||
rootViewController = ((UINavigationController *)rootViewController).viewControllers.firstObject;
|
||||
}
|
||||
if([rootViewController isKindOfClass:[UITabBarController class]])
|
||||
{
|
||||
rootViewController = ((UITabBarController *)rootViewController).selectedViewController;
|
||||
}
|
||||
|
||||
[rootViewController presentViewController:alertController animated:YES completion:nil];
|
||||
|
||||
CFRunLoopRef runLoop = CFRunLoopGetCurrent();
|
||||
CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
|
||||
|
||||
while (!dismissed) {
|
||||
for (NSString *mode in (__bridge NSArray *)allModes) {
|
||||
CFRunLoopRunInMode((CFStringRef)mode, 0.001, false);
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(allModes);
|
||||
|
||||
[self saveLog:exception];
|
||||
NSSetUncaughtExceptionHandler(NULL);
|
||||
|
||||
signal(SIGABRT, SIG_DFL);
|
||||
signal(SIGILL, SIG_DFL);
|
||||
signal(SIGSEGV, SIG_DFL);
|
||||
signal(SIGFPE, SIG_DFL);
|
||||
signal(SIGBUS, SIG_DFL);
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
|
||||
if ([[exception name] isEqual:UncaughtExceptionHandlerSignalExceptionName])
|
||||
{
|
||||
kill(getpid(), [[[exception userInfo] objectForKey:UncaughtExceptionHandlerSignalKey] intValue]);
|
||||
}
|
||||
else
|
||||
{
|
||||
[exception raise];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)saveLog:(NSException *)exception {
|
||||
NSLog(@"崩溃日志文件==================================");
|
||||
NSArray * arr = [exception callStackSymbols];
|
||||
NSString * reason = [exception reason]; // // 崩溃的原因 可以有崩溃的原因(数组越界,字典nil,调用未知方法...)
|
||||
NSString * name = [exception name];
|
||||
NSString * url = [NSString stringWithFormat:@"exception:%@\nreason:\n%@\ncallStackSymbols:\n%@",name,reason,[arr componentsJoinedByString:@"\n"]];
|
||||
NSString * path = [[CrashHandler applicationDocumentsDirectory] stringByAppendingPathComponent:[CrashHandler filename]];
|
||||
NSLog(@"崩溃日志文件:%@", path);
|
||||
[url writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
void HandleException(NSException *exception) {
|
||||
// int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
|
||||
// if (exceptionCount > UncaughtExceptionMaximum) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
NSArray *callStack = [CrashHandler backtrace];
|
||||
NSMutableDictionary *userInfo =
|
||||
[NSMutableDictionary dictionaryWithDictionary:[exception userInfo]];
|
||||
[userInfo
|
||||
setObject:callStack
|
||||
forKey:UncaughtExceptionHandlerAddressesKey];
|
||||
|
||||
[[[CrashHandler alloc] init]
|
||||
performSelectorOnMainThread:@selector(handleException:)
|
||||
withObject:
|
||||
[NSException
|
||||
exceptionWithName:[exception name]
|
||||
reason:[exception reason]
|
||||
userInfo:userInfo]
|
||||
waitUntilDone:YES];
|
||||
}
|
||||
|
||||
void SignalHandler(int signal) {
|
||||
// int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
|
||||
// if (exceptionCount > UncaughtExceptionMaximum) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
NSMutableDictionary *userInfo =
|
||||
[NSMutableDictionary
|
||||
dictionaryWithObject:[NSNumber numberWithInt:signal]
|
||||
forKey:UncaughtExceptionHandlerSignalKey];
|
||||
|
||||
NSArray *callStack = [CrashHandler backtrace];
|
||||
[userInfo
|
||||
setObject:callStack
|
||||
forKey:UncaughtExceptionHandlerAddressesKey];
|
||||
|
||||
[[[CrashHandler alloc] init]
|
||||
performSelectorOnMainThread:@selector(handleException:)
|
||||
withObject:
|
||||
[NSException
|
||||
exceptionWithName:UncaughtExceptionHandlerSignalExceptionName
|
||||
reason:
|
||||
[NSString stringWithFormat:
|
||||
NSLocalizedString(@"Signal %d was raised.", nil),
|
||||
signal]
|
||||
userInfo:
|
||||
[NSDictionary
|
||||
dictionaryWithObject:[NSNumber numberWithInt:signal]
|
||||
forKey:UncaughtExceptionHandlerSignalKey]]
|
||||
waitUntilDone:YES];
|
||||
}
|
||||
|
||||
void RegistUncauthExceptionHandler(void) {
|
||||
NSLog(@"崩溃日志文件============ install ======================");
|
||||
dateFormatter = [[NSDateFormatter alloc] init];
|
||||
[dateFormatter setDateFormat:@"yyyy-MM-dd-HH-mm-ss"];
|
||||
NSSetUncaughtExceptionHandler(&HandleException);
|
||||
signal(SIGABRT, SignalHandler);
|
||||
signal(SIGILL, SignalHandler);
|
||||
signal(SIGSEGV, SignalHandler);
|
||||
signal(SIGFPE, SignalHandler);
|
||||
signal(SIGBUS, SignalHandler);
|
||||
signal(SIGPIPE, SignalHandler);
|
||||
}
|
5
src/ios/CrashLogPlugin.h
Normal file
5
src/ios/CrashLogPlugin.h
Normal file
@ -0,0 +1,5 @@
|
||||
#import <Cordova/CDV.h>
|
||||
|
||||
@interface CrashLogPlugin : CDVPlugin
|
||||
|
||||
@end
|
12
src/ios/CrashLogPlugin.m
Normal file
12
src/ios/CrashLogPlugin.m
Normal file
@ -0,0 +1,12 @@
|
||||
#import "CrashHandler.h"
|
||||
#import "CrashLogPlugin.h"
|
||||
|
||||
@implementation CrashLogPlugin
|
||||
|
||||
- (void)pluginInitialize
|
||||
{
|
||||
NSLog(@"崩溃日志文件:pluginInitialize");
|
||||
RegistUncauthExceptionHandler();
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in New Issue
Block a user