[iOS][Swift]CallKit
Bài đăng này đã không được cập nhật trong 7 năm
*** Bài dịch từ https://www.raywenderlich.com/150015/callkit-tutorial-ios ***
Mở đầu
Nếu bạn đã từng làm 1 ứng dụng support việc gọi điện thoại (qua VoIP chẳng hạn) thì bạn sẽ thấy việc thông báo cuộc gọi cho các ứng dụng không chính chủ (của Apple) ở iOS nghèo nàn đến mức nào. Nó chỉ đơn giản là 1 cái notification nhỏ bé và người dùng luôn bỏ qua nó. Tuy đã thấu hiểu nhu cầu đó từ rất lâu nhưng mãi đến tận iOS10, Apple mới chính thức hỗ trợ cho nhu cầu vô cùng chính đáng đó, với việc ra mắt CallKit
CallKit bắt đầu được giới thiệu từ iOS 10.0 trở đi, vậy nên để sử dụng CallKit, bạn cần phải chuẩn bị cho mình 1 device iOS 10.0 trở lên, và phải là thiết bị thật, vì trên Simulator không hỗ trợ việc test CallKit cho bạn
CallKit
CallKit
bao gồm 2 thành phần chính mà bạn phải làm việc cùng là CXProvider
và CXCallController
CXProvider
Ứng dụng của bạn sẽ sử dụng XCProvider
để report những out-of-band notification (ví dụ như incoming call) tới hệ thống. Khi các sự kiện này xảy ra, CXProvider
sẽ tạo call update để notify tới hệ thống.
Ứng dụng communicate với CXProvider
thông qua CXProviderDelegate
CXCallController
Nếu CXProvider
được dùng để report tới hệ thống thì CXCallController
được sử dụng để báo cho hệ thống về những request do chính người dùng khởi tạo ra, ví dụ như khi start action Call
. CXCallController
sử dụng các CXTransaction
(mỗi CXTransaction
chứa 1 hoặc nhiều CXAction
) để tạo các request gửi tới hệ thống. Và việc của hệ thống là reponse lại cho CXProvider
Nhận cuộc gọi
Khi bạn nhận được 1 cuộc gọi (trong app của bạn) và bạn muốn hiển thị nó lên màn hình Call mặc định của Apple, CXProvider
sẽ giúp bạn việc đó. Đơn giản bạn chỉ cần làm
fileprivate let provider: CXProvider
func reportIncommingCall(uuid: UUID, handle: String, hasVideo: Bool = false, completion: ((NSError?) -> Void)?) {
let update = CXCallUpdate()
update.remoteHandle = CXHandle(type: .phoneNumber, value: handle)
update.hasVideo = hasVideo
self.provider.reportNewIncomingCall(with: uuid, update: update) { (error) in
if error == nil {
let call = Call(uuid: uuid, handle: handle)
self.callManager.add(call: call)
}
completion?(error as NSError?)
}
}
trong đó UUID sẽ là UUID của máy, bạn có thể lấy nó qua function UUID()
, handle
chính là cái mà bạn muốn nó hiển thị ở phần tên người gọi
Nếu bạn chọn handle type = .phoneNumber
, và handle
của bạn là số điện thoại thì iOS sẽ tự động map số điện thoại đó với danh bạ của bạn và hiển thị tên người gọi
Để thực hiện việc nhận cuộc gọi khi lock screen, đừng quên enable tính năng Background Modes
cho Voice over IP
Tuy vậy, mọi việc vẫn chỉ dừng lại ở việc hiển thị, mọi tác động tới màn hình Call đó đều không có giá trị gì cả.
Để giải quyết vấn đề này, những việc bạn cần làm đơn giản chỉ là gọi delegate của CXProvider
self.provider.setDelegate(self, queue: nil)
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
guard let call = callManager.callWithUUID(uuid: action.callUUID) else {
action.fail()
return
}
configureAudioSession()
call.answer()
action.fulfill()
}
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
startAudio()
}
End Call
Khi ở màn hình khóa, chúng ta dễ dàng EndCall, nhưng khi đã vào ứng dụng chính, việc đó không còn đơn giản như thế nữa, và việc chúng ta cần làm là thêm 1 vài dòng code vào project của mình. Và để gọi action Call ấy, chúng ta sẽ sử dụng tới CXCallController
private let callController = CXCallController()
func end(call: Call) {
let endCallAction = CXEndCallAction(call: call.uuid)
let transaction = CXTransaction(action: endCallAction)
callController.request(transaction) { error in
if let error = error {
print("Error = \(error.localizedDescription)")
} else {
print("Success")
}
}
}
func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
guard let call = callManager.callWithUUID(uuid: action.callUUID) else {
action.fail()
return
}
stopAudio()
call.end()
action.fulfill()
callManager.remove(call: call)
}
Kết
Rõ ràng, việc ra mắt CallKit đã giúp cho Dev nâng tầm UX ứng dụng của mình lên 1 tầng cao mới, nếu 1 lần có cơ hội được trải nghiệm trong 1 dự án có sử dụng VoIP, đừng quên suggest khách hàng về CallKit
nhé
All rights reserved