Skip to content

Commit 4e62f10

Browse files
Merge pull request #103 from ConnectyCube/development
release 2.3.0
2 parents 4f3273c + 251970f commit 4e62f10

File tree

11 files changed

+143
-44
lines changed

11 files changed

+143
-44
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 2.3.0
2+
- (iOS) Add a method for notifying the CallKit about muting/unmuting the call;
3+
- (iOS) Improvements for audio after accepting the call from the background or killed state;
4+
- (Dart) Add ignoring of not supported platforms;
5+
16
## 2.2.4
27
- (iOS) Improve the audio after accepting from the background or killed state;
38

README.md

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,21 @@ ConnectycubeFlutterCallKit.onCallAcceptedWhenTerminated = onCallAcceptedWhenTerm
131131
```
132132

133133
!> Attention: the functions `onCallRejectedWhenTerminated` and `onCallAcceptedWhenTerminated` must
134-
be a top-level function and cannot be anonymous
134+
be a top-level functions and cannot be anonymous. Mark these callbacks with the `@pragma('vm:entry-point')`
135+
annotation to allow using them from the native code.
136+
137+
#### Listen for the actions performed on the CallKit screen (iOS only):
138+
139+
##### Listening for the muting/unmuting the call
140+
141+
```dart
142+
ConnectycubeFlutterCallKit.onCallMuted = onCallMuted;
143+
144+
Future<void> onCallMuted(bool mute, String uuid) async {
145+
// [mute] - `true` - the call was muted on the CallKit screen, `false` - the call was unmuted
146+
// [uuid] - the id of the muted/unmuted call
147+
}
148+
```
135149

136150
### Get the call state
137151

@@ -155,7 +169,7 @@ var sessionId = await ConnectycubeFlutterCallKit.getLastCallId();
155169
```
156170
Then you can get the state of this call using `getCallState`.
157171

158-
### Notify the plugin about processing the call on the Flutter app side
172+
### Notify the plugin about user actions concerning the call on the Flutter app side
159173

160174
For dismissing the Incoming call screen (or the Call Kit for iOS) you should notify the plugin about
161175
these events.
@@ -166,6 +180,13 @@ ConnectycubeFlutterCallKit.reportCallAccepted(sessionId: uuid);
166180
ConnectycubeFlutterCallKit.reportCallEnded(sessionId: uuid);
167181
```
168182

183+
Notifying the plugin about muting/unmuting the call (iOS only):
184+
```dart
185+
var muted = true; // set `true` if the call was muted or `false` if the call was unmuted
186+
187+
ConnectycubeFlutterCallKit.reportCallMuted(sessionId: uuid, muted: muted);
188+
```
189+
169190
### Clear call data
170191
After finishing the call you can clear all data on the plugin side related to this call, call the
171192
next code for it

android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
group 'com.connectycube.flutter.connectycube_flutter_call_kit'
2-
version '2.2.4'
2+
version '2.3.0'
33

44
buildscript {
55
ext.kotlin_version = '1.6.21'

android/src/main/kotlin/com/connectycube/flutter/connectycube_flutter_call_kit/ConnectycubeFlutterCallKitPlugin.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,10 @@ class ConnectycubeFlutterCallKitPlugin : FlutterPlugin, MethodCallHandler,
292292
}
293293
}
294294

295+
"muteCall" -> {
296+
result.success(null)
297+
}
298+
295299
else ->
296300
result.notImplemented()
297301

example/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ description: Demonstrates how to use the connectycube_flutter_call_kit plugin.
66
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
77

88
environment:
9-
sdk: ">=2.7.0 <3.0.0"
9+
sdk: ">=2.12.0 <3.0.0"
1010

1111
dependencies:
1212
flutter:

ios/Classes/CallKitController.swift

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,12 @@ class CallKitController : NSObject {
8282
if(icon != nil){
8383
let iconImage = UIImage(named: icon!)
8484
let iconData = iconImage?.pngData()
85+
8586
providerConfiguration.iconTemplateImageData = iconData
8687
}
8788
}
8889

89-
func reportIncomingCall(
90+
@objc func reportIncomingCall(
9091
uuid: String,
9192
callType: Int,
9293
callInitiatorId: Int,
@@ -95,7 +96,8 @@ class CallKitController : NSObject {
9596
userInfo: String?,
9697
completion: ((Error?) -> Void)?
9798
) {
98-
print("[CallKitController][reportIncomingCall] call data: \(uuid), \(callType), \(callInitiatorId), \(callInitiatorName), \(opponents), \(userInfo ?? ""), ")
99+
print("[CallKitController][reportIncomingCall] call data: \(uuid), \(callType), \(callInitiatorId), \(callInitiatorName), \(opponents), \(userInfo ?? "nil")")
100+
99101
let update = CXCallUpdate()
100102
update.localizedCallerName = callInitiatorName
101103
update.remoteHandle = CXHandle(type: .generic, value: uuid)
@@ -105,11 +107,12 @@ class CallKitController : NSObject {
105107
update.supportsHolding = false
106108
update.supportsDTMF = false
107109

108-
configureAudioSession(active: true)
109110
if (self.currentCallData["session_id"] == nil || self.currentCallData["session_id"] as! String != uuid) {
110111
print("[CallKitController][reportIncomingCall] report new call: \(uuid)")
112+
111113
provider.reportNewIncomingCall(with: UUID(uuidString: uuid)!, update: update) { error in
112114
completion?(error)
115+
113116
if(error == nil){
114117
self.configureAudioSession(active: true)
115118

@@ -126,12 +129,16 @@ class CallKitController : NSObject {
126129
}
127130
} else if (self.currentCallData["session_id"] as! String == uuid) {
128131
print("[CallKitController][reportIncomingCall] update existing call: \(uuid)")
132+
129133
provider.reportCall(with: UUID(uuidString: uuid)!, updated: update)
134+
135+
completion?(nil)
130136
}
131137
}
132138

133139
func reportOutgoingCall(uuid : UUID, finishedConnecting: Bool){
134-
print("CallKitController: report outgoing call: \(uuid) connected:\(finishedConnecting)")
140+
print("[CallKitController][reportOutgoingCall] uuid: \(uuid.uuidString.lowercased()) connected: \(finishedConnecting)")
141+
135142
if !finishedConnecting {
136143
self.provider.reportOutgoingCall(with: uuid, startedConnectingAt: nil)
137144
} else {
@@ -140,7 +147,8 @@ class CallKitController : NSObject {
140147
}
141148

142149
func reportCallEnded(uuid : UUID, reason: CallEndedReason){
143-
print("CallKitController: report call ended: \(uuid)")
150+
print("[CallKitController][reportCallEnded] uuid: \(uuid.uuidString.lowercased())")
151+
144152
var cxReason : CXCallEndedReason
145153
switch reason {
146154
case .unanswered:
@@ -150,12 +158,14 @@ class CallKitController : NSObject {
150158
default:
151159
cxReason = CXCallEndedReason.failed
152160
}
161+
153162
self.callStates[uuid.uuidString.lowercased()] = .rejected
154163
self.provider.reportCall(with: uuid, endedAt: Date.init(), reason: cxReason)
155164
}
156165

157166
func getCallState(uuid: String) -> CallState {
158-
print("CallKitController: getCallState: \(self.callStates[uuid.lowercased()] ?? .unknown)")
167+
print("[CallKitController][getCallState] uuid: \(uuid), state: \(self.callStates[uuid.lowercased()] ?? .unknown)")
168+
159169
return self.callStates[uuid.lowercased()] ?? .unknown
160170
}
161171

@@ -173,15 +183,18 @@ class CallKitController : NSObject {
173183
}
174184

175185
func sendAudioInterruptionNotification(){
186+
print("[CallKitController][sendAudioInterruptionNotification]")
176187
var userInfo : [AnyHashable : Any] = [:]
177188
let intrepEndeRaw = AVAudioSession.InterruptionType.ended.rawValue
178189
userInfo[AVAudioSessionInterruptionTypeKey] = intrepEndeRaw
179190
userInfo[AVAudioSessionInterruptionOptionKey] = AVAudioSession.InterruptionOptions.shouldResume.rawValue
191+
180192
NotificationCenter.default.post(name: AVAudioSession.interruptionNotification, object: self, userInfo: userInfo)
181193
}
182194

183195
func configureAudioSession(active: Bool){
184-
print("CallKitController: [configureAudioSession]")
196+
print("[CallKitController][configureAudioSession] active: \(active)")
197+
185198
let audioSession = AVAudioSession.sharedInstance()
186199

187200
do {
@@ -190,7 +203,6 @@ class CallKitController : NSObject {
190203
options: [
191204
.allowBluetooth,
192205
.allowBluetoothA2DP,
193-
.duckOthers,
194206
])
195207
try audioSession.setMode(AVAudioSession.Mode.videoChat)
196208
try audioSession.setPreferredSampleRate(44100.0)
@@ -206,26 +218,29 @@ class CallKitController : NSObject {
206218
extension CallKitController {
207219

208220
func end(uuid: UUID) {
209-
print("CallKitController: user requested end call")
221+
print("[CallKitController][end] uuid: \(uuid.uuidString.lowercased())")
222+
210223
let endCallAction = CXEndCallAction(call: uuid)
211224
let transaction = CXTransaction(action: endCallAction)
212225

213226
self.callStates[uuid.uuidString.lowercased()] = .rejected
227+
214228
requestTransaction(transaction)
215229
}
216230

217231
private func requestTransaction(_ transaction: CXTransaction) {
218232
callController.request(transaction) { error in
219233
if let error = error {
220-
print("CallKitController: Error requesting transaction: \(error.localizedDescription)")
234+
print("[CallKitController][requestTransaction] Error: \(error.localizedDescription)")
221235
} else {
222-
print("CallKitController: Requested transaction successfully")
236+
print("[CallKitController][requestTransaction] successfully")
223237
}
224238
}
225239
}
226240

227241
func setHeld(uuid: UUID, onHold: Bool) {
228-
print("CallKitController: user requested hold call")
242+
print("[CallKitController][setHeld] uuid: \(uuid.uuidString.lowercased()), onHold: \(onHold)")
243+
229244
let setHeldCallAction = CXSetHeldCallAction(call: uuid, onHold: onHold)
230245

231246
let transaction = CXTransaction()
@@ -235,15 +250,18 @@ extension CallKitController {
235250
}
236251

237252
func setMute(uuid: UUID, muted: Bool){
238-
print("CallKitController: user requested mute call: muted - \(muted)")
253+
print("[CallKitController][setMute] uuid: \(uuid.uuidString.lowercased()), muted: \(muted)")
254+
239255
let muteCallAction = CXSetMutedCallAction(call: uuid, muted: muted);
240256
let transaction = CXTransaction()
241257
transaction.addAction(muteCallAction)
258+
242259
requestTransaction(transaction)
243260
}
244261

245262
func startCall(handle: String, videoEnabled: Bool, uuid: String? = nil) {
246-
print("CallKitController: user requested start call handle:\(handle), videoEnabled: \(videoEnabled) uuid: \(uuid ?? "")")
263+
print("[CallKitController][startCall] handle:\(handle), videoEnabled: \(videoEnabled) uuid: \(uuid ?? "nil")")
264+
247265
let handle = CXHandle(type: .generic, value: handle)
248266
let callUUID = uuid == nil ? UUID() : UUID(uuidString: uuid!)
249267
let startCallAction = CXStartCallAction(call: callUUID!, handle: handle)
@@ -257,7 +275,8 @@ extension CallKitController {
257275
}
258276

259277
func answerCall(uuid: String) {
260-
print("CallKitController: user requested answer call, uuid: \(uuid)")
278+
print("[CallKitController][answerCall] uuid: \(uuid)")
279+
261280
let callUUID = UUID(uuidString: uuid)
262281
let answerCallAction = CXAnswerCallAction(call: callUUID!)
263282
let transaction = CXTransaction(action: answerCallAction)
@@ -275,50 +294,46 @@ extension CallKitController: CXProviderDelegate {
275294
}
276295

277296
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
278-
print("CallKitController: Answer Call \(action.callUUID.uuidString)")
279-
280-
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1200)) {
281-
self.configureAudioSession(active: true)
282-
}
297+
print("[CallKitController][CXAnswerCallAction] callUUID: \(action.callUUID.uuidString.lowercased())")
283298

299+
configureAudioSession(active: true)
284300
callStates[action.callUUID.uuidString.lowercased()] = .accepted
285301
actionListener?(.answerCall, action.callUUID, self.currentCallData)
286302

287303
action.fulfill()
288304
}
289305

290306
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
291-
print("CallKitController: Audio session activated")
292-
293-
if(currentCallData["session_id"] != nil
294-
&& callStates[currentCallData["session_id"] as! String] == .accepted){
295-
sendAudioInterruptionNotification()
296-
return
297-
}
307+
print("[CallKitController] Audio session activated")
298308

299309
sendAudioInterruptionNotification()
300310
configureAudioSession(active: true)
301311
}
302312

303313
func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
304-
print("CallKitController: Audio session deactivated")
314+
print("[CallKitController] Audio session deactivated")
305315
}
306316

307317
func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
308-
print("CallKitController: End Call")
318+
print("[CallKitController][CXEndCallAction]")
319+
309320
actionListener?(.endCall, action.callUUID, currentCallData)
310321
callStates[action.callUUID.uuidString.lowercased()] = .rejected
322+
311323
action.fulfill()
312324
}
313325

314326
func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) {
315-
print("CallKitController: Set Held")
327+
print("[CallKitController][CXSetHeldCallAction] callUUID: \(action.callUUID.uuidString.lowercased())")
328+
316329
actionListener?(.setHeld, action.callUUID, ["isOnHold": action.isOnHold])
330+
317331
action.fulfill()
318332
}
319333

320334
func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
321-
print("CallKitController: Mute call")
335+
print("[CallKitController][CXSetMutedCallAction] callUUID: \(action.callUUID.uuidString.lowercased())")
336+
322337
if (action.isMuted){
323338
actionListener?(.setMuted, action.callUUID, currentCallData)
324339
} else {
@@ -329,9 +344,12 @@ extension CallKitController: CXProviderDelegate {
329344
}
330345

331346
func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
332-
print("CallKitController: Start Call")
347+
print("[CallKitController][CXStartCallAction]: callUUID: \(action.callUUID.uuidString.lowercased())")
348+
333349
actionListener?(.startCall, action.callUUID, currentCallData)
334350
callStates[action.callUUID.uuidString.lowercased()] = .accepted
351+
configureAudioSession(active: true)
352+
335353
action.fulfill()
336354
}
337355
}

ios/Classes/SwiftConnectycubeFlutterCallKitPlugin.swift

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public class SwiftConnectycubeFlutterCallKitPlugin: NSObject, FlutterPlugin {
3838
static let callController = CallKitController()
3939
static let voipController = VoIPController(withCallKitController: callController)
4040

41-
public static func register(with registrar: FlutterPluginRegistrar) {
41+
@objc public static func register(with registrar: FlutterPluginRegistrar) {
4242
print("[SwiftConnectycubeFlutterCallKitPlugin][register]")
4343
//setup method channels
4444
let methodChannel = FlutterMethodChannel(name: _methodChannelName, binaryMessenger: registrar.messenger())
@@ -52,7 +52,7 @@ public class SwiftConnectycubeFlutterCallKitPlugin: NSObject, FlutterPlugin {
5252
}
5353

5454
///useful for integrating with VIOP notifications
55-
static public func reportIncomingCall(uuid: String,
55+
@objc static public func reportIncomingCall(uuid: String,
5656
callType: Int,
5757
callInitiatorId: Int,
5858
callInitiatorName: String,
@@ -182,6 +182,17 @@ public class SwiftConnectycubeFlutterCallKitPlugin: NSObject, FlutterPlugin {
182182
else if call.method == "getLastCallId" {
183183
result(SwiftConnectycubeFlutterCallKitPlugin.callController.currentCallData["session_id"])
184184
}
185+
else if call.method == "muteCall" {
186+
guard let arguments = arguments else {
187+
result(FlutterError(code: "invalid_argument", message: "No data was provided.", details: nil))
188+
return
189+
}
190+
let callId = arguments["session_id"] as! String
191+
let muted = arguments["muted"] as! Bool
192+
193+
SwiftConnectycubeFlutterCallKitPlugin.callController.setMute(uuid: UUID(uuidString: callId)!, muted: muted)
194+
result(true)
195+
}
185196
else {
186197
result(FlutterMethodNotImplemented)
187198
}

0 commit comments

Comments
 (0)