【最新OS対応】音声割込みを検知しよう
目次
- 経緯
- 主な対応項目
- 対応方法
- 例外
一、経緯
仕事でとあるアプリの最新OS対応を行った時に発生したことです。
昔のアプリでサスペンドせずに音声が割り込まれる場合の対応がされていないので、例えばプッシュ通知にてアラームをスワイプで消した場合、音声が復帰しなくなりました。他にはマルチタスクやピクチャーインピクチャーのような最近のOSで実装された機能としては、もちろん当時はありませんので、対応する必要があります。
つまり、以前のOSでは、何か音声の割り込みがあった時に必ずサスペンドをコールバックするので、サスレジの対応をすれば問題がありませんが、最近のOSではサスペンドせずに音声の割り込みだけ発生することがあります。サスレジの箇所だけで音声操作を対応した場合、音声割込み終了後に音声が復帰しないことがあります(まさに今回発生した内容)。
二、主な対応項目
画面遷移せずに音声が割り込む場合
三、対応方法
- インポート
#import <AVFoundation/AVFoundation.h>
- インスタンスの取得
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
- カテゴリの指定
NSError *error = nil;
[audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
必要に応じてカテゴリを変更すれば良い、基本的にアプリはサイレントスイッチによりオンオフの切り替えが必要であるため、AVAudioSessionCategorySoloAmbientを指定しています。
また、マルチタスクやピクチャーインピクチャーのような機能も同時に対応したい場合に、同時に音声をサポートすることが必要になります。
[audioSession setCategory:AVAudioSessionCategoryPlayback mode:mixWithOthers error:&error];
- 割り込みの検知
- (void)audioSessionInterrupted:(NSNotification *)notification {
NSNumber *interruptType = [notification.userInfo objectForKey:@"AVAudioSessionInterruptionTypeKey"];
if ([interruptType unsignedIntegerValue] == AVAudioSessionInterruptionTypeBegan){
//割り込み開始時の処理
}else if([interruptType unsignedIntegerValue] == AVAudioSessionInterruptionTypeEnded){
//割り込み終了時の処理
}
}
四、例外
- 音声割込みとサスレジが同時にコールされた場合
音声割込みとサスレジが同時にコールされた場合は、特に問題はないが、同じ処理を二度読んでしまいますので、どちらかを呼ばないようにする方がよろしい気がします。
- OSにより、音声割込みとサスレジの順番が違いことがある
対応している時に、OSにより、音声割り込みとサスレジが呼ばれる順番が異なることがあるみたいです。基本的な順番としては音声割り込むとサスレジのワンセットずつ呼ばれることが望ましいだが、そうならない場合が実際ありました。
※確実ではないだが、OS14からは修正されているようです。(14と以前のOSとの挙動が異なっている)
参考資料
AVAudioSession細かいことまとめ(late 2014)