Skip to content

fix(ios): keep multitasking camera access across capture sessions - #88

Draft
renefloor wants to merge 1 commit into
mainfrom
fix/multitasking-camera-access-persistence
Draft

fix(ios): keep multitasking camera access across capture sessions#88
renefloor wants to merge 1 commit into
mainfrom
fix/multitasking-camera-access-persistence

Conversation

@renefloor

Copy link
Copy Markdown
Collaborator

The bug

getUserMedia allocates a new RTCCameraVideoCapturer on every video request (FlutterRTCMediaStream.m:606), and therefore a new AVCaptureSession. A fresh session starts with multitaskingCameraAccessEnabled == NO.

enableIOSMultitaskingCameraAccess only ever wrote to the session that happened to exist when it was called, so the setting was lost as soon as the camera was toggled off and on — which is exactly what the video SDK does when muting the camera (it stops the track and recreates it on unmute). After the first toggle, iOS suspends capture the moment the app goes to the background, and remote participants are left looking at a frozen frame.

The same call also dropped the request entirely when no capture session existed yet (result(@NO) and nothing remembered), so asking before the camera started never took effect.

The fix

Remember what was asked for, and apply it whenever a capture session starts.

  • FlutterWebRTCPlugin gains a multitaskingCameraAccessRequested flag, set by enableMultitaskingCameraAccess: before the nil-session check.
  • New -applyMultitaskingCameraAccessToCaptureSession applies the remembered request to the current session, no-op when it was never requested, when the device doesn't support it, or when it is already enabled.
  • getUserVideo: calls it from the startCaptureWithDevice completion handler, once the new session is configured and running.

Camera switching (CameraUtils.m:346) reuses the existing capturer and session, so it is unaffected and needs no change.

New API

Helper.isIOSMultitaskingCameraAccessSupported()Future<bool?>, backed by the isIOSMultitaskingCameraAccessSupported method channel. It reports session.isMultitaskingCameraAccessSupported for the capture session in use, and null when there is no session to ask.

This exists because enableIOSMultitaskingCameraAccess returns false for four different situations — unsupported device, iOS 15, no capture session, and "you asked me to disable it" — which leaves callers unable to tell a device that cannot do this from access that was simply never requested. The Stream Video Flutter SDK needs that distinction to decide whether to mute the video track while backgrounded (stream-video-flutter#1346), and today has to infer it.

isMultitaskingCameraAccessSupported is an AVCaptureSession instance property, not a device-wide one, hence null rather than false when no session exists — false would be a claim about the device that this cannot actually make.

macOS gets a stub returning NO, matching the existing enableMultitaskingCameraAccess stub there.

Testing

  • flutter build ios --simulator --debug on example/: succeeds, no new warnings.
  • flutter build macos --debug on example/: succeeds, no new warnings.
  • flutter analyze on the changed Dart files: clean.

Not verified on device. The behaviour this fixes only shows up on hardware that supports multitasking camera access (M1 iPads and later) — the simulator reports isMultitaskingCameraAccessSupported == false, so the new apply path is a no-op there. Confirming it needs an M1-or-later iPad in a call: enable camera, disable it, enable it again, background the app, and check that a second participant still receives frames. Before this change they would not.

No CHANGELOG entry — this repo writes those in the release PR.

🤖 Generated with Claude Code

A capture session is created per getUserMedia call, and a new one starts
without multitasking camera access — so toggling the camera off and on lost
it, and the camera stopped producing frames once the app was backgrounded.
The requested state is now remembered and applied whenever capture starts,
including when it was requested before a capture session existed.

Adds isIOSMultitaskingCameraAccessSupported, which reports whether the
capture session in use supports it, so callers can tell an unsupported
device from access that was never asked for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 11, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

renefloor added a commit to GetStream/stream-video-flutter that referenced this pull request Sep 11, 2026
…state

The mute decision now reads isIOSMultitaskingCameraAccessSupported from the
capture session in use instead of inferring it from whether the SDK managed to
turn multitasking camera access on, which also reads false when it was never
asked for. Requires the plugin fix in GetStream/webrtc-flutter#88, pinned here
through a git override until it ships.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant