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

Firebase初始化冲突:WorkManager与主进程重复初始化引发报错

解决WorkManager与主进程Firebase初始化冲突:[core/no-app] 与 [DEFAULT]已存在 错误

问题描述

在Flutter项目中,主进程已初始化Firebase,但在WorkManager中访问用户数据推送个性化通知时,出现两种冲突错误:

  1. 初始错误:未处理异常:[core/no-app] 未创建Firebase App '[DEFAULT]' - 请调用Firebase.initializeApp()
  2. 添加初始化判断后新错误:IllegalStateException: FirebaseApp name [DEFAULT] already exists!

场景是WorkManager与主进程同步执行,导致Firebase初始化时机冲突。

问题根源

WorkManager在Android上默认运行在独立进程,与主进程的内存空间完全隔离:

  • 主进程初始化Firebase后,WorkManager进程无法共享主进程的Firebase实例,直接访问会触发未初始化错误
  • 自定义的isInitialized静态变量是进程内的,WorkManager进程中该变量初始为false,加上Firebase.apps.isEmpty判断在多进程下失效(两个进程都认为需要初始化),导致重复初始化报错

解决方案

1. 修正Firebase初始化判断逻辑

移除自定义的isInitialized变量,仅依赖Firebase官方提供的Firebase.apps.isEmpty判断——该判断基于当前进程的Firebase实例列表,能正确识别进程内的初始化状态。

2. 跨进程传递用户信息

WorkManager进程无法直接获取主进程的Firebase Auth登录状态(currentUser会为null),需在调度任务时通过inputData传递必要的用户标识(如uid)。

3. 规范WorkManager任务执行逻辑

将数据访问和通知逻辑放在Workmanager().executeTask内部,确保符合WorkManager的任务执行规范。

修改后的代码示例

修正AuthService的Firebase初始化方法

// AuthService code
static Future initializeFirebase() async {
  if (Firebase.apps.isEmpty) {
    print('start firebase initialization in ${Isolate.current.debugName}');
    await Firebase.initializeApp(
      options: DefaultFirebaseOptions.currentPlatform,
    );
  } else {
    print('firebase is already initialized in ${Isolate.current.debugName}');
  }
}

主进程中调度WorkManager任务(传入uid)

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await AuthService.initializeFirebase();

  // 屏幕方向、通知初始化等逻辑...

  // 注册周期性任务时传入当前用户uid
  final currentUser = FirebaseAuth.instance.currentUser;
  if (currentUser != null) {
    await Workmanager().registerPeriodicTask(
      'morning_task_notification',
      'morning_task',
      inputData: {'uid': currentUser.uid},
      frequency: const Duration(hours: 24),
      initialDelay: Duration(hours: 6 - DateTime.now().hour), // 首次延迟到6点执行
    );
  }

  runApp(const MyApp());
}

修正WorkManager的callbackDispatcher

void callbackDispatcher() async {
  print('entered callback dispatcher...');
  WidgetsFlutterBinding.ensureInitialized();
  await AuthService.initializeFirebase();

  Workmanager().executeTask((taskName, inputData) async {
    // 从inputData获取uid,避免依赖currentUser
    final String? uid = inputData?['uid'];
    if (uid == null) {
      print('UID not provided, skipping notification');
      return Future.value(true);
    }

    // 访问Firestore获取用户数据和任务列表
    final CollectionReference childCollection = FirebaseFirestore.instance.collection('child');
    final DocumentSnapshot userDoc = await childCollection.doc(uid).get();
    
    if (!userDoc.exists) {
      print('User document not found for uid: $uid');
      return Future.value(true);
    }

    Map<String, dynamic> userData = userDoc.data() as Map<String, dynamic>;
    final String userName = userData['name']; 

    final QuerySnapshot morningTasks = await childCollection.doc(uid).collection('schedule_morning').get();
    
    // 检查当前时间并推送通知
    if (DateTime.now().hour == 6 && morningTasks.size > 0) {
      NotificationService().showNotification(
        title: '今日任务提醒',
        body: '$userName,别忘了你的晨间任务哦!',
      );
    }

    return Future.value(true);
  });
}

额外注意事项

  • 确保DefaultFirebaseOptions在WorkManager进程中能正确加载,通常FlutterFire配置会自动处理,但需确认google-services.json或GoogleService-Info.plist配置正确
  • 若使用iOS平台,WorkManager的实现依赖BGTaskScheduler,需在Info.plist中配置对应的后台权限
  • 测试时可使用WorkManager的OneTimeTask快速验证逻辑,避免等待周期性任务触发

内容的提问来源于stack exchange,提问作者ديمة

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 17:29:55