CallKit 可以在交换通话后重新激活声音
Posted
技术标签:
【中文标题】CallKit 可以在交换通话后重新激活声音【英文标题】:CallKit can reactivate sound after swapping call 【发布时间】:2017-11-21 15:16:43 【问题描述】:我正在开发 CallKit 应用程序,我有一个问题,在 CallKit 屏幕上“交换”呼叫时,呼叫保持无法重新启动音频,直到用户返回到应用内呼叫屏幕。我可以通过更新绕过这个:
supportsHolding = false
但是我可以解决这个问题,例如 whatsapp 可以正确地做到这一点!
附言我正在使用 webrtc 拨打电话!
谢谢!
编辑:
这是提供者的代码:
public func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction)
guard let call = conductor!.callWithUUID(uuid: action.callUUID) else
WebRtcConductor.debug("\(self.TAG) ???? failed to perform HeldAction: uuid: \(action.uuid), calluiid: \(action.callUUID)")
action.fail()
return
setIsHeld(call: call, isHeld: action.isOnHold)
action.fulfill()
setIsHeld 函数简单地做:
audioTrack.isEnabled = enabled
如果我使用 callkit 屏幕的“静音”按钮,一切正常,但如果我有 2 个活动呼叫,当我从 webrtc 呼叫滑动到正常呼叫时,调用 CXSetHeldCallAction 并且音轨确实被禁用,如果我再次滑动到webrtc 调用,音轨已启用,但我什么也没听到,如果我返回主应用程序屏幕,音频又可以正常工作了!
【问题讨论】:
请展示您编写的相关代码,但也要清楚说明会发生什么以及您期望会发生什么。 我添加了更多代码!谢谢! 嗨@LucaBecchetti,你解决了这个问题吗? 【参考方案1】:实际上,在实现支持交换调用的 CallKit 集成时,Google WebRTC 库中存在一个限制,这会导致所描述的问题。
WebRTC Issue 8126 已知已有一年多,但尚未集成到 WebRTC 主分支中。但是,您可以在原始票证中找到必要的代码更改来解决此问题。
但是,作为一种解决方法,您可以触发 WebRTC 内部订阅的系统通知。
在 CallKit Provider 的“didActivate audiosession
”方法中发布AVAudioSessionInterruptionType.ended
通知:
var userInfo = Dictionary<AnyHashable, Any>()
let interrupttioEndedRaw = AVAudioSessionInterruptionType.ended.rawValue
userInfo[AVAudioSessionInterruptionTypeKey] = interrupttioEndedRaw
NotificationCenter.default.post(name: NSNotification.Name.AVAudioSessionInterruption, object: self, userInfo: userInfo)
PS:盯着票以增加合并的机会;-)
【讨论】:
对于 Swift 4:NotificationCenter.default.post(name: AVAudioSession.interruptionNotification, object: self, userInfo: userInfo)
我应该在哪里使用它?填满后?
@WorieN in 'didActivate audioSession'
感谢您为我工作。 func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) print("Provider - Activate Audio Session: (audioSession.category)") var userInfo = Dictionary() let interrupttioEndedRaw = AVAudioSession.InterruptionType.ended。 rawValue userInfo[AVAudioSessionInterruptionTypeKey] = interrupttioEndedRaw NotificationCenter.default.post(name: AVAudioSession.interruptionNotification, object: self, userInfo: userInfo)
对我来说很酷,我使用 Tokbox 而不是 Google WebRTC,尝试了所有方法但没有让它工作,但触发系统通知让它也适用于 Tokbox!谢谢!【参考方案2】:
有同样的问题。如果我有 1 个活动呼叫,然后有新呼叫,我点击保持并接受。新通话有效,但在 CallKit
中使用 Swap
后音频停止工作。
发现CXProviderDelegate
协议中的provider:performSetHeldCallAction:
方法是您可以通过CallKit
本机接口为Swap
调用实际停用/激活音频的地方。
在我的例子中,我使用audioController.deactivateAudioSession()
方法将呼叫置于 OnHold 中。
但发现当通过 CallKit 轻按 Swap
按钮时,对于其他处于活动状态(从 OnHold 状态)的呼叫,会触发相同的方法 provider:performSetHeldCallAction:
。
因此,您只需分别停用/激活音频即可进入通话状态(保持或不保持)。
通常它应该是这样的:
func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction)
// Retrieve the Call instance corresponding to the action's call UUID
guard let call = callManager.callWithUUID(uuid: action.callUUID) else
action.fail()
return
// Update the Call's underlying hold state.
call.isOnHold = action.isOnHold
// Stop or start audio in response to holding or unholding the call.
if call.isOnHold
stopAudio()
else
startAudio()
// Signal to the system that the action has been successfully performed.
action.fulfill()
附:看起来您应该有一些响应音频会话的类。它应该实现activate audio session
/ deactivate audio session
。
【讨论】:
这在我的情况下不起作用。我也在使用 WebRTC 并将audioTrack.isEnabled
设置为false
(对于本地和远程轨道)。这可能与 WebRTC 如何在内部处理音频有关。但是,在交换呼叫后(通过按 CallKit UI 中的“我的应用程序”按钮)强制应用程序回到前台时,音频再次工作(传入和传出 - 这很神奇)。
哦,我面临着完全相同的问题。你解决了这个问题吗?
@Bogdan 你找到解决这个问题的方法了吗?
@AhadKhan 不幸的是,那个项目是 2 年前的,从那以后我就没有参与过那个项目。从那时起,Swift 版本也发生了变化。因此,您可以将该想法用作方法或模式。对我来说,它确实有效,并且在通过本机 iOS 界面交换呼叫时真正解决了声音问题
@AhadKhan 我看到你正在使用 WebRTC。这可能是个问题。您需要检查声音的“静音”/“取消静音”方法类型,或者检查流是否暂停或取消暂停。以上是关于CallKit 可以在交换通话后重新激活声音的主要内容,如果未能解决你的问题,请参考以下文章
当我从 callKit 结束通话时,通话没有结束,我可以看到绿色的状态栏