Twilio Programmable Voice SDKs allow you to add voice-over-IP (VoIP) calling directly into your web and native mobile applications. This page provides some known best practices to make implementation easier and reliable.
You connect to Twilio from your mobile app with the Voice Mobile SDKs (Android or iOS). To learn more about how Twilio communicates with your mobile app, read over the Voice SDK Overview page.
Click on a link below to jump to a specific section.
To get the most out of this guide, use it in conjunction with the Voice iOS or Android SDK Quickstarts and documentation.
SDK logs will help your team or Twilio Support to identify issues. Be sure to set the log level to debug or verbose (see examples below) as a first step.
These detailed logs can be shared when you open a GitHub issue or Twilio Support ticket (just remember to redact any sensitive information first).
Android: Set the log level to DEBUG
.
Voice.setLogLevel(LogLevel.DEBUG)
iOS: Set the log level to TVOLogLevelVerbose or .verbose
1/* Obj-C */2[VoiceClient setLogLevel:TVOLogLevelVerbose];3
1/* Swift */2VoiceClient.logLevel = .verbose
iOS: To ensure Apple VoIP push notification delivery, initialize the PushKit PKPushRegistry
instance at app launch (e.g. in AppDelegate
). This allows your app to receive notification in different states, especially when the app is relaunched from the terminated state. This also eliminates the need to check if registration exists or not.
Note: This functionality is already included in the Voice iOS SDK Quickstart.
It's important to unregister from push notifications using the SDK's unregister
methods (iOS SDK method, Android SDK method when re-launching applications with different Voice SDK identity. Otherwise your app might receive pushes for the previously logged in user.
Note: This functionality is NOT included in the Android or iOS Quickstarts.
We rely on the operating system (OS) to stop providing push notifications for apps that are no longer installed. Therefore, if the app is uninstalled before deregistration, bindings can become stale and cause issues. If the app is reinstalled and identity reregistered, things will start to work again.
iOS: APNS & iOS do not detect if the app has been uninstalled and will still try to deliver push notifications to the binding upon being requested by Twilio Notify, i.e. Notify has no way of knowing the app is uninstalled since there is no error.
Since the PushKit device token will be the same on the same device and the same app (unless iOS is reinstalled or reset/restored), registering with a new identity when reinstalling the app will deactivate the old binding and activate the binding for the new identity.
To avoid excessive registrations, you should save the device provided by the OS in the persistent memory. Compare the values on startup and re-register only if the tokens differ.
React to the new device token (See See Android SDK Quickstart example)
1public void onNewToken(String token) {2super.onNewToken(token);3Intent intent = new Intent(Constants.ACTION_FCM_TOKEN);4LocalBroadcastManager.getInstance(this).sendBroadcast(intent);5}
Re-register for call invites with new token (See Android SDK Quickstart example)
1case Constants.ACTION_FCM_TOKEN:2registerForCallInvites();3break;
Developers often use the same device while testing the development and production versions of their apps. Errors can occur if the developer uses the same client identity for each of the versions of the app on the same device.
Assuming the developer configures the Push Credential sandbox option correctly and has registered the identity in both development and production apps, there will be two active bindings existing in the Twilio Notify database. These two bindings each have an associated device token, which is development- or production-specific. Over time, the certificate and Push Credential associated with each binding may expire or become invalid and will result in errors when calling the client.
You should use a Twilio subaccount for creating AccessTokens for development and a different Twilio subaccount (or the primary Twilio account) for creating AccessTokens for the app version you will submit to the App Store.
When you run a different environment (development then production, or vice versa) for the first time, PushKit will return the device token from the previous environment, which may not match the sandbox configuration of the Push Credential in the AccessToken. This won't result in a registration failure, but "Invalid device token" errors will occur when Twilio sends the Push Notification delivery request to APNS.
Restrictive networks may fail unless ICE servers are provided via Connect Options or Accept Options. ICE servers can be obtained fromTwilio Network Traversal Service.
By default, ICE gathering is done on all interfaces except some VPN type interfaces. This makes it impossible to connect to Twilio in networks that require the use of VPN. The Boolean property to enable ICE gathering on any address ports in Connect Options should be enabled to allow the gathering of ICE candidates from all available interfaces.
1// Android2ConnectOptions.Builder builder = new3ConnectOptions.Builder(accessToken);45builder.enableIceGatheringOnAnyAddressPorts(true);
1// iOS2let connectOptions = ConnectOptions(accessToken: accessToken) { builder in3builder.params = [“foo”: “bar”]4builder.uuid = uuid5builder.enableIceGatheringOnAnyAddressPorts = true6}78let call = TwilioVoiceSDK.connect(options: connectOptions, delegate: self)
You may want to set your AccessTokens' time to live (TTL) to be several hours, with 24 hours as the maximum TTL.
AccessTokens are how Twilio tracks your Voice SDK usage (and how much your account should be billed). Keep AccessTokens secure.
Keep AccessTokens up to date. You should add logic to your application that automatically keeps AccessTokens up to date that follows the steps below:
register
method used at startup.On Android, all Twilio Voice API calls must originate from the same thread and that thread must contain a Looper. Many API calls invoke callbacks to notify the API user of state changes. In order for these messages to be invoked on the same thread as the thread that the API call originated from, a Looper is necessary. For an example of how to make all the API calls from the same thread, please look at the Android Voice Quickstart.
If you need to change or update your push credentials you can do so by selecting the Push Credential in the console and adding your new certificate
and private key
in the text box provided on the Push Credential page. If your APNS VoIP certificate is expiring soon or has expired you should not delete your Push Credential, instead you should update the Push Credential. More detail is in our IOS SDK quickstart on Github.