1
0
mirror of https://github.com/flutter/samples.git synced 2025-11-10 14:58:34 +00:00

Fix crashlytics in game_template (#1998)

This commit is contained in:
Filip Hracek
2023-08-31 03:37:49 +02:00
committed by GitHub
parent b0f2a6a86d
commit 612cf191d0
5 changed files with 38 additions and 179 deletions

View File

@@ -5,9 +5,12 @@
// Uncomment the following lines when enabling Firebase Crashlytics
// import 'dart:io';
// import 'package:firebase_core/firebase_core.dart';
// import 'package:firebase_crashlytics/firebase_crashlytics.dart';
// import 'package:flutter/foundation.dart';
// import 'firebase_options.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'dart:developer' as dev;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:go_router/go_router.dart';
@@ -17,7 +20,6 @@ import 'package:provider/provider.dart';
import 'src/ads/ads_controller.dart';
import 'src/app_lifecycle/app_lifecycle.dart';
import 'src/audio/audio_controller.dart';
import 'src/crashlytics/crashlytics.dart';
import 'src/games_services/games_services.dart';
import 'src/games_services/score.dart';
import 'src/in_app_purchase/in_app_purchase.dart';
@@ -38,33 +40,45 @@ import 'src/style/snack_bar.dart';
import 'src/win_game/win_game_screen.dart';
Future<void> main() async {
// To enable Firebase Crashlytics, uncomment the following lines and
// the import statements at the top of this file.
// Subscribe to log messages.
Logger.root.onRecord.listen((record) {
dev.log(
record.message,
time: record.time,
level: record.level.value,
name: record.loggerName,
zone: record.zone,
error: record.error,
stackTrace: record.stackTrace,
);
});
WidgetsFlutterBinding.ensureInitialized();
// TODO: To enable Firebase Crashlytics, uncomment the following line.
// See the 'Crashlytics' section of the main README.md file for details.
FirebaseCrashlytics? crashlytics;
// if (!kIsWeb && (Platform.isIOS || Platform.isAndroid)) {
// try {
// WidgetsFlutterBinding.ensureInitialized();
// await Firebase.initializeApp(
// options: DefaultFirebaseOptions.currentPlatform,
// );
// crashlytics = FirebaseCrashlytics.instance;
//
// FlutterError.onError = (errorDetails) {
// FirebaseCrashlytics.instance.recordFlutterFatalError(errorDetails);
// };
//
// // Pass all uncaught asynchronous errors
// // that aren't handled by the Flutter framework to Crashlytics.
// PlatformDispatcher.instance.onError = (error, stack) {
// FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
// return true;
// };
// } catch (e) {
// debugPrint("Firebase couldn't be initialized: $e");
// }
// }
await guardWithCrashlytics(
guardedMain,
crashlytics: crashlytics,
);
}
/// Without logging and crash reporting, this would be `void main()`.
void guardedMain() {
WidgetsFlutterBinding.ensureInitialized();
_log.info('Going full screen');
SystemChrome.setEnabledSystemUIMode(
SystemUiMode.edgeToEdge,

View File

@@ -1,103 +0,0 @@
// Copyright 2022, the Flutter project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:isolate';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:logging/logging.dart';
/// Runs [mainFunction] in a guarded [Zone].
///
/// If a non-null [FirebaseCrashlytics] instance is provided through
/// [crashlytics], then all errors will be reported through it.
///
/// These errors will also include latest logs from anywhere in the app
/// that use `package:logging`.
Future<void> guardWithCrashlytics(
void Function() mainFunction, {
required FirebaseCrashlytics? crashlytics,
}) async {
// Running the initialization code and [mainFunction] inside a guarded
// zone, so that all errors (even those occurring in callbacks) are
// caught and can be sent to Crashlytics.
await runZonedGuarded<Future<void>>(() async {
if (kDebugMode) {
// Log more when in debug mode.
Logger.root.level = Level.FINE;
}
// Subscribe to log messages.
Logger.root.onRecord.listen((record) {
final message = '${record.level.name}: ${record.time}: '
'${record.loggerName}: '
'${record.message}';
debugPrint(message);
// Add the message to the rotating Crashlytics log.
crashlytics?.log(message);
if (record.level >= Level.SEVERE) {
crashlytics?.recordError(message, filterStackTrace(StackTrace.current),
fatal: true);
}
});
// Pass all uncaught errors from the framework to Crashlytics.
if (crashlytics != null) {
WidgetsFlutterBinding.ensureInitialized();
FlutterError.onError = crashlytics.recordFlutterFatalError;
}
if (!kIsWeb) {
// To catch errors outside of the Flutter context, we attach an error
// listener to the current isolate.
Isolate.current.addErrorListener(RawReceivePort((dynamic pair) async {
final errorAndStacktrace = pair as List<dynamic>;
await crashlytics?.recordError(
errorAndStacktrace.first, errorAndStacktrace.last as StackTrace?,
fatal: true);
}).sendPort);
}
// Run the actual code.
mainFunction();
}, (error, stack) {
// This sees all errors that occur in the runZonedGuarded zone.
debugPrint('ERROR: $error\n\n'
'STACK:$stack');
crashlytics?.recordError(error, stack, fatal: true);
});
}
/// Takes a [stackTrace] and creates a new one, but without the lines that
/// have to do with this file and logging. This way, Crashlytics won't group
/// all messages that come from this file into one big heap just because
/// the head of the StackTrace is identical.
///
/// See this:
/// https://stackoverflow.com/questions/47654410/how-to-effectively-group-non-fatal-exceptions-in-crashlytics-fabrics.
@visibleForTesting
StackTrace filterStackTrace(StackTrace stackTrace) {
try {
final lines = stackTrace.toString().split('\n');
final buf = StringBuffer();
for (final line in lines) {
if (line.contains('crashlytics.dart') ||
line.contains('_BroadcastStreamController.java') ||
line.contains('logger.dart')) {
continue;
}
buf.writeln(line);
}
return StackTrace.fromString(buf.toString());
} catch (e) {
debugPrint('Problem while filtering stack trace: $e');
}
// If there was an error while filtering,
// return the original, unfiltered stack track.
return stackTrace;
}