mirror of
https://github.com/shuto-cn/CrashLog.git
synced 2024-10-06 07:42:22 +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="http://apache.org/cordova/ns/plugins/1.0"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<name>CrashLog</name>
|
<name>CrashLog</name>
|
||||||
<!-- js-module name="CrashLog" src="www/crash-log.js">
|
|
||||||
<clobbers target="CrashLog" />
|
|
||||||
</js-module -->
|
|
||||||
<platform name="android">
|
<platform name="android">
|
||||||
<config-file parent="/*" target="res/xml/config.xml">
|
<config-file parent="/*" target="res/xml/config.xml">
|
||||||
<feature name="CrashLog">
|
<feature name="CrashLog">
|
||||||
@ -13,11 +10,22 @@
|
|||||||
<param name="onload" value="true" />
|
<param name="onload" value="true" />
|
||||||
</feature>
|
</feature>
|
||||||
</config-file>
|
</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" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
</config-file>
|
</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/CrashLogPlugin.java" target-dir="src/cn/shuto/crash" />
|
||||||
<source-file src="src/android/cn/shuto/crash/CrashHandler.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>
|
||||||
|
<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>
|
</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