必要があって調べていましたが、
ネット上の情報が古くなってきていると感じたので書きます。
AVAudioSession
を使います。
init
// 明示的にアクティブにしておく必要があった
[[AVAudioSession sharedInstance] setActive:YES error:nil];
// Notificationの設定
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didChangeAudioSessionRoute:) name:AVAudioSessionRouteChangeNotification object:nil];
で、上で指定した`didChangeAudioSessionRoute:に状態の変更が通知されるので、今どうなってるか調べればいい。
notification
- (void)didChangeAudioSessionRoute:(NSNotification *)notification
{
for (AVAudioSessionPortDescription *desc in [[[AVAudioSession sharedInstance] currentRoute] outputs]) {
if ([desc.portType isEqual:AVAudioSessionPortHeadphones]) {
NSLog(@"ヘッドホン刺さった");
} else {
NSLog(@"ヘッドホン抜けた");
}
}
}
さくっとならコレで十分だと思いますが、本当に ヘッドホンが抜けた とか 刺さった 状態であるかどうかは、直前の状態を見ないとわからないので、
もうちょっと詳しく書くと以下のようになります。
notification2
- (void)didChangeAudioSessionRoute:(NSNotification *)notification
{
// ヘッドホンが刺さっていたか取得
BOOL (^isJointHeadphone)(NSArray *) = ^(NSArray *outputs){
for (AVAudioSessionPortDescription *desc in outputs) {
if ([desc.portType isEqual:AVAudioSessionPortHeadphones]) {
return YES;
}
}
return NO;
};
// 直前の状態を取得
AVAudioSessionRouteDescription *prevDesc = notification.userInfo[AVAudioSessionRouteChangePreviousRouteKey];
if (isJointHeadphone([[[AVAudioSession sharedInstance] currentRoute] outputs])) {
if (!isJointHeadphone(prevDesc.outputs)) {
NSLog(@"ヘッドフォンが刺さった");
}
} else {
if(isJointHeadphone(prevDesc.outputs)) {
NSLog(@"ヘッドフォンが抜かれた");
}
}
}
userInfo
で直前の状態が取れるので、その時ヘッドホンが刺さっていたかどうかを調べています。
なんだか、あまり効率的ではなさそうですが
userInfo
からAVAudioSessionRouteChangeReasonKey
でAVAudioSessionRouteChangeReason
が取得できますので、その中の
AVAudioSessionRouteChangeReasonNewDeviceAvailable
AVAudioSessionRouteChangeReasonOldDeviceUnavailable
ここら変を見るようにすればもうちょっと無駄なく書けそうかな。