Flutter崩溃时将rout堆栈上报到服务端
一、
捕获崩溃并上传
void main() async {
FlutterError.onError = (error) {
Zone.current.handleUncaughtError(error.exception, error.stack);
};
runZonedGuarded<Future<Null>>(
() async {
await _init();
},
(error, stack) async {
String errorStack = '【${error.toString()}】 \n $stack';
errorStack = '$errorStack \n 最后访问的最多$maxNavCount个页面路径如下:\n';
String extra = await navList2String();
errorStack = '$errorStack $extra';
//自己实现
CrashUploadChannel crashUploadChannel = CrashUploadChannel();
crashUploadChannel.uploadCrash(errorStack);
},
);
}
二、
在MaterialApp中监控navigator
Widget _buildMainApp(BuildContext context) {
return MaterialApp(
navigatorObservers: [
UserNavigatorObserver(),
],
三、
user_navigator_observer.dart实现
import 'dart:collection';
import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart';
const Duration delayDuration = Duration(seconds: 2);
final maxNavCount = 20;
final _navList = ListQueue<NavEntry>();
void addNavEntry(NavEntry entry) {
if (_navList.length > maxNavCount) {
_navList.removeFirst();
}
_navList.add(entry);
}
Future<String> navList2String() async {
String result = '';
try {
// didPush那delay了[delayDuration],等最后一个push后再输出日志
await Future.delayed(delayDuration);
final list = _navList.toList();
list.sort((a, b) => a.time.compareTo(b.time));
result = list.join('\n');
} catch (e) {}
return result;
}
class NavEntry {
final String pageName;
final String action;
final DateTime time;
String extra;
NavEntry({
@required this.pageName,
@required this.action,
@required this.time,
});
@override
String toString() {
return 'Action: $action PageName: $pageName Time: $time Extra: $extra';
}
}
class UserNavigatorObserver extends NavigatorObserver {
@override
void didPush(Route route, Route previousRoute) {
try {
addNavEntry(NavEntry(
pageName: route.toString(),
action: 'didPush',
time: DateTime.now(),
));
} catch (e) {
print('$e');
}
}
@override
void didPop(Route route, Route previousRoute) {
try {
addNavEntry(NavEntry(
pageName: route.toString(),
action: 'didPop',
time: DateTime.now(),
));
} catch (e) {
print('$e');
}
}
}