選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

JMCallKitProxy.swift 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * Copyright @ 2019-present 8x8, Inc.
  3. * Copyright @ 2018-2019 Atlassian Pty Ltd
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. import CallKit
  18. import Foundation
  19. /// JitsiMeet CallKit proxy
  20. // NOTE: The methods this class exposes are meant to be called in the UI thread.
  21. // All delegate methods called by JMCallKitEmitter will be called in the UI thread.
  22. @objc public final class JMCallKitProxy: NSObject {
  23. private override init() {}
  24. // MARK: - CallKit proxy
  25. private static var provider: CXProvider = {
  26. let configuration = CXProviderConfiguration(localizedName: "")
  27. return CXProvider(configuration: configuration)
  28. }()
  29. private static var providerConfiguration: CXProviderConfiguration? {
  30. didSet {
  31. guard let configuration = providerConfiguration else { return }
  32. provider.configuration = configuration
  33. provider.setDelegate(emitter, queue: nil)
  34. }
  35. }
  36. private static let callController: CXCallController = {
  37. return CXCallController()
  38. }()
  39. private static let emitter: JMCallKitEmitter = {
  40. return JMCallKitEmitter()
  41. }()
  42. /// Enables the proxy in between CallKit and the consumers of the SDK.
  43. /// Defaults to enabled, set to false when you don't want to use CallKit.
  44. @objc public static var enabled: Bool = true {
  45. didSet {
  46. provider.invalidate()
  47. if enabled {
  48. guard isProviderConfigured() else { return; }
  49. provider = CXProvider(configuration: providerConfiguration!)
  50. provider.setDelegate(emitter, queue: nil)
  51. } else {
  52. provider.setDelegate(nil, queue: nil)
  53. }
  54. }
  55. }
  56. @objc public static func configureProvider(localizedName: String,
  57. ringtoneSound: String?,
  58. iconTemplateImageData: Data?) {
  59. guard enabled else { return }
  60. let configuration = CXProviderConfiguration(localizedName: localizedName)
  61. configuration.iconTemplateImageData = iconTemplateImageData
  62. configuration.maximumCallGroups = 1
  63. configuration.maximumCallsPerCallGroup = 1
  64. configuration.ringtoneSound = ringtoneSound
  65. configuration.supportedHandleTypes = [CXHandle.HandleType.generic]
  66. configuration.supportsVideo = true
  67. providerConfiguration = configuration
  68. }
  69. @objc public static func isProviderConfigured() -> Bool {
  70. return providerConfiguration != nil
  71. }
  72. @objc public static func addListener(_ listener: JMCallKitListener) {
  73. emitter.addListener(listener)
  74. }
  75. @objc public static func removeListener(_ listener: JMCallKitListener) {
  76. emitter.removeListener(listener)
  77. }
  78. @objc public static func hasActiveCallForUUID(_ callUUID: String) -> Bool {
  79. let activeCallForUUID = callController.callObserver.calls.first {
  80. $0.uuid == UUID(uuidString: callUUID)
  81. }
  82. guard activeCallForUUID != nil else { return false }
  83. return true
  84. }
  85. @objc public static func reportNewIncomingCall(
  86. UUID: UUID,
  87. handle: String?,
  88. displayName: String?,
  89. hasVideo: Bool,
  90. completion: @escaping (Error?) -> Void) {
  91. guard enabled else { return }
  92. let callUpdate = makeCXUpdate(handle: handle,
  93. displayName: displayName,
  94. hasVideo: hasVideo)
  95. provider.reportNewIncomingCall(with: UUID,
  96. update: callUpdate,
  97. completion: completion)
  98. }
  99. @objc public static func reportCallUpdate(with UUID: UUID,
  100. handle: String?,
  101. displayName: String?,
  102. hasVideo: Bool) {
  103. guard enabled else { return }
  104. let callUpdate = makeCXUpdate(handle: handle,
  105. displayName: displayName,
  106. hasVideo: hasVideo)
  107. provider.reportCall(with: UUID, updated: callUpdate)
  108. }
  109. @objc public static func reportCall(
  110. with UUID: UUID,
  111. endedAt dateEnded: Date?,
  112. reason endedReason: CXCallEndedReason) {
  113. guard enabled else { return }
  114. provider.reportCall(with: UUID,
  115. endedAt: dateEnded,
  116. reason: endedReason)
  117. }
  118. @objc public static func reportOutgoingCall(
  119. with UUID: UUID,
  120. startedConnectingAt dateStartedConnecting: Date?) {
  121. guard enabled else { return }
  122. provider.reportOutgoingCall(with: UUID,
  123. startedConnectingAt: dateStartedConnecting)
  124. }
  125. @objc public static func reportOutgoingCall(
  126. with UUID: UUID,
  127. connectedAt dateConnected: Date?) {
  128. guard enabled else { return }
  129. provider.reportOutgoingCall(with: UUID, connectedAt: dateConnected)
  130. }
  131. @objc public static func request(
  132. _ transaction: CXTransaction,
  133. completion: @escaping (Error?) -> Swift.Void) {
  134. guard enabled else { return }
  135. callController.request(transaction, completion: completion)
  136. }
  137. // MARK: - Callkit Proxy helpers
  138. private static func makeCXUpdate(handle: String?,
  139. displayName: String?,
  140. hasVideo: Bool) -> CXCallUpdate {
  141. let update = CXCallUpdate()
  142. update.supportsDTMF = false
  143. update.supportsHolding = false
  144. update.supportsGrouping = false
  145. update.supportsUngrouping = false
  146. update.hasVideo = hasVideo
  147. if let handle = handle {
  148. update.remoteHandle = CXHandle(type: .generic,
  149. value: handle)
  150. }
  151. if let displayName = displayName {
  152. update.localizedCallerName = displayName
  153. }
  154. return update
  155. }
  156. }