You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter本地生成崩溃报告的实现方法咨询

实现Flutter本地崩溃报告存储与邮件发送方案

以下是完全基于设备本地实现的方案,无需依赖第三方崩溃监控服务,所有数据仅保存在用户设备上:

依赖准备

需要添加两个官方pub包到pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  path_provider: ^2.1.2  # 获取本地存储路径
  url_launcher: ^6.2.6    # 唤起系统邮件应用

核心实现步骤

1. 全局崩溃异常捕获

Flutter需要分别处理UI线程和后台Isolate的异常,确保所有崩溃都能被捕获:

import 'dart:async';
import 'dart:io';
import 'dart:isolate';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:url_launcher/url_launcher.dart';

void main() {
  // 捕获UI线程异常
  FlutterError.onError = (FlutterErrorDetails details) {
    if (kReleaseMode) {
      // 发布模式下捕获并保存崩溃报告
      _saveCrashReport(details.exception.toString(), details.stack.toString());
      // 终止应用(可选,根据需求决定是否强制退出)
      exit(1);
    } else {
      // 调试模式下直接打印异常
      FlutterError.dumpErrorToConsole(details);
    }
  };

  // 捕获后台Isolate异常
  Isolate.current.addErrorListener(RawReceivePort((pair) async {
    final List<dynamic> errorAndStacktrace = pair;
    if (kReleaseMode) {
      _saveCrashReport(errorAndStacktrace[0].toString(), errorAndStacktrace[1].toString());
      exit(1);
    }
  }).sendPort);

  runApp(const MyApp());
}

2. 生成并保存崩溃报告到本地

将崩溃信息写入应用私有目录下的文件,确保不会被其他应用访问:

Future<void> _saveCrashReport(String exception, String stackTrace) async {
  try {
    final Directory appDocDir = await getApplicationDocumentsDirectory();
    final Directory crashDir = Directory('${appDocDir.path}/crash_reports');
    // 若目录不存在则创建
    if (!await crashDir.exists()) {
      await crashDir.create(recursive: true);
    }
    // 用时间戳命名文件,避免重复
    final String timestamp = DateTime.now().millisecondsSinceEpoch.toString();
    final File crashFile = File('${crashDir.path}/crash_$timestamp.txt');
    // 写入崩溃详情:时间、异常信息、堆栈
    final String reportContent = '''
崩溃时间: ${DateTime.now().toLocal()}
异常信息: $exception
堆栈跟踪:
$stackTrace
''';
    await crashFile.writeAsString(reportContent);
  } catch (e) {
    // 捕获保存失败的异常,避免二次崩溃
    if (kDebugMode) {
      print('保存崩溃报告失败: $e');
    }
  }
}

3. 启动时检测崩溃报告并唤起邮件应用

在应用启动时检查本地是否存在未发送的崩溃报告,若有则唤起邮件应用并填充报告内容:

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

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

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    // 应用启动后立即检测崩溃报告
    _checkAndSendCrashReport();
  }

  Future<void> _checkAndSendCrashReport() async {
    try {
      final Directory appDocDir = await getApplicationDocumentsDirectory();
      final Directory crashDir = Directory('${appDocDir.path}/crash_reports');
      if (await crashDir.exists()) {
        final List<FileSystemEntity> files = crashDir.listSync();
        for (final file in files) {
          if (file is File) {
            final String reportContent = await file.readAsString();
            // 构造mailto链接,替换为你的收件邮箱、邮件主题
            final Uri mailUri = Uri(
              scheme: 'mailto',
              path: 'your-support-email@example.com',
              queryParameters: {
                'subject': 'Flutter应用崩溃报告',
                'body': reportContent,
              },
            );
            // 唤起系统邮件应用
            if (await canLaunchUrl(mailUri)) {
              await launchUrl(mailUri);
              // 发送后删除报告文件,避免重复触发
              await file.delete();
            }
          }
        }
      }
    } catch (e) {
      if (kDebugMode) {
        print('处理崩溃报告失败: $e');
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('本地崩溃报告示例')),
        body: const Center(child: Text('测试应用')),
      ),
    );
  }
}

注意事项

  • 仅在发布模式下启用崩溃捕获和存储,调试模式下保持默认的异常打印便于调试
  • 邮件唤起依赖系统自带邮件应用,若用户设备未配置邮件应用,canLaunchUrl会返回false,可添加提示引导用户配置
  • 崩溃报告存储在应用私有目录,卸载应用时会被自动删除,不会残留数据

内容的提问来源于stack exchange,提问作者Sparkringo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 15:36:25