Flutter日志发送插件send_log的使用

Flutter日志发送插件send_log的使用

发送日志插件send_log

pub package

send_log 插件提供了一种简单直接的日志支持,并通过电子邮件发送。其主要用途是便于收集日志数据,让用户在寻求帮助时能够将这些日志发送到支持邮箱。

日志记录方式如下:

  • 调试模式:在Flutter(带颜色的行)和Logcat控制台中。
  • 发布/性能模式:记录到日志文件中(也可以在调试模式下选择)。

当达到指定的最大文件大小时,日志会轮转到指定数量的文件中。与其它日志解决方案不同的是,此插件在每次写入后都会关闭并刷新日志文件。虽然这降低了效率,但使得可以从不同的位置(如Dart端和底层平台代码)写入同一个日志文件成为可能。

该模块支持将当前日志文件打包成ZIP存档并通过电子邮件发送。其主要用途是支持应用设置页面中的“请求帮助”选项,用户可以将日志作为支持请求的附件发送。

从Dart代码中记录日志

main()函数中调用构造函数:

void main() async {
  SendLogger(
    /// 此名称将在日志行中出现,作为发送者,方便在Logcat中识别或过滤。
    'YourAppName',
    /// 保留的轮转日志文件数量。默认为3。
    keepRotateCount: 5,
    /// 文件大小限制,超过该大小将生成新的日志文件。默认为10MB。
    rotateAtSizeBytes: 50 * 1024 * 1024,
    /// 轮转检查频率。默认为10分钟。
    rotateCheckInterval: const Duration(minutes: 10),
    /// 是否将调试日志发送到控制台(false)或文件(true)。默认为false。
    /// 发布和性能模式总是发送到文件。
    logFileInDebugMode: true,
  );
  runApp(...);
}

一旦构造函数被调用,你可以在代码的任何地方使用以下函数:

logInfo(String prefix, Object? message, [Object? error, StackTrace? stackTrace]);
logDebug(String prefix, Object? message, [Object? error, StackTrace? stackTrace]);
logWarning(String prefix, Object? message, [Object? error, StackTrace? stackTrace]);
logError(String prefix, Object? message, [Object? error, StackTrace? stackTrace]);
  • prefix 将附加到消息之前。
  • message 可以是一个字符串或任何具有toString()方法的对象。
  • error(实际上是一个ExceptionError)和stackTrace在发布模式下会被抑制,在其他模式下打印。

还有一个方便的方法可以帮助打印格式化的十六进制转储。它需要一个整数列表(可以是Uint8List):

logHexDump(String prefix, Object? message, List<int> data, {int rowSize = 16, bool showAscii = true});

可以通过使用常见的Level值随时更改所需的日志级别:

setLogLevel(Level.FINE);

从平台代码中记录日志

为了从平台代码中记录日志,请确保首先使用上下文调用init()。通常可以在活动的onCreate()函数中调用。

import hu.co.tramontana.sendlog.*

override fun onCreate(savedInstanceState: Bundle?) {
  Log.init(this)
  super.onCreate(savedInstanceState)
}

从此之后,你可以使用等效的日志函数:

Log.info(prefix: String, message: Any?, error: Throwable? = null)
Log.debug(prefix: String, message: Any?, error: Throwable? = null)
Log.warning(prefix: String, message: Any?, error: Throwable? = null)
Log.error(prefix: String, message: Any?, error: Throwable? = null)
Log.hexDump(prefix: String, message: Any?, data: IntArray, rowSize: Int = 16, showAscii: Boolean = true)
  • prefix 将附加到消息之前。
  • message 可以是一个字符串或任何具有toString()方法的对象。
  • error 在发布模式下会被抑制,其他模式下则打印。

发送日志

可以通过以下方式启动日志发送:

await SendLogger.launchEmailLog('YourAppName', 'sendlog@example.com', 'message body');

这将调用用户选择的邮件应用程序,主题为"Log (YourAppName)",收件人地址和初始邮件正文已填充。插件不会发送邮件,这取决于用户的选择。它仅启动邮件并将压缩的日志文件附加。但是,它会返回一个逻辑值,您可以根据此值决定向用户展示成功还是失败的消息。

Android上的警告

如果您计划在应用中使用自己的文件提供器,请确保两个文件提供器(您的和send_log中的)不冲突。在您的清单文件中添加以下内容:

<provider
  android:name="hu.co.tramontana.sendlog.SendLogFileProvider"
  android:authorities="hu.co.tramontana.sendlog.logprovider"
  android:exported="false"
  android:grantUriPermissions="true"
  tools:replace="android:authorities">
  <meta-data
    android:name="android.support.FILE_PROVIDER_PATHS"
    android:resource="@xml/sendlog_paths"
    tools:replace="android:resource" />
</provider>

其中:

  • 保持原始名称和权限,
  • 告诉编译器不要担心替换原始数据,
  • 并不要忘记将原始sendlog_paths.xml文件提升到您的res/xml文件夹中。

状态

该插件已在多个发布的Android应用中使用,用户经常且成功地通过它发送支持请求。尽管iOS尚未经过充分测试,但代码应该是可用的。欢迎进行测试和报告,以及在iOS和其他平台上提交PR。

支持

如果您喜欢这个包,请考虑支持它。

Buy Me A Book


示例代码

import 'package:flutter/material.dart';
import 'package:send_log/send_log.dart';

void main() {
  SendLogger(
    MyApp.APP_TITLE,
    // logFileInDebugMode: true,
  );
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  static const String APP_TITLE = 'Send Log Demo';

  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: MyApp.APP_TITLE,
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const MyHomePage(),
    );
  }
}

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

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<String> attachments = [];
  bool isHTML = false;
  final recipientController = TextEditingController(text: 'sendlog@example.com');
  final subjectController = TextEditingController(text: 'Test');
  final bodyController = TextEditingController(text: 'Mail body.');

  [@override](/user/override)
  void initState() {
    super.initState();

    Future.delayed(Duration(seconds: 3)).then((_) {
      logDebug('test', 'initState');
      logInfo('test', 'initState');
      logWarning('test', 'initState');
      logError('test', 'initState');
    });
  }

  Future<void> send() async {
    logInfo('test', 'send');
    String result = '';
    try {
      await SendLogger.launchEmailLog(subjectController.text, recipientController.text, bodyController.text);
      result = 'success';
    } catch (error) {
      result = error.toString();
    }

    if (mounted)
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text(result)),
      );
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(MyApp.APP_TITLE),
        actions: [
          IconButton(
            icon: const Icon(Icons.send),
            onPressed: send,
          )
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: TextField(
                controller: recipientController,
                decoration: const InputDecoration(border: OutlineInputBorder(), labelText: 'Recipient'),
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: TextField(
                controller: subjectController,
                decoration: const InputDecoration(labelText: 'Subject', border: OutlineInputBorder()),
              ),
            ),
            Expanded(
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: TextField(
                  controller: bodyController,
                  maxLines: null,
                  expands: true,
                  textAlignVertical: TextAlignVertical.top,
                  decoration: const InputDecoration(labelText: 'Body', border: OutlineInputBorder()),
                ),
              ),
            ),
            CheckboxListTile(
              contentPadding: const EdgeInsets.symmetric(vertical: 0.0, horizontal: 8.0),
              title: const Text('HTML'),
              onChanged: (bool? value) {
                if (value != null) {
                  setState(() => isHTML = value);
                }
              },
              value: isHTML,
            ),
          ],
        ),
      ),
    );
  }
}

更多关于Flutter日志发送插件send_log的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter日志发送插件send_log的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


send_log 是一个用于 Flutter 的日志发送插件,它允许你将应用程序的日志发送到远程服务器或其他目标位置。这对于调试、监控和记录应用程序的行为非常有用。

安装 send_log 插件

首先,你需要在 pubspec.yaml 文件中添加 send_log 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  send_log: ^1.0.0  # 请使用最新版本

然后,运行 flutter pub get 来安装插件。

使用 send_log 插件

以下是如何在 Flutter 项目中使用 send_log 插件的基本步骤:

1. 导入插件

import 'package:send_log/send_log.dart';

2. 初始化 send_log

在应用程序的入口点(通常是 main.dart 文件中的 main 函数)初始化 send_log

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 初始化 send_log
  await SendLog.initialize(
    url: 'https://your-server.com/logs', // 日志发送的目标URL
    headers: {
      'Authorization': 'Bearer your_token', // 如果需要,可以添加请求头
    },
  );

  runApp(MyApp());
}

3. 发送日志

在你的应用程序中,你可以使用 SendLog.send 方法来发送日志:

void someFunction() {
  // 发送一条日志
  SendLog.send('This is a log message');

  // 你也可以发送自定义的日志数据
  SendLog.send({
    'message': 'Custom log message',
    'level': 'INFO',
    'timestamp': DateTime.now().toIso8601String(),
  });
}

4. 配置日志级别

你可以设置日志级别,以便只发送特定级别的日志:

SendLog.setLevel(LogLevel.INFO); // 只发送INFO级别及以上的日志

5. 处理错误

你可以通过设置 onError 回调来处理日志发送过程中可能出现的错误:

SendLog.onError = (error) {
  print('Failed to send log: $error');
};

示例代码

以下是一个完整的示例,展示了如何在 Flutter 应用程序中使用 send_log 插件:

import 'package:flutter/material.dart';
import 'package:send_log/send_log.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 初始化 send_log
  await SendLog.initialize(
    url: 'https://your-server.com/logs',
    headers: {
      'Authorization': 'Bearer your_token',
    },
  );

  // 设置日志级别
  SendLog.setLevel(LogLevel.INFO);

  // 处理错误
  SendLog.onError = (error) {
    print('Failed to send log: $error');
  };

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Send Log Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () {
              // 发送一条日志
              SendLog.send('Button pressed at ${DateTime.now()}');
            },
            child: Text('Send Log'),
          ),
        ),
      ),
    );
  }
}
回到顶部