| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- import 'dart:convert';
- import 'dart:io';
- import 'package:path_provider/path_provider.dart';
- import 'package:flutter_app_group_directory/flutter_app_group_directory.dart';
- import 'log/logger.dart';
- class BoostLogger {
- static const String LOG_FOLDER = 'boost_logs';
- static const String APP_LOG_FILE = 'app.json';
- static const String CORE_LOG_FILE = 'core.json';
- static const String TAG = 'BoostLogger';
- Map<String, dynamic> _currentSession = {};
- String? _logPath;
- /// 单例模式实现
- static final BoostLogger _instance = BoostLogger._internal();
- factory BoostLogger() => _instance;
- BoostLogger._internal();
- /// 获取日志目录
- Future<Directory> _getLogDirectory() async {
- if (Platform.isIOS) {
- try {
- // iOS 使用 App Group 目录
- final Directory? appGroupDirectory =
- await FlutterAppGroupDirectory.getAppGroupDirectory(
- 'group.app.xixi.nomo',
- );
- // 验证 App Group 目录是否有效
- if (appGroupDirectory != null) {
- final logDir = Directory('${appGroupDirectory.path}/$LOG_FOLDER');
- if (!await logDir.exists()) {
- await logDir.create(recursive: true);
- }
- return logDir;
- } else {
- // App Group 目录不可用,回退到应用文档目录
- log(
- TAG,
- 'App Group directory not available, falling back to documents directory',
- );
- final appDir = await getApplicationDocumentsDirectory();
- final logDir = Directory('${appDir.path}/$LOG_FOLDER');
- if (!await logDir.exists()) {
- await logDir.create(recursive: true);
- }
- return logDir;
- }
- } catch (e) {
- // 如果 App Group 出现错误,回退到应用文档目录
- log(
- TAG,
- 'Error with App Group directory: $e, falling back to documents directory',
- );
- final appDir = await getApplicationDocumentsDirectory();
- final logDir = Directory('${appDir.path}/$LOG_FOLDER');
- if (!await logDir.exists()) {
- await logDir.create(recursive: true);
- }
- return logDir;
- }
- } else {
- // Android 使用外部存储目录
- final appDir = await getExternalStorageDirectory();
- if (appDir == null) {
- throw Exception('Failed to get external storage directory');
- }
- final logDir = Directory('${appDir.path}/$LOG_FOLDER');
- if (!await logDir.exists()) {
- await logDir.create(recursive: true);
- }
- return logDir;
- }
- }
- /// 初始化日志系统
- Future<void> init() async {
- try {
- final logDir = await _getLogDirectory();
- _logPath = logDir.path;
- // 清除旧的app日志文件
- final appFile = File('${logDir.path}/$APP_LOG_FILE');
- if (await appFile.exists()) {
- await appFile.delete();
- }
- // 清除旧的内核日志文件
- final coreFile = File('${logDir.path}/$CORE_LOG_FILE');
- if (await coreFile.exists()) {
- await coreFile.delete();
- }
- // 初始化空的会话数据
- _currentSession = {};
- await _saveSession();
- } catch (e) {
- log(TAG, 'BoostLogger init error: $e');
- }
- }
- //读取历史日志
- Future<void> readHistoryLog() async {
- try {
- final logDir = await _getLogDirectory();
- _logPath = logDir.path;
- getCurrentSession();
- } catch (e) {
- log(TAG, 'BoostLogger readHistoryLog error: $e');
- }
- }
- /// 设置整个部分的数据
- Future<void> setSection(String section, Map<String, dynamic> data) async {
- try {
- _currentSession[section] = data;
- await _saveSession();
- } catch (e) {
- log(TAG, 'BoostLogger setSection error: $e');
- }
- }
- /// 设置整个部分的数据
- Future<void> setSectionObj(String section, dynamic data) async {
- try {
- _currentSession[section] = data;
- await _saveSession();
- } catch (e) {
- log(TAG, 'BoostLogger setSectionObj error: $e');
- }
- }
- /// 更新部分中的特定字段
- Future<void> updateField(String section, String field, dynamic value) async {
- try {
- final sectionData = _currentSession[section] as Map<String, dynamic>;
- sectionData[field] = value;
- _currentSession[section] = sectionData;
- await _saveSession();
- } catch (e) {
- log(TAG, 'BoostLogger updateField error: $e');
- }
- }
- /// 向数组添加数据
- Future<void> appendToArray(
- String section,
- String arrayField,
- Map<String, dynamic> data,
- ) async {
- try {
- final sectionData =
- _currentSession[section] as Map<String, dynamic>? ?? {};
- final array = sectionData[arrayField] as List<dynamic>? ?? [];
- array.add(data);
- sectionData[arrayField] = array;
- _currentSession[section] = sectionData;
- await _saveSession();
- } catch (e) {
- log(TAG, 'BoostLogger appendToArray error: $e');
- }
- }
- /// 保存会话数据到文件
- Future<void> _saveSession() async {
- if (_logPath == null) return;
- try {
- final file = File('$_logPath/$APP_LOG_FILE');
- // 使用 writeAsStringSync 确保写入完成
- final jsonString = const JsonEncoder.withIndent(
- ' ',
- ).convert(_currentSession);
- await file.writeAsString(jsonString, flush: true);
- // 验证文件写入
- final content = await file.readAsString();
- final savedData = jsonDecode(content) as Map<String, dynamic>;
- log(TAG, 'BoostLogger verify saved data: $savedData');
- } catch (e) {
- log(TAG, 'BoostLogger save session error: $e');
- }
- }
- /// 获取当前会话数据
- Map<String, dynamic> getCurrentSession() {
- try {
- // 从文件读取最新数据
- final file = File('$_logPath/$APP_LOG_FILE');
- if (file.existsSync()) {
- final content = file.readAsStringSync();
- _currentSession = jsonDecode(content) as Map<String, dynamic>;
- }
- return Map<String, dynamic>.from(_currentSession);
- } catch (e) {
- log(TAG, 'BoostLogger getCurrentSession error: $e');
- return {};
- }
- }
- /// 获取日志文件路径
- Future<String?> getAppLogFilePath() async {
- return _logPath != null ? '$_logPath/$APP_LOG_FILE' : null;
- }
- /// 获取核心日志文件路径
- Future<String?> getCoreLogFilePath() async {
- return _logPath != null ? '$_logPath/$CORE_LOG_FILE' : null;
- }
- /// 清理资源
- Future<void> release() async {
- try {
- // 检查 _currentSession 是否为空
- if (_currentSession.isEmpty) {
- return;
- }
- await _saveSession();
- _currentSession.clear();
- } catch (e) {
- log(TAG, 'BoostLogger release error: $e');
- }
- }
- }
|