camera: app-lifecycle pause / resume (Phase 6 polish)
Camera page kept the session running while the host app was
backgrounded — wastes battery, holds the hardware, and blocks
other apps from grabbing the camera. Add per-platform observers
that pause/resume the session on app foreground/background, with
a uniform `pauseForBackground` / `resumeForForeground` pair on the
shared CameraInstance.
Behaviour:
- On background: any in-flight recording is hard-cancelled
(matches every messaging app — the take ends with the app
switch). The session stops so the OS can release the camera.
- On foreground: session restarts iff it had been running.
Emits `sessionInterrupted` (`reason: appBackgrounded`) and
`sessionResumed` events so the Dart side can surface UX
affordances if needed.
iOS — `ios/Classes/Camera/CameraInstance+iOS.swift`:
Subscribes to UIApplication.{willResignActive, didBecomeActive}
notifications. Work hops onto sessionQueue so AV mutations stay
serialised. Storage uses the shared
`CameraInstance.lifecycleCleanup` closure slot — extension
doesn't need to add stored properties.
Android — added `androidx.lifecycle:lifecycle-process:2.7.0`,
observes `ProcessLifecycleOwner.get().lifecycle`. ON_STOP →
`pauseForBackground` (cancels recording + drops
CustomLifecycleOwner to CREATED → CameraX releases camera).
ON_START → `resumeForForeground`. Observer add/remove on main
thread per `ProcessLifecycleOwner` contract.
macOS — `macos/Classes/Camera/CameraInstance+macOS.swift`:
Intentional no-op. macOS desktop background semantics are
softer; the chat composer's Card dialog typically stays
foregrounded. Slot is wired so the shared
`observeLifecycle()` call still compiles.
Verified: all four platforms (iOS / Android / macOS / app tests)
build clean. Pod install picks up the new iOS extension file
once Pods/ is fresh — `flutter clean` if mid-iteration.
This commit is contained in:
20
macos/Classes/Camera/CameraInstance+macOS.swift
Normal file
20
macos/Classes/Camera/CameraInstance+macOS.swift
Normal file
@@ -0,0 +1,20 @@
|
||||
import Foundation
|
||||
|
||||
/// macOS counterpart of `CameraInstance+iOS.swift`.
|
||||
///
|
||||
/// macOS doesn't have iOS's hard "the app is backgrounded, you must
|
||||
/// release the camera" lifecycle. A backgrounded Mac app keeps
|
||||
/// running, and there's no equivalent UIApplication notification —
|
||||
/// the closest analogues are `NSApplication.didResignActive` /
|
||||
/// `…didBecomeActive`, but the chat composer's macOS surface (a
|
||||
/// Card dialog) typically stays in the foreground long enough that
|
||||
/// teardown on resign-active would cost more than it saves.
|
||||
///
|
||||
/// Left as a no-op so the shared `CameraInstance.observeLifecycle()`
|
||||
/// call compiles. If a need surfaces later, wire NSApplication
|
||||
/// observers here calling `pauseForBackground` / `resumeForForeground`.
|
||||
extension CameraInstance {
|
||||
func observeLifecycle() {
|
||||
// Intentionally empty.
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user