flutter_background_service调用SharedPreferences报MissingPluginException如何解决
错误原因
这个错误是因为 Flutter 后台 isolate 和主运行 isolate 是相互独立的运行环境,默认不会自动注册原生插件,导致 shared_preferences 等依赖原生通道实现的插件在后台 isolate 中调用时找不到对应实现。另外你代码里把 Firebase 初始化写在定时循环内,重复初始化也会带来额外的异常风险。
修复步骤
- 第一步:升级
shared_preferences到最新稳定版,新版本官方已经适配了后台 isolate 调用场景。 - 第二步:调整
onStart方法的初始化逻辑,在调用插件前确保插件初始化完成,同时将 Firebase 初始化移到循环外避免重复执行。修改后的代码参考:
void onStart() async { WidgetsFlutterBinding.ensureInitialized(); // 提前初始化SharedPreferences适配后台场景 await SharedPreferences.ensureInitialized(); // Firebase初始化移到循环外仅执行一次,高版本Flutter可传入自动生成的Firebase配置参数 await Firebase.initializeApp( // 可选:如果提示缺少配置,传入DefaultFirebaseOptions.currentPlatform ); final service = FlutterBackgroundService(); await service.setForegroundMode(true); final prefs = await SharedPreferences.getInstance(); final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance; Timer.periodic(Duration(seconds: 15), (timer) async { try { if (!(await service.isServiceRunning())) { timer.cancel(); return; } final memberId = prefs.getString("member_id"); if (memberId != null) { final token = await _firebaseMessaging.getToken(); print("TOKEN $token"); // await ProfileApi().updateToken(memberId, token); service.sendData( { "current_date": DateTime.now().toIso8601String(), }, ); } } catch (e) { final memberId = prefs.getString("member_id"); if(memberId != null) { await ProfileApi().updateToken(memberId, e.toString()); } print(e); } }); }
- 第三步:如果执行上述修改后仍报错,需要手动注册所有原生插件到后台 isolate:
直接引用 Flutter 编译时自动生成的generated_plugin_registrant.dart文件,在onStart方法的WidgetsFlutterBinding.ensureInitialized()之后添加GeneratedPluginRegistrant.registerWith(WidgetsBinding.instance.platformDispatcher.views.first.engine!)即可。
注意事项
- 现在设置的15秒更新频率过于频繁,FCM token 仅在应用重装、用户清除数据、设备恢复出厂等少数场景才会变更,建议调整到24小时更新一次即可,降低耗电和无效请求量。
- 调用自有 API 上传 token 时建议添加失败重试机制,避免网络波动导致 token 上传失败。
内容的提问来源于stack exchange,提问作者Boby
相关产品推荐
相关产品推荐

