Table of Contents |
---|
Пример iOS приложения для приема входящих звонков с использованием Call Kit
Данный пример может использоваться как основа для написания собственного приложения, использующего Call Kit и пуш-уведомлений для соединения с сервером и приема входящего SIP звонка.
...
При входящем звонке приложение получает пуш-уведомление, даже если оно свернуто или закрыто. Если приложение закрыто, оно подключается к SIP-сессии на сервере с токеном, полученным в уведомлении, и принимает входящий звонок.
Настройки сервера
Для того, чтобы работали пуш-уведомления, на сервере необходимо указать следующие настройки
Параметр | Описание |
---|---|
notification_apns_key_path | Расположение файла ключа Apple Push Notification service |
notification_apns_key_id | Идентификатор ключа APNs |
notification_apns_team_id | Идентификатор команды разработки |
Например
Code Block | ||
---|---|---|
| ||
notification_apns_key_path=/opt/apns_auth_key.p8
notification_apns_team_id=SXZF5547NK
notification_apns_key_id=7NQA96WTFZ |
В соответствии с этими настройками, сервер отправляет уведомления в APNs при поступлении входящего звонка
Работа с кодом примера
Для разбора кода возьмем версию примера CallKitDemo Swift, которая доступна для скачивания на GitHub
Классы приложения:
- класс основного вида приложения CallKitDemoViewController (файл CallKitDemoViewController.swift)
- класс реализации протокола CXProviderDelegate (файл ProviderDelegate.swift)
- класс для работы с интерфейсом пользователя и реестром пуш-уведомлений AppDelegate (файл AppDelegate.swift)
- расширение для создания объекта CXAnswerCallAction по действию пользователя, для ответа на звонок NSUserActivity: StartCallConvertible (файл NSUserActivity+StartCallConvertible.swift)
- расширение для создания объекта CXAnswerCallAction из URL, для ответа на звонок URL: StartCallConvertible (файл URL+StartCallConvertible.swift)
- расширение для создания звонка, реализующее протокол INStartCallIntentHandling (файл CallKitIntentExtension/IntentHandler.swift)
1. Импорт API
Code Block | ||||
---|---|---|---|---|
| ||||
import FPWCSApi2Swift |
2. Подключение к серверу и создание SIP-сессии
FPWCSApi2.createSession code
При создании сессии передаются следующие параметры:
- urlServer - URL WCS сервера
- keepAlive - сохранять сессию при отключении клиента
- sipRegisterRequired - регистрировать сессию на SIP сервере
- sipLogin - имя пользователя на SIP сервере
- sipAuthenticationName - имя пользователя для аутентификации на SIP сервере
- sipPassword - пароль на SIP сервере
- sipDomain - адрес SIP сервера
- sipOutboundProxy - адрес SIP сервера
- sipPort - порт на SIP сервере
- noticationToken - токен для получения уведомлений о входящих звонках
- appId - идентификатор приложения
- appKey - REST hook приложение на WCS сервере
Code Block | ||||
---|---|---|---|---|
| ||||
let options = FPWCSApi2SessionOptions() options.urlServer = wcsUrl.text options.keepAlive = true options.sipRegisterRequired = true options.sipLogin = sipLogin.text options.sipAuthenticationName = sipAuthName.text options.sipPassword = sipPassword.text options.sipDomain = sipDomain.text options.sipOutboundProxy = sipOutboundProxy.text options.sipPort = Int(sipPort.text ?? "5060") as NSNumber? let userDefaults = UserDefaults.standard options.noticationToken = userDefaults.string(forKey: "voipToken") options.appId = "com.flashphoner.ios.CallKitDemoSwift" options.appKey = "defaultApp" do { let session = try FPWCSApi2.createSession(options) processSession(session) appDelegate.providerDelegate?.setSession(session) session.connect() } catch { print(error) } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
func setSession(_ session: FPWCSApi2Session) { self.session = session; session.onIncomingCallCallback({ rCall in guard let call = rCall else { return } call.on(kFPWCSCallStatus.fpwcsCallStatusFinish, callback: {rCall in self.viewController.toNoCallState() guard let uuid = rCall?.getUuid() else { return } self.provider.reportCall(with: uuid, endedAt: Date(), reason: .remoteEnded) }) let id = call.getId() NSLog("CKD - session.onIncomingCallCallback. wcsCallId: " + (id ?? "")) call.on(kFPWCSCallStatus.fpwcsCallStatusEstablished, callback: {rCall in self.viewController.toHangupState(call.getId()) }) self.viewController.toAnswerState(call.getId()) self.currentCall = call self.actionCall?.fulfill() }) } |
5. Запрос действия для ответа на звонок
Code Block | ||||
---|---|---|---|---|
| ||||
func answer(_ callId: String) { guard let call = self.session?.getCall(callId) else { return } let callController = CXCallController() let answerCallAction = CXAnswerCallAction(call: call.getUuid()) callController.request(CXTransaction(action: answerCallAction), completion: { error in if let error = error { print("Error: \(error)") } else { print("Success") } }) } |
...