flutter_vault_logger 0.1.0
flutter_vault_logger: ^0.1.0 copied to clipboard
Secure, encrypted on-device crash log storage with export/import and duplicate detection. Drop-in Flutter package.
example/lib/main.dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_vault_logger/flutter_vault_logger.dart';
import 'package:hive_flutter/hive_flutter.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Hive.initFlutter();
await CrashLogService.init(
const VaultLoggerConfig(
encryptionKey: '12345678901234567890123456789012',
encryptionIV: '1234567890123456',
fileExtension: 'vaultlog',
maxLogCount: 200,
expirationMinutes: 60,
),
);
runApp(const ExampleApp());
}
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Vault Logger Example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
),
home: const LoggerHomePage(),
);
}
}
class LoggerHomePage extends StatefulWidget {
const LoggerHomePage({super.key});
@override
State<LoggerHomePage> createState() => _LoggerHomePageState();
}
class _LoggerHomePageState extends State<LoggerHomePage> {
String _status = 'Ready';
String? _lastExportPath;
List<CrashLogModel> get _logs => CrashLogService.getLogs();
Future<void> _createTestError() async {
try {
throw StateError('Example crash at ${DateTime.now().toIso8601String()}');
} catch (e, st) {
await CrashLogService.logError(e, st, 'LoggerHomePage._createTestError');
setState(() {
_status = 'Test error captured';
});
}
}
Future<void> _exportLogs() async {
try {
final path = await CrashLogService.exportEncryptedLogs();
setState(() {
_lastExportPath = path;
_status = 'Exported logs to: $path';
});
} catch (e) {
setState(() {
_status = 'Export failed: $e';
});
}
}
Future<void> _importLastExport() async {
final path = _lastExportPath;
if (path == null || !File(path).existsSync()) {
setState(() {
_status = 'No exported file found yet';
});
return;
}
try {
final imported = await CrashLogService.importEncryptedLogs(path);
await CrashLogService.saveReport(
'Imported ${DateTime.now().toIso8601String()}',
imported,
);
setState(() {
_status = 'Imported ${imported.length} log(s) and saved report';
});
} catch (e) {
setState(() {
_status = 'Import failed: $e';
});
}
}
Future<void> _clearLogs() async {
await CrashLogService.clearLogs();
setState(() {
_status = 'Cleared local logs';
});
}
@override
Widget build(BuildContext context) {
final logs = _logs;
return Scaffold(
appBar: AppBar(title: const Text('flutter_vault_logger example')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(_status),
const SizedBox(height: 12),
Wrap(
spacing: 8,
runSpacing: 8,
children: [
ElevatedButton(
onPressed: _createTestError,
child: const Text('Log test error'),
),
ElevatedButton(
onPressed: _exportLogs,
child: const Text('Export logs'),
),
ElevatedButton(
onPressed: _importLastExport,
child: const Text('Import last export'),
),
ElevatedButton(
onPressed: _clearLogs,
child: const Text('Clear logs'),
),
],
),
const SizedBox(height: 16),
Text('Current log count: ${logs.length}'),
const SizedBox(height: 8),
Expanded(
child: logs.isEmpty
? const Center(child: Text('No logs captured yet'))
: ListView.builder(
itemCount: logs.length,
itemBuilder: (context, index) {
final log = logs[index];
return ListTile(
dense: true,
title: Text(
log.error,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
subtitle: Text(log.timestamp.toIso8601String()),
);
},
),
),
],
),
),
);
}
}