Closed ryotayama closed 1 month ago
バックグラウンドで写真が撮られた!という検知はできなさそう。 オーディオルートの変更が飛んでくるか、要調査。
#import <AVFoundation/AVFoundation.h>
// Notificationの登録
- (void)registerForAudioRouteChangeNotifications {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleRouteChange:)
name:AVAudioSessionRouteChangeNotification
object:nil];
}
// オーディオルート変更時の処理
- (void)handleRouteChange:(NSNotification *)notification {
NSDictionary *userInfo = notification.userInfo;
AVAudioSessionRouteChangeReason reason = [userInfo[AVAudioSessionRouteChangeReasonKey] unsignedIntegerValue];
switch (reason) {
case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
// 新しいデバイスが接続された場合の処理
NSLog(@"New device available");
break;
case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
// デバイスが切断された場合の処理
NSLog(@"Old device unavailable");
break;
case AVAudioSessionRouteChangeReasonCategoryChange:
// オーディオセッションのカテゴリーが変更された場合の処理
NSLog(@"Audio session category changed");
break;
default:
break;
}
}
// Notificationの解除(deallocなどで呼び出す)
- (void)unregisterForAudioRouteChangeNotifications {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:AVAudioSessionRouteChangeNotification
object:nil];
}
テストの結果、オーディオルートの変更は飛んでこず✍️
続いて、AVAudioSessionInterruptionNotificationが飛んでこないか試してみる。
#import <AVFoundation/AVFoundation.h>
// Interruptionの監視
- (void)startMonitoringAudioInterruptions {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleInterruption:)
name:AVAudioSessionInterruptionNotification
object:[AVAudioSession sharedInstance]];
}
// Interruption通知の処理
- (void)handleInterruption:(NSNotification *)notification {
NSDictionary *info = notification.userInfo;
AVAudioSessionInterruptionType type = [info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
if (type == AVAudioSessionInterruptionTypeBegan) {
NSLog(@"Audio session interrupted (began)");
// 中断時の処理
} else if (type == AVAudioSessionInterruptionTypeEnded) {
NSLog(@"Audio session interruption ended");
// 中断終了後の処理
NSError *error = nil;
[[AVAudioSession sharedInstance] setActive:YES error:&error];
if (error) {
NSLog(@"Error resuming audio session: %@", error.localizedDescription);
}
}
}
// Interruption監視の解除
- (void)stopMonitoringAudioInterruptions {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:AVAudioSessionInterruptionNotification
object:[AVAudioSession sharedInstance]];
}
飛んでこず✍️
AVSystemController_SystemVolumeDidChangeNotificationで音量の変更を監視するって路線はどうかな?
#import <MediaPlayer/MediaPlayer.h>
// 音量変更の監視
- (void)startMonitoringVolumeChanges {
// MPVolumeViewを非表示で作成
MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:CGRectZero];
[self.view addSubview:volumeView];
volumeView.hidden = YES; // ユーザーに見えないように非表示にします。
// 音量変更の監視
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(volumeChanged:)
name:@"AVSystemController_SystemVolumeDidChangeNotification"
object:nil];
}
// 音量変更時の処理
- (void)volumeChanged:(NSNotification *)notification {
float volume = [notification.userInfo[@"AVSystemController_AudioVolumeNotificationParameter"] floatValue];
NSLog(@"Volume changed: %f", volume);
}
// 音量変更監視の解除
- (void)stopMonitoringVolumeChanges {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:@"AVSystemController_SystemVolumeDidChangeNotification"
object:nil];
}
飛んでこず✍️
AVAudioSessionCategoryPlayAndRecordをAVAudioSessionCategoryPlaybackに変更してみたところ、音量も問題は発生しなくなったものの、これだと録音ができない。
ためしにAVAudioSessionCategoryOptionMixWithOthersを指定してみたけどダメ。
↑これの元の仕様に戻せば少なくとも再生時は発生しなくなりそう(録音時はダメ)だけど、録音開始時/停止時に再生中の曲が一瞬止まってしまう仕様は復活してしまう。
今後の方針 ・一応、他のパラメータも試してみて、症状が改善するか点検 ・それでもダメなら録音時に再生中の音が一瞬止まる仕様を諦める (ただし、その場合でも録音中の場合は写真を撮ると音量が変えられなくなるまま)
待てよ。Bluetoothデバイスが接続されている時だけ、AVAudioSessionCategoryOptionAllowBluetoothやAVAudioSessionCategoryOptionAllowBluetoothA2DPを指定するようにすれば被害を一番最小限にできるのではないか。
これによって、音量操作不能バグはBluetoothデバイスが接続されている時でかつ録音時のみに絞られる。
こういう感じ?(未テスト)
// Bluetoothデバイスが接続されているかをチェックする関数
- (BOOL)isBluetoothDeviceConnected {
AVAudioSessionRouteDescription *routeDescription = [[AVAudioSession sharedInstance] currentRoute];
for (AVAudioSessionPortDescription *output in routeDescription.outputs) {
// Bluetoothデバイスが接続されているかをチェック
if ([output.portType isEqualToString:AVAudioSessionPortBluetoothA2DP] ||
[output.portType isEqualToString:AVAudioSessionPortBluetoothHFP] ||
[output.portType isEqualToString:AVAudioSessionPortBluetoothLE]) {
// Bluetoothデバイスが接続されている場合
NSLog(@"Bluetooth device connected: %@", output.portType);
return YES;
}
}
// Bluetoothデバイスが接続されていない場合
NSLog(@"No Bluetooth device connected");
return NO;
}
アプリの実行中にBluetoothデバイスが接続、解除されるケースもあるから、オーディオルート変更通知のチェックも必要✍️
↑でも写真のタイミングで音量が変えられなくなるケースを見つけた。Bluetoothの接続有無にかかわらず再生時はPlaybackにするしかなさそう。
問合せ559など多数
ハヤえもんで曲再生→カメラアプリ起動→写真撮る→ホーム画面に移動→音量の変更ができなくなる