Интеграция Twilio SDK для звонков в мобильном приложении
Twilio Voice SDK берёт на себя медиатранспорт, кодирование аудио, TURN-инфраструктуру и глобальную маршрутизацию через собственные data centers. Разработчику остаётся: сигнализация через Twilio, управление аудиосессией на платформе и интеграция со системными звонковыми интерфейсами. Это быстрее, чем WebRTC с нуля, но менее гибко и дороже при масштабировании.
Серверная часть: Access Token
Twilio Voice SDK аутентифицируется через краткосрочные Access Token, которые генерирует ваш бэкенд с помощью Twilio Helper Library. Токен содержит VoiceGrant — разрешения на входящие и исходящие звонки.
from twilio.jwt.access_token import AccessToken
from twilio.jwt.access_token.grants import VoiceGrant
token = AccessToken(
account_sid=ACCOUNT_SID,
signing_key_sid=API_KEY_SID,
private_key=API_KEY_SECRET,
identity=user_id,
ttl=3600
)
token.add_grant(VoiceGrant(
outgoing_application_sid=TWIML_APP_SID,
incoming_allow=True
))
return token.to_jwt()
Мобильный клиент получает токен при запуске и обновляет его до истечения. Twilio SDK уведомляет через делегат accessTokenInvalidOrExpired — в этот момент нужно сделать запрос на новый токен и вызвать updateAccessToken.
Android SDK
Зависимость: com.twilio:voice-android:6.x.x. SDK работает поверх WebRTC, но предоставляет высокоуровневый API.
// Инициализация
Voice.initialize(context, LogLevel.DEBUG)
// Исходящий звонок
val connectOptions = ConnectOptions.Builder(accessToken)
.params(mapOf("To" to phoneNumber))
.build()
val call = Voice.connect(context, connectOptions, object : Call.Listener {
override fun onConnected(call: Call) { /* звонок установлен */ }
override fun onDisconnected(call: Call, error: CallException?) { /* завершён */ }
override fun onConnectFailure(call: Call, error: CallException) { /* ошибка */ }
})
Входящие звонки приходят через FCM. Twilio SDK обрабатывает FCM payload через Voice.handleMessage():
override fun onMessageReceived(message: RemoteMessage) {
if (Voice.handleMessage(context, message.data, object : MessageListener {
override fun onCallInvite(callInvite: CallInvite) {
// показываем уведомление о входящем звонке
showIncomingCallNotification(callInvite)
}
override fun onCancelledCallInvite(cancelledInvite: CancelledCallInvite, ...) {
// звонок отменён до ответа
}
})) { /* это Twilio push */ }
}
Принятие звонка: callInvite.accept(context, callListener).
iOS SDK
CocoaPods: pod 'TwilioVoice', '~> 6.x'. PushKit обязателен для входящих звонков — APNs VoIP channel.
// Регистрация PushKit токена в Twilio
func pushRegistry(_ registry: PKPushRegistry,
didUpdate credentials: PKPushCredentials,
for type: PKPushType) {
TwilioVoice.register(accessToken: token,
deviceToken: credentials.token) { error in }
}
// Входящий звонок через PushKit
func pushRegistry(_ registry: PKPushRegistry,
didReceiveIncomingPushWith payload: PKPushPayload,
for type: PKPushType,
completion: @escaping () -> Void) {
TwilioVoice.handleNotification(payload.dictionaryPayload,
delegate: self,
delegateQueue: nil)
// ОБЯЗАТЕЛЬНО вызвать CallKit reportNewIncomingCall до completion
}
Нарушение правила вызова CallKit до completion в PushKit delegate — принудительное завершение приложения iOS. Это не предупреждение, это crash.
Интеграция с CallKit через TVODefaultAudioDevice — Twilio предоставляет готовый AVAudioSession менеджер, который правильно взаимодействует с CallKit. Заменить на кастомный можно через TwilioVoice.audioDevice = customDevice.
TwiML и маршрутизация на сервере
Когда мобильный клиент звонит через Twilio, запрос идёт на ваш TwiML Application webhook. Бэкенд отвечает TwiML — XML-инструкциями для Twilio:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial callerId="+1234567890">
<Client>recipient_user_id</Client>
</Dial>
</Response>
Для звонков на обычные телефонные номера — <Number> вместо <Client>. Twilio выступает посредником, ваш сервер управляет логикой маршрутизации.
Запись звонков и аналитика
Запись через TwiML <Record> или программно через REST API — доступна без изменений в SDK. Twilio хранит записи на своих серверах, предоставляя URL для скачивания. Аналитика звонков (длительность, качество, статусы) — через Twilio Console или REST API.
Ограничения и когда смотреть в сторону WebRTC
Twilio Voice добавляет latency через relay — все медиапотоки идут через дата-центры Twilio, не P2P. Для большинства задач это незаметно (< 50 мс дополнительной задержки при ближайшем PoP), но в регионах без близкого дата-центра Twilio (Центральная Азия, часть Африки) задержка может быть заметной.
Стоимость: Twilio Voice billing — за минуту соединения. При больших объёмах (10 000+ минут/день) собственный WebRTC + TURN дешевле, но дороже в разработке и поддержке.
Что входит в работу
Настраиваем Twilio аккаунт (TwiML App, API Keys, Push Credentials), реализуем бэкенд для генерации Access Token и webhook, интегрируем Twilio Voice SDK на Android и/или iOS с CallKit/ConnectionService, тестируем входящие/исходящие звонки на реальных устройствах.
Срок: 1–3 недели в зависимости от сложности маршрутизации и требований к UI звонка.







