I'm trying to catch all unhandled exceptions in a Flutter app so I can sent it to a crash reporter. There are instructions on how to do this in the Flutter docs. I followed those, and added two bits of code to my app to catch exceptions:
Catch Dart errors by wrapping runApp
in runZoned
:
runZoned<Future<void>>(
() async {
runApp(MyApp());
},
onError: (dynamic error, StackTrace stackTrace) {
print("=================== CAUGHT DART ERROR");
// Send report
},
);
Catch flutter errors by setting FlutterError.onError
:
FlutterError.onError = (FlutterErrorDetails details) {
print("=================== CAUGHT FLUTTER ERROR");
// Send report
};
However, when I test this at runtime by throwing an exception from a button:
throw Exception("Just testing");
The exception appears in the console:
════════ Exception Caught By gesture ═══════════════════════════════════════════════════════════════ The following _Exception was thrown while handling a gesture: Exception: Just testing When the exception was thrown, this was the stack:
... etc
But I see no sign of my print statements (CAUGHT DART ERROR or CAUGHT FLUTTER ERROR), and setting breakpoints on those lines never seems to hit, so I think my exception handling code isn't catching it. Am I missing something?
Here's a minimal reproducible example (click the button, which throws an exception, but it's not caught as expected):
import 'dart:async';
import 'package:flutter/material.dart';
void main() =>
runZoned<Future<void>>(
() async {
runApp(MyApp());
},
onError: (dynamic error, StackTrace stackTrace) {
print("=================== CAUGHT DART ERROR");
// Send report
// NEVER REACHES HERE - WHY?
},
);
class MyApp extends StatefulWidget {
// This widget is the root of your application.
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
// This captures errors reported by the FLUTTER framework.
FlutterError.onError = (FlutterErrorDetails details) {
print("=================== CAUGHT FLUTTER ERROR");
// Send report
// NEVER REACHES HERE - WHY?
};
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: RaisedButton(
child: Text("Throw exception"),
onPressed: () {
throw Exception("This is a test exception");
},
),
),
),
);
}
}