diff --git a/lib/features/auth/presentation/bloc/auth_cubit.dart b/lib/features/auth/presentation/bloc/auth_cubit.dart index 096a4cf6..4c91f60f 100644 --- a/lib/features/auth/presentation/bloc/auth_cubit.dart +++ b/lib/features/auth/presentation/bloc/auth_cubit.dart @@ -49,9 +49,9 @@ class AuthCubit extends Cubit { data: {'user': user, 'data': user} ); if (user != null) { - tcp.connect(host: TCPConsts.TCP_IP, port: TCPConsts.TCP_PORT); + await tcp.connect(host: TCPConsts.TCP_IP, port: TCPConsts.TCP_PORT); // await _authTcpDatasource.sendAuthPacket();//包括发送认证包和获取列表和切换函数 - tcp.startHeartbeat(interval: const Duration(seconds: 4)); + tcp.startHeartbeat(interval: const Duration(seconds: 4)); // 2. 同步全局 App 状态 appCubit.setAuth(user); // 3. 进入已登录状态 @@ -142,4 +142,27 @@ class AuthCubit extends Cubit { _kickOutSub?.cancel(); // 销毁 Cubit 时关闭监听 return super.close(); } + + + /// 🔥 息屏/后台后恢复到前台时的重连方法 + Future reconnectAfterResume() async { + print('📱 [AUTH] 检测到应用恢复到前台,检查 TCP 连接状态...'); + + // 如果 TCP 未连接,则执行重连 + if (!tcp.isConnected) { + print('⚠️ [AUTH] TCP 未连接,开始重连...'); + try { + await tcp.connect(host: TCPConsts.TCP_IP, port: TCPConsts.TCP_PORT); + tcp.startHeartbeat(interval: const Duration(seconds: 4)); + print('✅ [AUTH] TCP 重连成功!'); + } catch (e) { + print('❌ [AUTH] TCP 重连失败:$e'); + // 可以选择重试或者通知用户 + } + } else { + print('✅ [AUTH] TCP 连接正常,无需重连'); + // 可选:发送一个心跳包确认连接有效 + tcp.sendHeartbeat(); + } + } } diff --git a/lib/main.dart b/lib/main.dart index ed0afe8b..8a08aeb1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -12,6 +12,7 @@ import 'package:maibu_satabot_v2/features/auth/presentation/bloc/auth_cubit.dart import 'package:maibu_satabot_v2/features/devices/presentation/bloc/devices_cubit.dart'; import 'core/di/injection.dart'; +import 'features/auth/presentation/bloc/auth_state.dart'; import 'features/auth/presentation/bloc/login_cubit.dart'; import 'features/devices/presentation/bloc/device_status_bloc.dart'; @@ -71,7 +72,101 @@ class MyApp extends StatelessWidget { ), // 其他 Cubit... ], - child: MaterialApp.router(title: 'Maibu Satabot', theme: AppTheme.lightTheme, routerConfig: sl()), + child: MaterialApp.router(title: 'Maibu Satabot', theme: AppTheme.lightTheme, routerConfig: sl(), + builder: (context, child) { + return _LifecycleListener(child: child); + },), + + ); } } +// 🔥 新增:应用生命周期监听器 +class _LifecycleListener extends StatefulWidget { + final Widget? child; + + const _LifecycleListener({required this.child}); + + @override + State<_LifecycleListener> createState() => _LifecycleListenerState(); +} + +class _LifecycleListenerState extends State<_LifecycleListener> with WidgetsBindingObserver { + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addObserver(this); + } + + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + super.dispose(); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + + switch (state) { + case AppLifecycleState.resumed: + // 🔥 从息屏或后台恢复到前台 + debugPrint('📱 [生命周期] 应用恢复到前台 (resumed),检查 TCP 连接...'); + _handleResume(); + break; + + case AppLifecycleState.inactive: + // 应用处于非活动状态(iOS 来电、Android 分屏等) + debugPrint('💤 [生命周期] 应用进入非活动状态 (inactive)'); + break; + + case AppLifecycleState.paused: + // 应用进入后台(息屏、按 Home 键等) + debugPrint('🌙 [生命周期] 应用进入后台 (paused)'); + break; + + case AppLifecycleState.detached: + // 应用仍然托管但不会显示给用户(例如销毁中的 Activity) + debugPrint('🚫 [生命周期] 应用已分离 (detached)'); + break; + + case AppLifecycleState.hidden: + // 应用不可见(Android 14+ 或未来版本) + debugPrint('👻 [生命周期] 应用已隐藏 (hidden)'); + break; + } + } + + // 🔥 处理恢复到前台的逻辑 + Future _handleResume() async { + try { + final authCubit = context.read(); + + // 检查当前是否已登录 + if (authCubit.state is! AuthAuthenticated) { + debugPrint('⚠️ [生命周期] 用户未登录,跳过 TCP 重连'); + return; + } + + // 检查 TCP 连接状态 + // 注意:这里需要通过 authCubit 访问 tcp 实例 + // 由于 tcp 是 private 字段,我们需要在 AuthCubit 中暴露一个方法 + debugPrint('✅ [生命周期] 准备执行 TCP 重连检查...'); + + // 延迟一点执行,确保 UI 已经加载完成 + await Future.delayed(const Duration(milliseconds: 500)); + + // 调用 AuthCubit 的重连方法 + await authCubit.reconnectAfterResume(); + + debugPrint('✅ [生命周期] TCP 重连检查完成'); + } catch (e, stack) { + debugPrint('❌ [生命周期] 重连过程发生错误:$e\n$stack'); + } + } + + @override + Widget build(BuildContext context) { + return widget.child!; + } +} \ No newline at end of file