crashlog 1.2.0
crashlog: ^1.2.0 copied to clipboard
A comprehensive Flutter package for capturing errors, console logs, and screenshots with cross-platform support and dev report functionality.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:crashlog/crashlog.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize Crashlog with full configuration
await Crashlog.init(
enabled: true,
enableScreenshots: true,
autoOpenOnError: false,
maxLogs: 50,
maxConsoleLogs: 1000,
logRetentionDays: 7,
showDeviceInfo: true,
logFileName: "crash_logs.json",
consoleLogFileName: "debug_logs.json",
screenshotFolder: "crash_screenshots",
);
runApp(const CrashlogExampleApp());
}
class CrashlogExampleApp extends StatelessWidget {
const CrashlogExampleApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Crashlog Example',
theme: ThemeData(
primarySwatch: Colors.blue,
useMaterial3: true,
),
home: ErrorRecorderWrapper(
child: const ExampleHomePage(),
),
);
}
}
class ExampleHomePage extends StatefulWidget {
const ExampleHomePage({Key? key}) : super(key: key);
@override
State<ExampleHomePage> createState() => _ExampleHomePageState();
}
class _ExampleHomePageState extends State<ExampleHomePage> {
int _counter = 0;
final ScrollController _scrollController = ScrollController();
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
// Simulate different types of crashes
void _simulateNullPointerError() {
String? nullString;
// This will throw a null pointer exception
Crashlog.logInfo('About to access null string length', source: 'Demo');
final length = nullString!.length; // This will crash
debugPrint('Length: $length');
}
void _simulateIndexOutOfBounds() {
final list = [1, 2, 3];
Crashlog.logWarning('About to access invalid index', source: 'Demo');
final value = list[10]; // This will crash
debugPrint('Value: $value');
}
void _simulateAsyncError() async {
Crashlog.logInfo('Starting async operation that will fail', source: 'Demo');
await Future.delayed(const Duration(seconds: 1));
throw Exception('Simulated async error for testing');
}
void _simulateCustomError() {
try {
throw FormatException('Custom format exception for testing');
} catch (e, stackTrace) {
Crashlog.logError('Caught custom error: $e',
stackTrace: stackTrace, source: 'Demo');
}
}
void _generateConsoleLogs() {
Crashlog.logInfo('This is an info message', source: 'Demo');
Crashlog.logWarning('This is a warning message', source: 'Demo');
Crashlog.logDebug('This is a debug message', source: 'Demo');
Crashlog.log('This is a custom level message',
level: 'custom', source: 'Demo');
// Also use regular print and debugPrint
print('Regular print statement from example');
debugPrint('Debug print statement from example');
}
void _incrementCounter() {
setState(() {
_counter++;
});
Crashlog.logInfo('Counter incremented to $_counter', source: 'Counter');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text('Crashlog Example'),
actions: [
ErrorRecorderIconButton(
tooltip: 'Open Dev Report',
color: Colors.white,
),
],
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
// Status Card
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Crashlog Status',
style:
TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Text('Initialized: ${Crashlog.isInitialized}'),
Text('Enabled: ${Crashlog.isEnabled}'),
Text(
'Screenshots: ${Crashlog.config?.enableScreenshots ?? false}'),
Text('Max Logs: ${Crashlog.config?.maxLogs ?? 0}'),
Text(
'Max Console Logs: ${Crashlog.config?.maxConsoleLogs ?? 0}'),
],
),
),
),
const SizedBox(height: 16),
// Counter Section
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
const Text(
'Counter Demo',
style:
TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Text(
'Count: $_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
const SizedBox(height: 8),
ElevatedButton(
onPressed: _incrementCounter,
child: const Text('Increment Counter'),
),
],
),
),
),
const SizedBox(height: 16),
// Error Simulation Section
Expanded(
child: Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Error Simulation',
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
const Text(
'Test different types of errors and logging:',
style: TextStyle(fontSize: 14, color: Colors.grey),
),
const SizedBox(height: 16),
Expanded(
child: Scrollbar(
controller: _scrollController,
child: ListView(
controller: _scrollController,
children: [
_buildActionButton(
'Null Pointer Exception',
'Simulates accessing null value',
Icons.error,
Colors.red,
_simulateNullPointerError,
),
_buildActionButton(
'Index Out of Bounds',
'Simulates array index error',
Icons.warning,
Colors.orange,
_simulateIndexOutOfBounds,
),
_buildActionButton(
'Async Error',
'Simulates asynchronous error',
Icons.timer,
Colors.purple,
_simulateAsyncError,
),
_buildActionButton(
'Custom Error',
'Logs a custom caught error',
Icons.build,
Colors.blue,
_simulateCustomError,
),
_buildActionButton(
'Generate Console Logs',
'Creates various console log entries',
Icons.terminal,
Colors.green,
_generateConsoleLogs,
),
_buildActionButton(
'Clear All Logs',
'Removes all stored logs',
Icons.clear_all,
Colors.grey,
() => Crashlog.clearAllLogs(),
),
],
),
),
),
],
),
),
),
),
],
),
),
floatingActionButton: const ErrorRecorderButton(
icon: Icons.bug_report,
color: Colors.red,
),
);
}
Widget _buildActionButton(
String title,
String description,
IconData icon,
Color color,
VoidCallback onPressed,
) {
return Card(
margin: const EdgeInsets.symmetric(vertical: 4),
child: ListTile(
leading: Icon(icon, color: color),
title: Text(title),
subtitle: Text(description),
trailing: ElevatedButton(
onPressed: onPressed,
style: ElevatedButton.styleFrom(
backgroundColor: color,
foregroundColor: Colors.white,
),
child: const Text('Test'),
),
),
);
}
}
// Additional demo screen to show navigation and more features
class SecondScreen extends StatelessWidget {
const SecondScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Second Screen'),
actions: [
ErrorRecorderIconButton(),
],
),
body: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'This is a second screen to demonstrate',
style: TextStyle(fontSize: 18),
),
Text(
'that Crashlog works across navigation.',
style: TextStyle(fontSize: 18),
),
SizedBox(height: 32),
ErrorRecorderInlineButton(
label: 'Open Dev Report',
icon: Icons.bug_report,
),
],
),
),
);
}
}