CallProviderDelegate.swift 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. //
  2. // CallProviderDelegate.swift
  3. // FloatingButtonApp
  4. //
  5. // Created by Yayan Dwi on 10/08/21.
  6. //
  7. import Foundation
  8. import UIKit
  9. import CallKit
  10. import AVFoundation
  11. import SwiftUI
  12. import nuSDKService
  13. class CallProviderDelegate: NSObject {
  14. static let providerConfiguration: CXProviderConfiguration = {
  15. let providerConfiguration = CXProviderConfiguration()
  16. providerConfiguration.maximumCallsPerCallGroup = 4
  17. providerConfiguration.maximumCallGroups = 5
  18. providerConfiguration.supportsVideo = true
  19. providerConfiguration.supportedHandleTypes = [.phoneNumber]
  20. // providerConfiguration.ringtoneSound = "call_in.mp3"
  21. return providerConfiguration
  22. }()
  23. let callManager: CallManager
  24. private let provider: CXProvider
  25. init(callManager: CallManager) {
  26. self.callManager = callManager
  27. provider = CXProvider(configuration: type(of: self).providerConfiguration)
  28. super.init()
  29. provider.setDelegate(self, queue: nil)
  30. }
  31. func reportIncomingCall(uuid: UUID, handle: String, hasVideo: Bool = false, completion: ((Error?) -> Void)? = nil) {
  32. let update = CXCallUpdate()
  33. if let user = User.getData(pin: handle) {
  34. update.remoteHandle = CXHandle(type: .phoneNumber, value: user.fullName)
  35. }
  36. update.hasVideo = hasVideo
  37. update.supportsGrouping = true
  38. update.supportsUngrouping = true
  39. update.supportsHolding = true
  40. provider.reportNewIncomingCall(with: uuid, update: update) { error in
  41. if error == nil {
  42. let call = Call(uuid: uuid)
  43. call.handle = handle
  44. call.hasVideo = hasVideo
  45. Nexilis.startAudio(nMode: 1, bSpeakerOn: false)
  46. self.callManager.addCall(call)
  47. }
  48. completion?(error)
  49. }
  50. }
  51. }
  52. extension CallProviderDelegate: CXProviderDelegate {
  53. func providerDidReset(_ provider: CXProvider) {
  54. print("providerDidReset...")
  55. for call in callManager.calls {
  56. call.endCall()
  57. }
  58. callManager.removeAllCalls()
  59. }
  60. func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
  61. print("CXStartCallAction...\(action.callUUID)")
  62. let call = Call(uuid: action.callUUID, isOutgoing: true)
  63. call.handle = action.handle.value
  64. call.hasStartedConnectingDidChange = { [weak self] in
  65. self?.provider.reportOutgoingCall(with: call.uuid, startedConnectingAt: call.connectingDate)
  66. }
  67. call.hasConnectedDidChange = { [weak self] in
  68. self?.provider.reportOutgoingCall(with: call.uuid, connectedAt: call.connectDate)
  69. }
  70. if self.callManager.calls.count == 0 {
  71. Nexilis.startAudio(nMode: 1, bSpeakerOn: false)
  72. } else if self.callManager.calls.count > 0 {
  73. self.callManager.setOnHoldStatus(for: self.callManager.calls.last!, to: true)
  74. }
  75. action.fulfill()
  76. print("JUMLAH START CALL \(self.callManager.calls.count)")
  77. self.callManager.addCall(call)
  78. if self.callManager.calls.count > 1 {
  79. API.initiateCCall(sParty: call.handle)
  80. }
  81. }
  82. func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
  83. print("CXAnswerCallAction...\(action.callUUID)")
  84. guard let call = callManager.callWithUUID(uuid: action.callUUID) else {
  85. action.fail()
  86. return
  87. }
  88. call.answerCall()
  89. action.fulfill()
  90. if call.hasVideo {
  91. } else {
  92. let controller = QmeraAudioViewController()
  93. controller.user = User.getData(pin: call.handle)
  94. controller.isOnGoing = true
  95. controller.isOutgoing = false
  96. controller.modalPresentationStyle = .overCurrentContext
  97. if UIApplication.shared.visibleViewController?.navigationController != nil {
  98. UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
  99. } else {
  100. UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
  101. }
  102. }
  103. }
  104. func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
  105. print("CXEndCallAction...\(action.callUUID)")
  106. guard let call = callManager.callWithUUID(uuid: action.callUUID) else {
  107. action.fail()
  108. return
  109. }
  110. call.endCall()
  111. action.fulfill()
  112. self.callManager.removeCall(call)
  113. print("JUMLAH CALL \(self.callManager.calls.count)")
  114. if self.callManager.calls.count == 0, !call.isReceiveEnd {
  115. print("MASUK TERMINATE CALL DELEGATE")
  116. API.terminateCall(sParty: nil)
  117. DispatchQueue.global().async {
  118. if let pin = call.handle {
  119. _ = Nexilis.write(message: CoreMessage_TMessageBank.endCall(pin: pin))
  120. }
  121. }
  122. }
  123. }
  124. func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) {
  125. print("CXSetHeldCallAction...\(action.callUUID)")
  126. guard let call = callManager.callWithUUID(uuid: action.callUUID) else {
  127. action.fail()
  128. return
  129. }
  130. call.isOnHold = action.isOnHold
  131. if call.isOnHold {
  132. // pause??
  133. } else {
  134. // resume??
  135. }
  136. action.fulfill()
  137. }
  138. func provider(_ provider: CXProvider, timedOutPerforming action: CXAction) {
  139. print("Timed out", #function)
  140. }
  141. func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
  142. print("Received", #function)
  143. /*
  144. Start call audio media, now that the audio session is activated,
  145. after having its priority elevated.
  146. */
  147. if let call = self.callManager.calls.last {
  148. if call.isOutgoing {
  149. API.initiateCCall(sParty: call.handle)
  150. } else {
  151. API.receiveCCall(sParty: call.handle)
  152. }
  153. }
  154. }
  155. func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
  156. print("Received", #function)
  157. // do {
  158. // try AVAudioSession.sharedInstance().setCategory(.ambient)
  159. // try AVAudioSession.sharedInstance().setMode(.default)
  160. // try AVAudioSession.sharedInstance().overrideOutputAudioPort(.none)
  161. // } catch {
  162. // }
  163. /*
  164. Restart any non-call related audio now that the app's audio session is deactivated,
  165. after having its priority restored to normal.
  166. */
  167. }
  168. }