Files
chanora/apps
EdisonJwa b1d117033e fix(ios,audio): don't call setPreferredInput after speaker/receiver override (silent route reversion)
User report: 'speakerphone (built-in mic input)' logs printed
successfully but audio output didn't actually switch to speaker.
No exception thrown by either AVAudioSession call.

Root cause:

Previous _selectSpeaker called:
  1. await overrideOutputAudioPort(.speaker)
  2. await setPreferredInput(builtInMic)

Apple-documented behavior in .voiceChat mode: when
setPreferredInput is called, iOS recalculates the entire route
based on the natural input/output pairing for the selected port.

Built-in mic's natural output pairing is the receiver/earpiece
(matches the 'I'm talking on a phone' UX of .voiceChat). So step 2
caused iOS to SILENTLY REVERT the speaker override from step 1
and route output back through the earpiece.

Net: await chain returned without exception (both calls 'succeeded'
in API terms), debugPrint logged the success message, but the user
heard the call audio coming out of the earpiece, not the speaker.

Same issue affected _selectReceiver (after the speaker bug fix
was reverted): redundant setPreferredInput(builtInMic) call risked
the same recalc race.

Fix:

  * _selectSpeaker: only call overrideOutputAudioPort(.speaker).
    No setPreferredInput. The override alone is sufficient \u2014 the
    input stays on whatever the system was already using (built-in
    mic by default, or BT/wired if connected).

  * _selectReceiver: only call overrideOutputAudioPort(.none).
    No setPreferredInput. Removing the speaker override naturally
    returns to .voiceChat's default route (receiver).

  * _selectInput (BT / wired / USB): unchanged. These inputs PAIR
    their own output device, so .none + setPreferredInput is the
    correct combo (user hears audio through the same device they
    speak into).

flutter build ios --release --no-codesign: 21.2 s, Runner.app
30.4 MB.
2026-05-16 21:36:59 +08:00
..