How to configure session to use Bluetooth headset mic on Android?
I've been struggling to get audio input via Bluetooth headset working on Android:
final session = await AudioSession.instance;
// await session.configure(AudioSessionConfiguration.speech());
await session.configure(AudioSessionConfiguration(
avAudioSessionCategory: AVAudioSessionCategory.playAndRecord,
avAudioSessionCategoryOptions: AVAudioSessionCategoryOptions.defaultToSpeaker |
AVAudioSessionCategoryOptions.allowBluetooth,
// AVAudioSessionCategoryOptions.duckOthers,
// avAudioSessionMode: AVAudioSessionMode.spokenAudio,
avAudioSessionMode: AVAudioSessionMode.defaultMode,
avAudioSessionRouteSharingPolicy: AVAudioSessionRouteSharingPolicy.defaultPolicy,
avAudioSessionSetActiveOptions: AVAudioSessionSetActiveOptions.none,
androidAudioAttributes: const AndroidAudioAttributes(
contentType: AndroidAudioContentType.speech,
flags: AndroidAudioFlags.none,
usage: AndroidAudioUsage.voiceCommunication,
),
androidAudioFocusGainType: AndroidAudioFocusGainType.gain,
androidWillPauseWhenDucked: true,
));
await session.setActive(true);
```
Everything works fine on iOS, but no matter how I tweak the Android settings (which seem quite limited compared to iOS AVAudioSession), I cannot get audio input via the Bluetooth headset microphone. Anyone have any suggestions?
Hi. I have the same issue. I try flutter_sound, but does not work. Have you solve this? Thanks
In order to receive audio from Bluetooth microphone in Android, you have to implement the audio capture at native side while managing the Bluetooth remote device connect and disconnection by listening through ACTION_CONNECTION_STATE_CHANGED events while also managing the mobile Bluetooth disconnection through ACTION_STATE_CHANGED events.
In order to capture audio, you should implement AudioRecord class. Before calling the startRecording method of AudioRecord, call startBluetoothSco then setBluetoothScoOn(true) of AudioManager.
When Bluetooth remote device is reconnected after a disconnection, you have to wait for STATE_CONNECTED event then stop the audio recording(AudioRecord class) and add a delay of 5secs(thread sleep) so that device is connected and ready before starting the recording again.
When done remember to clean up the event listeners and calling stopBluetoothSco() setBluetoothScoOn(false) of AudioManager.
Hope this helps :)
That sounds like something that a good audio recorder plugin should manage.
The record plugin has a feature request for it: https://github.com/llfbandit/record/issues/84 . There was also a PR https://github.com/llfbandit/record/pull/225 which was later closed by its author 🤷
@ryanheise Agreed, it's out of scope for audio_session.
I am facing an issue; I think you can suggest something on it. I am using audio_session for handling interruptions by subscribing to 'interruptionEventStream' but when the audio is interrupted by apps like music player, I receive unknown audio interruption type and audioFocus is lost and as such I don't receive further interruption events unless I set the audio_session to active again basically regaining audioFocus.
I was looking for a way I can listen to some event that would inform me that audioFocus is now available and not being used by other app so I can safely request for audioFocus. Reason being gaining audioFocus if other app is using it, will cause the music player to stop abruptly.
@bilalahmed24 I don't think the API supports this by design. If Android wants to tell you when the audio focus is available again, it will give you type pause instead of unknown. But rather than try to offer advice, I would say that this plugin will wrap whatever is in the original API, and so if you refer to the original Android API documentation and find a way to do something that is not possible in this wrapper, please let me know and I will add the missing API to this wrapper.
@ryanheise I believe this configuration, will provide the ability for app to regain audio focus: setAcceptsDelayedFocusGain