···1515 late final SparkLogger _logger;
1616 AppLifecycleListener? _lifecycleListener;
17171818+ // Track if camera was disposed due to app lifecycle (not user navigation)
1919+ bool _wasDisposedByLifecycle = false;
2020+1821 @override
1922 FutureOr<CameraState> build() async {
2023 _logger = GetIt.instance<LogService>().getLogger('Camera');
21242222- ref.onDispose(_disposeCamera);
2525+ // Only dispose lifecycle listener when provider is permanently disposed
2626+ // Don't use _disposeCamera here - we need to keep lifecycle listener
2727+ // active so we can detect when app returns to foreground
2828+ ref.onDispose(_disposeLifecycleListener);
23292424- // Listen to app lifecycle to dispose camera when backgrounded
2525- _lifecycleListener = AppLifecycleListener(
3030+ // Listen to app lifecycle to pause/resume camera
3131+ // Note: onHide is for app fully backgrounded (not transient inactive states)
3232+ // onShow handles when app returns to foreground
3333+ _lifecycleListener ??= AppLifecycleListener(
2634 onHide: _onAppBackgrounded,
2727- onInactive: _onAppBackgrounded,
3535+ onShow: _onAppForegrounded,
2836 );
3737+3838+ // If camera was disposed by lifecycle, reinitialize now
3939+ if (_wasDisposedByLifecycle && state.value != null) {
4040+ _logger.i('Reinitializing camera after app resume');
4141+ _wasDisposedByLifecycle = false;
4242+ try {
4343+ return await _initializeCamera();
4444+ } catch (e, stackTrace) {
4545+ _logger.e(
4646+ 'Failed to reinitialize camera after resume',
4747+ error: e,
4848+ stackTrace: stackTrace,
4949+ );
5050+ // Return error state but don't crash
5151+ return CameraState(
5252+ error: 'Failed to restart camera: $e',
5353+ cameras: state.value?.cameras ?? [],
5454+ );
5555+ }
5656+ }
29573058 _logger.i('Initializing camera provider');
3159···321349 Future<void> _disposeCamera() async {
322350 _logger.d('Disposing camera');
323351324324- // Dispose lifecycle listener to prevent further callbacks
325325- _lifecycleListener?.dispose();
326326- _lifecycleListener = null;
327327-328352 try {
329353 final currentState = state.value;
330354 final controller = currentState?.controller;
···366390 }
367391 }
368392393393+ /// Disposes the lifecycle listener. Should only be called when provider
394394+ /// is being permanently disposed (not for lifecycle pauses).
395395+ void _disposeLifecycleListener() {
396396+ _lifecycleListener?.dispose();
397397+ _lifecycleListener = null;
398398+ }
399399+369400 Future<void> _waitForPreviewDetach() async {
370401 if (!ref.mounted) return;
371402···387418 }
388419 }
389420390390- /// Handles app lifecycle changes when app is backgrounded or becomes inactive.
421421+ /// Handles app lifecycle changes when app is fully backgrounded (onHide).
391422 /// Disposes the camera to free resources and prevent battery drain.
392423 void _onAppBackgrounded() {
393393- _logger.i('App backgrounded/inactive, disposing camera');
424424+ _logger.i('App backgrounded, disposing camera');
425425+ _wasDisposedByLifecycle = true;
394426 _disposeCamera();
427427+ }
428428+429429+ /// Handles app lifecycle changes when app returns to foreground (onShow).
430430+ /// Triggers a rebuild which will reinitialize the camera.
431431+ void _onAppForegrounded() {
432432+ _logger.i('App returned to foreground');
433433+ if (_wasDisposedByLifecycle) {
434434+ _logger.d('Camera was disposed by lifecycle, will reinitialize');
435435+ // Trigger a rebuild by invalidating the state
436436+ // The build method will check _wasDisposedByLifecycle and reinit
437437+ ref.invalidateSelf();
438438+ }
395439 }
396440397441 Future<void> disposeCamera() async {