У меня есть это приложение, которое позволяет пользователям записывать вещи вокруг. Затем, когда у них есть аксессуар Bluetooth (скажем, гарнитура), они должны иметь возможность начать / остановить сеанс записи с помощью кнопки воспроизведения / паузы на устройстве Bluetooth.
Я успешно реализовал начальный сеанс с использованием MPRemoteCommandCenter`
let rcCenter = MPRemoteCommandCenter.shared()
rcCenter.nextTrackCommand.isEnabled = false
rcCenter.nextTrackCommand.addTarget { _ in return .success }
rcCenter.previousTrackCommand.isEnabled = false
rcCenter.previousTrackCommand.addTarget { _ in return .success }
rcCenter.togglePlayPauseCommand.isEnabled = true
rcCenter.playCommand.isEnabled = true
rcCenter.pauseCommand.isEnabled = true
rcCenter.stopCommand.isEnabled = true
rcCenter.togglePlayPauseCommand.addTarget(self, action: #selector(remotePlayPauseAction(_:)))
rcCenter.playCommand.addTarget(self, action: #selector(remotePlayPauseAction(_:)))
rcCenter.pauseCommand.addTarget(self, action: #selector(remotePlayPauseAction(_:)))
rcCenter.stopCommand.addTarget(self, action: #selector(remotePlayPauseAction(_:)))
Тем не менее, он никогда не сталкивается с моим действием паузы / остановки от Bluetooth. Я не знал о том, что случилось, пока не увидел это в консоли устройства:
по умолчанию 18: 19: 46.609673 +0700 bluetoothd Получен запрос «get play status» от устройства
по умолчанию 18: 19: 46.671092 +0700 bluetoothd Получена команда воспроизведения AVRCP от устройства
// отправка состояний аудио сеанса, потому что приложение записывает бла-бла ...
по умолчанию 18: 19: 48.246780 +0700 bluetoothd AudioSendThreading
Это срабатывает, когда приложение не записывает -> получает команду воспроизведения от bluetoothhd -> начать запись -> отправка сеанса на bluetooth.
А потом я снова нажму кнопку воспроизведения / паузы и получу этот журнал:
по умолчанию 18: 20: 09.650855 +0700 bluetoothd Событие зависания принятого вызова
(AT + CHUP) из устройства по умолчанию 18: 20: 09.651273
+0700 bluetoothd Обнаружен текущий виртуальный вызов - устройство для взлома и оповещение верхних уровней.
=> похоже, что на телефон поступает сигнал об окончании вызова (обратите внимание, что звонок не выполняется, только запись в сеансе)
Итак, как мне обработать это событие? Я пытался использовать CallKit
, но все еще бесполезно:
let callCenter = CXCallObserver()
callCenter.setDelegate(self, queue: nil)
func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {
print("Hi!") // not jump in!
}
Обновление
Я попытался вернуться к старому стилю обработки:
UIApplication.shared.beginReceivingRemoteControlEvents()
becomeFirstResponder()
/////////////////
override func remoteControlReceived(with event: UIEvent?) {
guard let event = event, event.type == .remoteControl else { return }
// Start / pause actions
}
И все же получил тот же результат (может начать, но не может остановиться, получая события play
и call hangup
, как и раньше). Теперь мое предположение переключилось на режим и категории AVAudioSession
, но все еще не получило никаких подсказок.
do {
let session = AVAudioSession.shared()
// What is the correct params here?
// try session.setCategory(.playAndRecord, mode: .voiceChat, options: [.allowBluetoothA2DP, .allowBluetooth])
// try session.setCategory(.record, options: .allowBluetooth)
session.setActive(true)
} catch { print(error) }