Call.swift 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. //
  2. // Call.swift
  3. // flutter_callkit_incoming
  4. //
  5. // Created by Hien Nguyen on 07/10/2021.
  6. //
  7. import Foundation
  8. import AVFoundation
  9. public class Call: NSObject {
  10. public var uuid: UUID
  11. public var data: Data
  12. public var isOutGoing: Bool
  13. public var handle: String?
  14. var stateDidChange: (() -> Void)?
  15. var hasStartedConnectDidChange: (() -> Void)?
  16. var hasConnectDidChange: (() -> Void)?
  17. var hasEndedDidChange: (() -> Void)?
  18. var connectData: Date?{
  19. didSet{
  20. stateDidChange?()
  21. hasStartedConnectDidChange?()
  22. }
  23. }
  24. var connectedData: Date?{
  25. didSet{
  26. stateDidChange?()
  27. hasConnectDidChange?()
  28. }
  29. }
  30. var endDate: Date?{
  31. didSet{
  32. stateDidChange?()
  33. hasEndedDidChange?()
  34. }
  35. }
  36. var isOnHold = false{
  37. didSet{
  38. stateDidChange?()
  39. }
  40. }
  41. var isMuted = false{
  42. didSet{
  43. }
  44. }
  45. var hasStartedConnecting: Bool{
  46. get{
  47. return connectData != nil
  48. }
  49. set{
  50. connectData = newValue ? Date() : nil
  51. }
  52. }
  53. var hasConnected: Bool {
  54. get{
  55. return connectedData != nil
  56. }
  57. set{
  58. connectedData = newValue ? Date() : nil
  59. }
  60. }
  61. var hasEnded: Bool {
  62. get{
  63. return endDate != nil
  64. }
  65. set{
  66. endDate = newValue ? Date() : nil
  67. }
  68. }
  69. var duration: TimeInterval {
  70. guard let connectDate = connectedData else {
  71. return 0
  72. }
  73. return Date().timeIntervalSince(connectDate)
  74. }
  75. init(uuid: UUID, data: Data, isOutGoing: Bool = false){
  76. self.uuid = uuid
  77. self.data = data
  78. self.isOutGoing = isOutGoing
  79. }
  80. var startCallCompletion: ((Bool) -> Void)?
  81. func startCall(withAudioSession audioSession: AVAudioSession ,completion :((_ success : Bool)->Void)?){
  82. startCallCompletion = completion
  83. hasStartedConnecting = true
  84. }
  85. var answCallCompletion :((Bool) -> Void)?
  86. func ansCall(withAudioSession audioSession: AVAudioSession ,completion :((_ success : Bool)->Void)?){
  87. answCallCompletion = completion
  88. hasStartedConnecting = true
  89. }
  90. var connectedCallCompletion: ((Bool) -> Void)?
  91. func connectedCall(completion :((_ success : Bool)->Void)?){
  92. connectedCallCompletion = completion
  93. hasConnected = true
  94. }
  95. func endCall(){
  96. hasEnded = true
  97. }
  98. func startAudio() {
  99. }
  100. }
  101. @objc public class Data: NSObject {
  102. @objc public var uuid: String
  103. @objc public var nameCaller: String
  104. @objc public var appName: String
  105. @objc public var handle: String
  106. @objc public var avatar: String
  107. @objc public var type: Int
  108. @objc public var normalHandle: Int
  109. @objc public var duration: Int
  110. @objc public var extra: NSDictionary
  111. //iOS
  112. @objc public var iconName: String
  113. @objc public var handleType: String
  114. @objc public var supportsVideo: Bool
  115. @objc public var maximumCallGroups: Int
  116. @objc public var maximumCallsPerCallGroup: Int
  117. @objc public var supportsDTMF: Bool
  118. @objc public var supportsHolding: Bool
  119. @objc public var supportsGrouping: Bool
  120. @objc public var supportsUngrouping: Bool
  121. @objc public var includesCallsInRecents: Bool
  122. @objc public var ringtonePath: String
  123. @objc public var configureAudioSession: Bool
  124. @objc public var audioSessionMode: String
  125. @objc public var audioSessionActive: Bool
  126. @objc public var audioSessionPreferredSampleRate: Double
  127. @objc public var audioSessionPreferredIOBufferDuration: Double
  128. @objc public init(id: String, nameCaller: String, handle: String, type: Int) {
  129. self.uuid = id
  130. self.nameCaller = nameCaller
  131. self.appName = "Callkit"
  132. self.handle = handle
  133. self.avatar = ""
  134. self.type = type
  135. self.normalHandle = 0
  136. self.duration = 30000
  137. self.extra = [:]
  138. self.iconName = "CallKitLogo"
  139. self.handleType = ""
  140. self.supportsVideo = true
  141. self.maximumCallGroups = 2
  142. self.maximumCallsPerCallGroup = 1
  143. self.supportsDTMF = true
  144. self.supportsHolding = true
  145. self.supportsGrouping = true
  146. self.supportsUngrouping = true
  147. self.includesCallsInRecents = true
  148. self.ringtonePath = ""
  149. self.configureAudioSession = true
  150. self.audioSessionMode = ""
  151. self.audioSessionActive = true
  152. self.audioSessionPreferredSampleRate = 44100.0
  153. self.audioSessionPreferredIOBufferDuration = 0.005
  154. }
  155. @objc public convenience init(args: NSDictionary) {
  156. var argsConvert = [String: Any?]()
  157. for (key, value) in args {
  158. argsConvert[key as! String] = value
  159. }
  160. self.init(args: argsConvert)
  161. }
  162. public init(args: [String: Any?]) {
  163. self.uuid = args["id"] as? String ?? ""
  164. self.nameCaller = args["nameCaller"] as? String ?? ""
  165. self.appName = args["appName"] as? String ?? "Callkit"
  166. self.handle = args["handle"] as? String ?? ""
  167. self.avatar = args["avatar"] as? String ?? ""
  168. self.type = args["type"] as? Int ?? 0
  169. self.normalHandle = args["normalHandle"] as? Int ?? 0
  170. self.duration = args["duration"] as? Int ?? 30000
  171. self.extra = args["extra"] as? NSDictionary ?? [:]
  172. if let ios = args["ios"] as? [String: Any] {
  173. self.iconName = ios["iconName"] as? String ?? "CallKitLogo"
  174. self.handleType = ios["handleType"] as? String ?? ""
  175. self.supportsVideo = ios["supportsVideo"] as? Bool ?? true
  176. self.maximumCallGroups = ios["maximumCallGroups"] as? Int ?? 2
  177. self.maximumCallsPerCallGroup = ios["maximumCallsPerCallGroup"] as? Int ?? 1
  178. self.supportsDTMF = ios["supportsDTMF"] as? Bool ?? true
  179. self.supportsHolding = ios["supportsHolding"] as? Bool ?? true
  180. self.supportsGrouping = ios["supportsGrouping"] as? Bool ?? true
  181. self.supportsUngrouping = ios["supportsUngrouping"] as? Bool ?? true
  182. self.includesCallsInRecents = ios["includesCallsInRecents"] as? Bool ?? true
  183. self.ringtonePath = ios["ringtonePath"] as? String ?? ""
  184. self.configureAudioSession = ios["configureAudioSession"] as? Bool ?? true
  185. self.audioSessionMode = ios["audioSessionMode"] as? String ?? ""
  186. self.audioSessionActive = ios["audioSessionActive"] as? Bool ?? true
  187. self.audioSessionPreferredSampleRate = ios["audioSessionPreferredSampleRate"] as? Double ?? 44100.0
  188. self.audioSessionPreferredIOBufferDuration = ios["audioSessionPreferredIOBufferDuration"] as? Double ?? 0.005
  189. }else {
  190. self.iconName = args["iconName"] as? String ?? "CallKitLogo"
  191. self.handleType = args["handleType"] as? String ?? ""
  192. self.supportsVideo = args["supportsVideo"] as? Bool ?? true
  193. self.maximumCallGroups = args["maximumCallGroups"] as? Int ?? 2
  194. self.maximumCallsPerCallGroup = args["maximumCallsPerCallGroup"] as? Int ?? 1
  195. self.supportsDTMF = args["supportsDTMF"] as? Bool ?? true
  196. self.supportsHolding = args["supportsHolding"] as? Bool ?? true
  197. self.supportsGrouping = args["supportsGrouping"] as? Bool ?? true
  198. self.supportsUngrouping = args["supportsUngrouping"] as? Bool ?? true
  199. self.includesCallsInRecents = args["includesCallsInRecents"] as? Bool ?? true
  200. self.ringtonePath = args["ringtonePath"] as? String ?? ""
  201. self.configureAudioSession = args["configureAudioSession"] as? Bool ?? true
  202. self.audioSessionMode = args["audioSessionMode"] as? String ?? ""
  203. self.audioSessionActive = args["audioSessionActive"] as? Bool ?? true
  204. self.audioSessionPreferredSampleRate = args["audioSessionPreferredSampleRate"] as? Double ?? 44100.0
  205. self.audioSessionPreferredIOBufferDuration = args["audioSessionPreferredIOBufferDuration"] as? Double ?? 0.005
  206. }
  207. }
  208. open func toJSON() -> [String: Any] {
  209. let ios: [String : Any] = [
  210. "iconName": iconName,
  211. "handleType": handleType,
  212. "supportsVideo": supportsVideo,
  213. "maximumCallGroups": maximumCallGroups,
  214. "maximumCallsPerCallGroup": maximumCallsPerCallGroup,
  215. "supportsDTMF": supportsDTMF,
  216. "supportsHolding": supportsHolding,
  217. "supportsGrouping": supportsGrouping,
  218. "supportsUngrouping": supportsUngrouping,
  219. "includesCallsInRecents": includesCallsInRecents,
  220. "ringtonePath": ringtonePath,
  221. "configureAudioSession": configureAudioSession,
  222. "audioSessionMode": audioSessionMode,
  223. "audioSessionActive": audioSessionActive,
  224. "audioSessionPreferredSampleRate": audioSessionPreferredSampleRate,
  225. "audioSessionPreferredIOBufferDuration": audioSessionPreferredIOBufferDuration
  226. ]
  227. let map: [String : Any] = [
  228. "uuid": uuid,
  229. "id": uuid,
  230. "nameCaller": nameCaller,
  231. "appName": appName,
  232. "handle": handle,
  233. "avatar": avatar,
  234. "type": type,
  235. "normalHandle": normalHandle,
  236. "duration": duration,
  237. "extra": extra,
  238. "ios": ios
  239. ]
  240. return map
  241. }
  242. func getEncryptHandle() -> String {
  243. if (normalHandle > 0) {
  244. return handle
  245. }
  246. do {
  247. var map: [String: Any] = [:]
  248. map["nameCaller"] = nameCaller
  249. map["handle"] = handle
  250. var mapExtras = extra as? [String: Any]
  251. if (mapExtras == nil) {
  252. print("error casting dictionary to [String: Any]")
  253. return String(format: "{\"nameCaller\":\"%@\", \"handle\":\"%@\"}", nameCaller, handle).encryptHandle()
  254. }
  255. for (key, value) in mapExtras! {
  256. map[key] = value
  257. }
  258. let mapData = try JSONSerialization.data(withJSONObject: map, options: .prettyPrinted)
  259. let mapString: String = String(data: mapData, encoding: .utf8) ?? ""
  260. return mapString.encryptHandle()
  261. } catch {
  262. print("error encrypting call data")
  263. return String(format: "{\"nameCaller\":\"%@\", \"handle\":\"%@\"}", nameCaller, handle).encryptHandle()
  264. }
  265. }
  266. }