Skip to content

Commit 8a0caa0

Browse files
docs(crashlytics): Use PlatformDispatcher.instance.onError for async errors. Update Crashlytics example app to use "flutterfire-e2e-tests" project. (#9669)
Co-authored-by: Kevin Cheung <kevinthecheung@users.noreply.github.com>
1 parent 02d7148 commit 8a0caa0

File tree

12 files changed

+556
-100
lines changed

12 files changed

+556
-100
lines changed

docs/crashlytics/_customize-crash-reports.md

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,57 +20,62 @@ to disk to be sent along with the next fatal report or when the app restarts.
2020

2121
## Report uncaught exceptions {: #report-uncaught-exceptions}
2222

23-
You can automatically catch all errors that are thrown within the Flutter
23+
You can automatically catch all "fatal" errors that are thrown within the Flutter
2424
framework by overriding `FlutterError.onError` with
25-
`FirebaseCrashlytics.instance.recordFlutterFatalError`:
25+
`FirebaseCrashlytics.instance.recordFlutterFatalError`. Alternatively,
26+
to also catch "non-fatal" exceptions, override `FlutterError.onError` with `FirebaseCrashlytics.instance.recordFlutterError`:
2627

2728
```dart
2829
void main() async {
2930
WidgetsFlutterBinding.ensureInitialized();
3031
3132
await Firebase.initializeApp();
32-
33-
// Pass all uncaught errors from the framework to Crashlytics.
34-
FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterFatalError;
33+
bool weWantFatalErrorRecording = true;
34+
FlutterError.onError = (errorDetails) {
35+
if(weWantFatalErrorRecording){
36+
FirebaseCrashlytics.instance.recordFlutterFatalError(errorDetails);
37+
} else {
38+
FirebaseCrashlytics.instance.recordFlutterError(errorDetails);
39+
}
40+
};
3541
3642
runApp(MyApp());
3743
}
3844
```
3945

40-
### Zoned errors {: #zoned-errors}
4146

42-
Not all errors are caught by Flutter. Sometimes, errors are instead caught by
43-
`Zones`. A common case where relying on Flutter to catch errors would not be
44-
enough is when an exception happens inside the `onPressed` handler of a button:
47+
### Asynchronous errors {: #asynchronous-errors}
48+
49+
Asynchronous errors are not caught by the Flutter framework:
4550

4651
```dart
4752
ElevatedButton(
48-
onPressed: () {
53+
onPressed: () async {
4954
throw Error();
5055
}
5156
...
5257
)
5358
```
5459

55-
To catch such errors, you can use `runZonedGuarded`:
60+
To catch such errors, you can use the `PlatformDispatcher.instance.onError` handler:
5661

5762
```dart
58-
void main() async {
59-
runZonedGuarded<Future<void>>(() async {
63+
Future<void> main() async {
6064
WidgetsFlutterBinding.ensureInitialized();
6165
await Firebase.initializeApp();
62-
// The following lines are the same as previously explained in "Handling uncaught errors"
63-
FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterFatalError;
64-
66+
FlutterError.onError = (errorDetails) {
67+
FirebaseCrashlytics.instance.recordFlutterFatalError(errorDetails);
68+
};
69+
// Pass all uncaught asynchronous errors that aren't handled by the Flutter framework to Crashlytics
70+
PlatformDispatcher.instance.onError = (error, stack) {
71+
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
72+
return true;
73+
};
6574
runApp(MyApp());
66-
}, (error, stack) => FirebaseCrashlytics.instance.recordError(error, stack, fatal: true));
75+
6776
}
6877
```
6978

70-
Note: You must call `WidgetsFlutterBinding.ensureInitialized()` _inside_
71-
`runZonedGuarded`. Error handling wouldn’t work if
72-
`WidgetsFlutterBinding.ensureInitialized()` was called from the outside.
73-
7479
### Errors outside of Flutter {: #errors-outside-flutter}
7580

7681
To catch errors that happen outside of the Flutter context, install an error
@@ -108,6 +113,9 @@ await FirebaseCrashlytics.instance.recordError(
108113
stackTrace,
109114
reason: 'a non-fatal error'
110115
);
116+
117+
// Or you can use:
118+
await FirebaseCrashlytics.instance.recordFlutterError(errorDetails);
111119
```
112120

113121
You may also wish to log further information about the error which is possible

docs/crashlytics/_get-started.md

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -66,29 +66,31 @@ void main() async {
6666
6767
await Firebase.initializeApp();
6868
69-
// Pass all uncaught errors from the framework to Crashlytics.
69+
// Pass all uncaught "fatal" errors from the framework to Crashlytics
7070
FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterFatalError;
7171
7272
runApp(MyApp());
7373
}
7474
```
7575
76-
If you're using zones, instrumenting the zone’s error handler will catch errors
77-
that aren't caught by the Flutter framework (for example, in a button’s
78-
`onPressed` handler):
76+
To catch asynchronous errors that aren't handled by the Flutter framework, use
77+
`PlatformDispatcher.instance.onError`:
78+
7979

8080
```dart
81-
void main() async {
82-
runZonedGuarded<Future<void>>(() async {
81+
Future<void> main() async {
8382
WidgetsFlutterBinding.ensureInitialized();
8483
await Firebase.initializeApp();
85-
86-
FlutterError.onError =
87-
FirebaseCrashlytics.instance.recordFlutterFatalError;
88-
84+
FlutterError.onError = (errorDetails) {
85+
FirebaseCrashlytics.instance.recordFlutterFatalError(errorDetails);
86+
};
87+
// Pass all uncaught asynchronous errors that aren't handled by the Flutter framework to Crashlytics
88+
PlatformDispatcher.instance.onError = (error, stack) {
89+
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
90+
return true;
91+
};
8992
runApp(MyApp());
90-
}, (error, stack) =>
91-
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true));
93+
9294
}
9395
```
9496

0 commit comments

Comments
 (0)