【问题标题】:CallKit issue with Speaker, Automatically turned On after receiving the call扬声器的 CallKit 问题,接听电话后自动打开
【发布时间】:2018-05-02 10:27:51
【问题描述】:

我正在使用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];
        }
}

到目前为止,有没有人有任何建议或任何人已经纠正了这种状态?

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

任何帮助都将不胜感激。

谢谢

【问题讨论】:

  • 如果我正确理解了您的问题,您正在尝试在接听电话时禁用音频。如果是这样的话,接听电话就应该激活扬声器不是常识吗?如果用户没有准备好,他们就不会接受。你怎么看? @Abhishek Mitra
  • @LucasHuang 感谢您的回复,我面临的是,当接收器接到电话时,扬声器变为活动状态(在响亮模式下)并且通过录音,它不会变得无法听。接听电话时,扬声器不应大声。
  • 当您说扬声器时,您指的是物理扬声器吗?那么,您不能通过点击扬声器上的静音按钮来静音吗?我也不明白你所说的响亮模式。你能详细说明一下吗?
  • @LucasHuang 感谢您对我的问题感到好奇,我将发布一个屏幕截图,希望您现在能明白。图片链接:ibb.co/nnX91J
  • @AbhishekMitra 您找到解决此问题的方法了吗?我有同样的问题

标签: ios swift avaudiosession tokbox callkit


【解决方案1】:

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

audioOptions |= AVAudioSessionCategoryOptionDefaultToSpeaker;

希望它能拯救许多人的一天。

谢谢。

【讨论】:

  • 非常感谢,我会在几个小时内对其进行测试,然后告诉您进展如何
  • 现在其中一台设备正常,但另一台设备仍在扬声器中,可能与设备有关,我仍然会评价您的回答,因为它有点帮助:)
  • 接收者应该禁用扬声器,关于来电者,我实际上不知道。你要为谁得到什么? @stan
  • 似乎它发生在同一设备上参考:扬声器已打开。不管是接电话还是接电话
  • @stan,假设我有两个设备,即设备 A 和设备 B,如果我从设备 A 向设备 B 拨打电话,设备 B 的 CallKit UI 将不会显示启用扬声器,如果它仅在音频聊天中。我不知道设备 A。因为我已经为视频通话制作了我的应用程序。但在此之前我已经测试并且它正在工作。
【解决方案2】:

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

首先,我已将 Objective C 类 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];

【讨论】:

  • 伟大的工作斯坦,我一定会在需要时使用你的代码,你的答案值得投票。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-17
  • 1970-01-01
  • 2019-10-04
相关资源
最近更新 更多