flutter_file_logger 0.0.1 copy "flutter_file_logger: ^0.0.1" to clipboard
flutter_file_logger: ^0.0.1 copied to clipboard

A Flutter plugin to log messages to files.

example/lib/main.dart

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_archive/flutter_archive.dart';
import 'package:flutter_file_logger/flutter_file_logger.dart';
import 'package:intl/intl.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart' as pp;
import 'package:proper_filesize/proper_filesize.dart';
import 'package:share_plus/share_plus.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _desc = 'A Flutter plugin to log messages to files.';
  // final _privateKey =
  //     '471e607b1bb3760205f74a5e53d2764f795601e241ebc780c849e7fde1b4ce40';
  final _publicKey =
      '300330b09d9e771d6163bc53a4e23b188ac9b2f5c7150366835bce3a12b0c8d9c5ecb0b15274f12b2dffae7f4b11c3b3d340e0521e8690578f51813c93190e1e';

  final _logTimes = 10000;

  int _totalLogSize = 0;
  int _logCost = 0;

  @override
  void initState() {
    super.initState();
    _refreshTotalLogSize();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter File Logger'),
          centerTitle: true,
        ),
        body: SizedBox.expand(
          child: Column(
            children: [
              Text(_desc),
              Expanded(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    ElevatedButton(onPressed: _open, child: Text('open')),
                    ElevatedButton(onPressed: _close, child: Text('close')),
                    ElevatedButton(onPressed: _flush, child: Text('flush')),
                    ElevatedButton(onPressed: _export, child: Text('export')),
                    ElevatedButton(onPressed: _clear, child: Text('clear')),
                    ElevatedButton(
                      onPressed: () => _log(_desc),
                      child: Text('log (${_desc.length} chars)'),
                    ),
                    ElevatedButton(
                      onPressed: () => _log(_desc * 10),
                      child: Text('log (${_desc.length * 10} chars)'),
                    ),
                    Text(
                      'Total log size is ${FileSize.fromBytes(_totalLogSize)}',
                    ),
                    Text('$_logTimes logs cost ${_logCost}ms'),
                    Text(
                      'Averaging ${((_logCost).toDouble() / _logTimes)}ms per log',
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Future<void> _open() async {
    final logDir = Directory(await _logSaveDirPath());
    if (!await logDir.exists()) {
      await logDir.create(recursive: true);
    }
    await FlutterFileLogger.open(
      LogConfig(
        saveDirPath: logDir.path,
        maxCacheDays: 7,
        fileNamePrefix: 'flutter_file_log',
        publicKey: _publicKey,
      ),
    );
    await _refreshTotalLogSize();
  }

  Future<void> _close() async {
    await FlutterFileLogger.close();
    await _refreshTotalLogSize();
  }

  Future<void> _flush() async {
    await FlutterFileLogger.flush();
    await _refreshTotalLogSize();
  }

  Future<void> _clear() async {
    final logDirPath = await _logSaveDirPath();
    final logDir = Directory(logDirPath);
    if (await logDir.exists()) {
      await logDir.delete(recursive: true);
    }
    await logDir.create(recursive: true);
    await _refreshTotalLogSize();
  }

  Future<void> _export() async {
    await FlutterFileLogger.flush();
    await _refreshTotalLogSize();
    final logDirPath = await _logSaveDirPath();
    final logDir = Directory(logDirPath);
    final cacheDir = await pp.getApplicationCacheDirectory();
    final zipDirPath = p.join(cacheDir.path, 'flutter_file_log_cache');
    final zipDir = Directory(zipDirPath);
    if (await zipDir.exists()) {
      await zipDir.delete(recursive: true);
    }
    await zipDir.create(recursive: true);
    final zipFilePath = p.join(
      zipDirPath,
      'flutter_file_logs_${DateFormat('yyyy_MM_dd_HH_mm_ss_SSS', 'en-US').format(DateTime.now())}.zip',
    );
    final zipFile = File(zipFilePath);
    await ZipFile.createFromDirectory(
      sourceDir: logDir,
      zipFile: zipFile,
      recurseSubDirs: true,
    );
    final params = ShareParams(
      title: 'Export Logs',
      files: [XFile(zipFilePath)],
    );
    await SharePlus.instance.share(params);
    await zipDir.delete(recursive: true);
  }

  void _log(String msg) {
    final begin = DateTime.now();
    for (var i = 0; i < _logTimes; i++) {
      FlutterFileLogger.d('FlutterFileLogger', msg);
    }
    final end = DateTime.now();
    final cost = end.difference(begin);
    setState(() {
      _logCost = cost.inMilliseconds;
    });
    _refreshTotalLogSize();
  }

  Future<void> _refreshTotalLogSize() async {
    int totalSize = 0;
    final logDirPath = await _logSaveDirPath();
    final logDir = Directory(logDirPath);
    if (logDir.existsSync()) {
      final childFiles = logDir.listSync();
      for (var e in childFiles) {
        totalSize += e.statSync().size;
      }
    }
    setState(() {
      _totalLogSize = totalSize;
    });
  }

  Future<String> _logSaveDirPath() async {
    final rootDir = await pp.getApplicationSupportDirectory();
    return p.join(rootDir.path, 'flutter_file_logs');
  }
}