AudioManager MODE_IN_COMMUNICATION снижает качество звука и вызывает треск/треск
Описание проблемы:
Когда приложение подключено через наушники Bluetooth, я запускаюaudioManager.startBluetoothSco()
. Вы можете проверить код ниже. Соединение работает хорошо, но у меня проблема с потрескивающими звуками, которые воспроизводит MediaPlayer. Всякий раз, когда воспроизводится звук действия, качество плохое или слышен треск. (например, R.raw.record_start, R.raw.success_action, R.raw.failure_action)
Устройства, которые я использовал для тестирования:
- OpenComm от AfterShokx и Jabra Evolve 65
- Samsung A52, Samsung A50, Пиксель 3, OnePlus 6 Pro
Что я пробовал до сих пор?
- я пытался изменить
audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
в AudioManager.MODE_IN_CALL или AudioManager.MODE_NORMAL.
- Изменение на MODE_IN_CALL не меняет . Значение остается равным 0, что соответствует MODE_NORMAL.
- Изменение на MODE_NORMAL работает только на Samsung A52. Никаких потрескиваний не слышно все работает отлично. Вот чего я хочу добиться,
- НО все остальные телефоны переключаются на другой поток или что-то еще; вот почему я не СЛЫШУ никаких звуков мультимедиа.
- Допустим, я использую Pixel 3 и подключен к Jabra Evolve 65 в режиме MODE_NORMAL. Я больше не слышу никаких звуков мультимедиа, включая звуки других приложений, таких как Youtube, Spotify и системные звуки, но в режиме MODE_IN_COMMUNICATION он работает с потрескивающим звуком.
Я пытался изменить AudioAttributes MediaPlayer, но все равно плохое качество.
val actionSound = if (triggerErrorEarcon) R.raw.failure_action else if (longRecordingBreak) R.raw.success_action else R.raw.record_start val md = MediaPlayer.create(context, actionSound) val streamType = if (audioDeviceManager.headsetConnected) AudioManager.STREAM_VOICE_CALL else AudioManager.STREAM_MUSIC md.setAudioAttributes( AudioAttributes.Builder() .setLegacyStreamType(streamType) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build()) md.play()
Возможные решения?
- не знаю как, но исправляю
audioManager.mode
или некоторые другие свойства audioManager. - Продолжайте использовать MODE_IN_COMMUNICATION, но исправьте свойства MediaPlayer, чтобы отключить плохое качество звука на устройстве Bluetooth.
- Я не могу думать ни о чем другом с этого момента. Я надеюсь, что вы могли бы помочь мне с этой проблемой, спасибо заранее.
AudioDeviceManager.kt:
class AudioDeviceManager(val context: Context) {
internal val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
internal val headsetConnectedSubject = BehaviorSubject.createDefault(false)
internal val headsetConnected: Boolean get() = headsetConnectedSubject.value ?: false
private val intentFilter = IntentFilter().apply { addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED) }
private val audioDeviceCallback = object: AudioDeviceCallback() {
override fun onAudioDevicesAdded(addedDevices: Array<out AudioDeviceInfo>?) {
super.onAudioDevicesAdded(addedDevices)
updateBluetoothHeadsetState()
}
override fun onAudioDevicesRemoved(removedDevices: Array<out AudioDeviceInfo>?) {
super.onAudioDevicesRemoved(removedDevices)
updateBluetoothHeadsetState()
}
}
private val scoReceiver = object: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (intent?.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1) == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
// SCO now connected
audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
audioManager.isSpeakerphoneOn = false
audioManager.isBluetoothScoOn = true
}
}
}
fun start() {
if (headsetConnected.not())
audioManager.registerAudioDeviceCallback(audioDeviceCallback, null)
}
fun stop(unregisterAudioDeviceCallback: Boolean = false) {
if (unregisterAudioDeviceCallback)
unregisterDeviceCallback()
audioManager.mode = AudioManager.MODE_NORMAL
audioManager.isSpeakerphoneOn = true
audioManager.isBluetoothScoOn = false
audioManager.stopBluetoothSco()
}
private fun unregisterDeviceCallback() = audioManager.unregisterAudioDeviceCallback(audioDeviceCallback)
fun updateBluetoothHeadsetState() {
val headset = audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)?.firstOrNull { it.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO }
val headsetConnected = headset != null
headsetConnectedSubject.onNext(headsetConnected)
if (headsetConnected) {
audioManager.startBluetoothSco()
context.registerReceiver(scoReceiver, intentFilter)
} else {
audioManager.mode = AudioManager.MODE_NORMAL
audioManager.isSpeakerphoneOn = true
audioManager.isBluetoothScoOn = false
audioManager.stopBluetoothSco()
}
}
}
Воспроизведение звука действия в приложении:
MediaPlayer.create(context, R.raw.record_start)
.play()
.subscribe()
.addTo(disposable)
Функция расширения:
fun MediaPlayer.play(): Completable {
return Completable.create { emitter ->
var isCancelled = false
emitter.setCancellable {
isCancelled = true
}
setOnCompletionListener {
GlobalScope.launch {
// release the sound a bit later. Listener is triggering so fast!
delay(3000)
it.release()
}
if (isCancelled) { return@setOnCompletionListener }
emitter.onComplete()
}
start()
}
}