Edited at

【Swift】動画再生中にイヤホン(Bluetooth)の抜き差しをチェックする

動画再生中にイヤホンの抜き差しが発生した時に検知する必要があったので

Extensionを作成しました。

検知に利用するのは「AVAudioSession」「Notification」です。

NotificationでAVAudioSessionの値の監視を行います。

また、今回はRxのExtensionとして実装しましたが、普通にNotificationの実装をすればRxを使わなくても実装可能です。


ソースコード


Rx+AVAudioSession.swift


import Foundation
import RxSwift
import AVFoundation

extension Reactive {

// イヤホン(Bluetooth含む)の抜き差しをチェック
var isConnectedHeadPhone: Observable<Bool> {
AVAudioSession.sharedInstance()
return NotificationCenter.default.rx.notification(.AVAudioSessionRouteChange,
object: nil)
.map { didChage in

guard let desc = didChage.userInfo?[AVAudioSessionRouteChangePreviousRouteKey] as? AVAudioSessionRouteDescription
else { return false }
let outputs = desc.outputs
for component in outputs {
if component.portType == AVAudioSessionPortHeadphones ||
component.portType == AVAudioSessionPortBluetoothA2DP ||
component.portType == AVAudioSessionPortBluetoothLE ||
component.portType == AVAudioSessionPortBluetoothHFP {
// イヤホン(Bluetooth含む)が抜かれた
return false
}
}
// イヤホン(Bluetooth含む)が差された
return true
}
}
}



Usage


ViewController.swift


import UIKit
import RxSwift

final class ViewController: UIViewController {

private let disposeBag = DisposeBag()

override func viewDidLoad() {
super.viewDidLoad()

rx.isConnectedHeadPhone
.subscribe { isConnected in
guard let isConnected = isConnected.element else { return }
if isConnected {
// イヤホン(Bluetooth含む)が差された時の処理
} else {
// イヤホン(Bluetooth含む)が差された時の処理
}
}
.disposed(by: disposeBag)
}
}



Rxを使わない時は

Rxを使わない場合はこんな感じでいけると思います。


ViewController.swift


import UIKit

final class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

AVAudioSession.sharedInstance()
NotificationCenter.default.addObserver(self,
selector: #selector(self.didAudioSessionRouteChanged(_:)),
name: .AVAudioSessionRouteChange, object: nil)
}

@objc
private func didAudioSessionRouteChanged(_ notification: Notification) {

guard let desc = notification.userInfo?[AVAudioSessionRouteChangePreviousRouteKey] as? AVAudioSessionRouteDescription
else { return }
let outputs = desc.outputs
for component in outputs {
if component.portType == AVAudioSessionPortHeadphones ||
component.portType == AVAudioSessionPortBluetoothA2DP ||
component.portType == AVAudioSessionPortBluetoothLE ||
component.portType == AVAudioSessionPortBluetoothHFP {
// イヤホン(Bluetooth含む)が差された時の処理
return
}
}
// イヤホン(Bluetooth含む)が差された時の処理
}
}



まとめ

イヤホン(Bluetooth)の抜き差しの判定が思っていたよりも簡単にできましたね。

これまで動画関連は深く踏み込んで触っていなかったので、いろいろ触ってみようと思います。

以上です。