扬声器的 CallKit 问题,接听电话后自动打开

CallKit issue with Speaker, Automatically turned On after receiving the call

我正在使用 CallKitTokBox 以及它如何处理一个错误,即接听电话后,扬声器变为活动状态,无法通过点击它来禁用。通话从主动扬声器开始,我认为这是一个错误,但 WhatsApp 和 FBMassenger 在他们的自定义呼叫屏幕视图中使用了相同的功能,但他们的扬声器在接到电话后变得不活动,我搜索了这个电话但没有找到相关答案所以远.

TokBox 中,他们提供了 OTDefaultAudioDevice.hOTDefaultAudioDevice.m 文件,他们从那里配置了所有关于音频的 CallKitSpeakerBox 文件。我在哪里找到以下配置:

#define AUDIO_DEVICE_HEADSET     @"AudioSessionManagerDevice_Headset"
#define AUDIO_DEVICE_BLUETOOTH   @"AudioSessionManagerDevice_Bluetooth"
#define AUDIO_DEVICE_SPEAKER     @"AudioSessionManagerDevice_Speaker"

使用方式如下:

- (BOOL)configureAudioSessionWithDesiredAudioRoute:(NSString*)desiredAudioRoute
{
    OT_AUDIO_DEBUG(@"configureAudioSessionWithDesiredAudioRoute %@",desiredAudioRoute);

    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    NSError *err;

    //ios 8.0 complains about Deactivating an audio session that has running
    // I/O. All I/O should be stopped or paused prior to deactivating the audio
    // session. Looks like we can get away by not using the setActive call
    if (SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(@"7.0")) {
        // close down our current session...
        [audioSession setActive:NO error:nil];
    }

    if ([AUDIO_DEVICE_BLUETOOTH isEqualToString:desiredAudioRoute]) {
        [self setBluetoothAsPrefferedInputDevice];
    }

    if (SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(@"7.0")) {
        // Set our session to active...
        if (![audioSession setActive:YES error:&err]) {
            NSLog(@"unable to set audio session active: %@", err);
            return NO;
        }
    }

    if ([AUDIO_DEVICE_SPEAKER isEqualToString:desiredAudioRoute]) {
        // replace AudiosessionSetProperty (deprecated from iOS7) with
        // AVAudioSession overrideOutputAudioPort
#if !(TARGET_OS_TV)
        [audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker
                                        error:&err];
#endif
    } else
    {
        [audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideNone
                                        error:&err];
    }

    return YES;
}

其中 AVAudioSessionPortOverrideSpeaker 用于所有设备,我认为这是启用扬声器的主要原因,但我不完全知道。即

if ([AUDIO_DEVICE_SPEAKER isEqualToString:desiredAudioRoute]) {
            // replace AudiosessionSetProperty (deprecated from iOS7) with
            // AVAudioSession overrideOutputAudioPort
    #if !(TARGET_OS_TV)
            [audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker
                                            error:&err];
    #endif
        } else
        {
            [audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideNone
                                            error:&err];
        }
}

有没有人有任何建议,或者这里有没有人已经纠正了这个状态?

我也相信很多像我一样的人正在经历这个问题。

任何帮助都将不胜感激。

谢谢

我已经通过 opentok 支持,他们认真对待这个问题,并且由于该服务仅用于视频聊天,因此他们在 CallKit UI 中启用了该扬声器。要通过使用他们的 Objective C class 即 OTDefaultAudioDevice.hOTDefaultAudioDevice.m 使其禁用或仅用于音频通话,那么我们必须在 [=12] 中注释以下行=] 文件.

audioOptions |= AVAudioSessionCategoryOptionDefaultToSpeaker;

希望它能拯救很多人。

谢谢。

终于解决了这个问题。解决方案是@AbhishekMitra 和我自己发现的东西的混合体

首先,我已将 Objective C class OTDefaultAudioDevice 替换为 DefaultAudioDevice.swift,此处找到: https://github.com/opentok/opentok-ios-sdk-samples-swift/blob/master/Custom-Audio-Driver/Custom-Audio-Driver/DefaultAudioDevice.swift

相当于 objc,注释掉 Abhishek 建议的行并在同一函数中添加另一行,即:

configureAudioSessionWithDesiredAudioRoute(desiredAudioRoute: DefaultAudioDevice.kAudioDeviceHeadset)

这是整个函数

fileprivate func setupAudioSession() {
        let session = AVAudioSession.sharedInstance()
        
        previousAVAudioSessionCategory = session.category
        avAudioSessionMode = session.mode
        avAudioSessionPreffSampleRate = session.preferredSampleRate
        avAudioSessionChannels = session.inputNumberOfChannels
        do {
            try session.setPreferredSampleRate(Double(DefaultAudioDevice.kSampleRate))
            try session.setPreferredIOBufferDuration(0.01)
            let audioOptions = AVAudioSessionCategoryOptions.mixWithOthers.rawValue |
                AVAudioSessionCategoryOptions.allowBluetooth.rawValue
                //|
                //AVAudioSessionCategoryOptions.defaultToSpeaker.rawValue
            try session.setCategory(AVAudioSessionCategoryPlayAndRecord, mode: AVAudioSessionModeVideoChat, options: AVAudioSessionCategoryOptions(rawValue: audioOptions))
            setupListenerBlocks()
            //set the audio to headset
            configureAudioSessionWithDesiredAudioRoute(desiredAudioRoute: DefaultAudioDevice.kAudioDeviceHeadset)
            
            try session.setActive(true)
        } catch let err as NSError {
            print("Error setting up audio session \(err)")
        } catch {
            print("Error setting up audio session")
        }
    }

这终于解决了我的问题,通话时设备没有打开扬声器。如果您有任何问题,请告诉我。

此行的 objc 版本为:

[self configureAudioSessionWithDesiredAudioRoute:
                 AUDIO_DEVICE_HEADSET];