Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

動画再生中にイヤホンの抜き差しが発生した時に検知する必要があったので
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)の抜き差しの判定が思っていたよりも簡単にできましたね。
これまで動画関連は深く踏み込んで触っていなかったので、いろいろ触ってみようと思います。

以上です。

s_emoto
iOS歴: 3年 Android歴: 1年
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away