twilio_voice

Provides an interface to Twilio's Programmable Voice SDK to allow voice-over-IP (VoIP) calling into your Flutter applications. This plugin was taken from the original flutter_twilio_voice, as it seems that plugin is no longer maitained, this one is.

Features

  • Receive and place calls from iOS devices, uses callkit to receive calls.
  • Receive and place calls from Android devices, uses custom UI to receive calls.

Android Limitations

As iOS has CallKit, an Apple provided UI for answering calls, there is no default UI for android to receive calls, for this reason a default UI was made. To increase customization, the UI will use a splash_icon.png registered on your res/drawable folder. I havent found a way to customize colors, if you find one, please submit a pull request.

Setup

Please follow Twilio's quickstart setup for each platform, you dont need to write the native code but it will help you undestand the basic functionality of setting up your server, registering your iOS app for VOIP, etc.

iOS Setup

To customize the icon displayed on a CallKit call, Open XCode and add a png icon named 'callkit_icon' to your assets.xassets folder

Android Setup:

register in your AndroidManifest.xml the service in charge of displaying incomming call notifications:

<Application>
  .....
  <service
      android:name="com.twilio.twilio_voice.fcm.VoiceFirebaseMessagingService"
      android:stopWithTask="false">
      <intent-filter>
          <action android:name="com.google.firebase.MESSAGING_EVENT" />
      </intent-filter>
  </service>

Usage

The plugin was separated into two classes, the TwilioVoice.instance and TwilioVoice.instance.call, the first one is in charge of general configuration and the second one is in charge of managing calls.

Register iOS capabilities

  • Add Audio and Voice over IP in background modes

TwilioVoice.instance

Setting the tokens

call TwilioVoice.instance.setTokens as soon as your app starts.

  • accessToken provided from your server, you can see an example cloud function here.
  • deviceToken is automatically handled on iOS, for android you need to pass a FCM token.

call TwilioVoice.instance.unregister to unregister from Twilio, if no access token is passed, it will use the token provided in setTokens at the same session.

Call Identifier

As incomming call UI is shown in background and the App can even be closed when receiving the calls, you can map call identifiers such as firebaseAuth userIds to real names, this operation must be done before actially receiving the call. So if you have a chat app, and know the members names, register them so when they call, the call UI can display their names and not their userIds.

Registering a client

TwilioVoice.instance.registerClient(String clientId, String clientName)

Unegistering a client

TwilioVoice.instance.unregisterClient(String clientId)

Default caller

You can also set a dafault caller, such as "unknown number" or "chat friend" in case a call comes in from an unregistered client.

TwilioVoice.instance.setDefaultCallerName(String callerName)

Call Events

use stream TwilioVoice.instance.callEventsListener to receive events from the TwilioSDK such as call events and logs, it is a broadcast so you can listen to it on different parts of your app. Some events might be missed when the app has not launched, please check out the example project to find the workarounds.

The events sent are the following

  • ringing
  • connected
  • callEnded
  • unhold
  • hold
  • unmute
  • mute
  • speakerOn
  • speakerOff
  • log
  • answer

showMissedCallNotifications

By default a local notification will be shown to the user after missing a call, clicking on the notification will call back the user. To remove this feature, set showMissedCallNotifications to false.

Calls

Make a Call

from your own identifier to the id you want to call use extraOptions to pass additional variables to your server callback function.

 await TwilioVoice.instance.call.place(from:myId, to: clientId, extraOptions)
                   ;

Mute a Call

 TwilioVoice.instance.call.toggleMute(isMuted: true);

Toggle Speaker

 TwilioVoice.instance.call.toggleSpeaker(speakerIsOn: true);

Hang Up

 TwilioVoice.instance.call.hangUp();

Send Digits

 TwilioVoice.instance.call.sendDigits(String digits);

Permissions

Microphone

To receive and place calls you need Microphone permisisons, register the micropohone permission in your info.plist for iOS.

You can use TwilioVoice.instance.hasMicAccess and TwilioVoice.instance.requestMicAccess to check and request the permission. Permissions is also automatically requested when receiving a call.

Background calls (Android only on some devices)

Xiami devices, and maybe others, need a spetial permission to receive background calls. use TwilioVoice.instance.requiresBackgroundPermissions to check if your device requires a special permission, if it does, show a rationale explaining the user why you need the permisison. Finally call TwilioVoice.instance.requestBackgroundPermissions which will take the user to the App Settings page to enable the permission.

Localization

Because some of the UI is in native code, you need to localize those strings natively in your project. You can find in the example project localization for spanish, PRs are welcome for other languages.

Libraries

twilio_voice