ryotayama / hayaemon_ios_issues

4 stars 0 forks source link

音量が変えられなくなるケースがある #891

Closed ryotayama closed 1 month ago

ryotayama commented 2 months ago

問合せ559など多数

ハヤえもんで曲再生→カメラアプリ起動→写真撮る→ホーム画面に移動→音量の変更ができなくなる

ryotayama commented 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];
}
ryotayama commented 1 month ago

テストの結果、オーディオルートの変更は飛んでこず✍️

ryotayama commented 1 month ago

続いて、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]];
}
ryotayama commented 1 month ago

飛んでこず✍️

ryotayama commented 1 month ago

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];
}
ryotayama commented 1 month ago

飛んでこず✍️

ryotayama commented 1 month ago

AVAudioSessionCategoryPlayAndRecordをAVAudioSessionCategoryPlaybackに変更してみたところ、音量も問題は発生しなくなったものの、これだと録音ができない。

ryotayama commented 1 month ago

ためしにAVAudioSessionCategoryOptionMixWithOthersを指定してみたけどダメ。

ryotayama commented 1 month ago

748 録音開始時/停止時に再生中の曲が一瞬止まってしまう

↑これの元の仕様に戻せば少なくとも再生時は発生しなくなりそう(録音時はダメ)だけど、録音開始時/停止時に再生中の曲が一瞬止まってしまう仕様は復活してしまう。

ryotayama commented 1 month ago

今後の方針 ・一応、他のパラメータも試してみて、症状が改善するか点検 ・それでもダメなら録音時に再生中の音が一瞬止まる仕様を諦める  (ただし、その場合でも録音中の場合は写真を撮ると音量が変えられなくなるまま)

ryotayama commented 1 month ago

https://developer.apple.com/documentation/avfaudio/avaudiosessioncategoryoptions

ryotayama commented 1 month ago

現状

追加テスト

削除テスト

ryotayama commented 1 month ago

待てよ。Bluetoothデバイスが接続されている時だけ、AVAudioSessionCategoryOptionAllowBluetoothやAVAudioSessionCategoryOptionAllowBluetoothA2DPを指定するようにすれば被害を一番最小限にできるのではないか。

ryotayama commented 1 month ago

Bluetoothデバイスが接続されていない時

再生時、録音時

Bluetoothデバイスが接続されているとき

再生時

録音時

これによって、音量操作不能バグはBluetoothデバイスが接続されている時でかつ録音時のみに絞られる。

ryotayama commented 1 month ago

こういう感じ?(未テスト)

// 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;
}
ryotayama commented 1 month ago

アプリの実行中にBluetoothデバイスが接続、解除されるケースもあるから、オーディオルート変更通知のチェックも必要✍️

ryotayama commented 1 month ago

残作業

ryotayama commented 1 month ago

↑でも写真のタイミングで音量が変えられなくなるケースを見つけた。Bluetoothの接続有無にかかわらず再生時はPlaybackにするしかなさそう。