sautikit 0.1.0 copy "sautikit: ^0.1.0" to clipboard
sautikit: ^0.1.0 copied to clipboard

Place and receive real phone calls from a Flutter app over SautiKit's voice network. WebRTC audio on Android, iOS, web, macOS and Windows.

sautikit #

Real phone calls from a Flutter app, over SautiKit's voice network. One package for Android, iOS, web, macOS and Windows.

// `credentials` is called on every connect AND every reconnect. Point it at
// your server's token endpoint — do not close over a token you fetched once.
final phone = SautikitPhone(credentials: () async {
  final r = await http.post(Uri.parse('$myServer/voice-token'));
  return SautikitCredentials.fromMint(jsonDecode(r.body));
});

phone.events.listen((e) {
  switch (e) {
    case Registered():   setState(() => ready = true);
    case Ringing():      setState(() => status = 'Ringing…');
    case Answered():     setState(() => status = 'Connected');
    case Hangup(:final reason): setState(() => status = reason ?? 'Ended');
    case ErrorEvent(:final error): debugPrint('$error');
    default: break;
  }
});

await phone.connect();
await phone.call('+254700000001');

Getting a token #

Your server mints it and hands it to the app:

POST https://api.sautikit.com/v1/webrtc/token
Authorization: Bearer <your workspace API key>
{ "phone_number": "+254700000001" }

The response carries the token, the gateway endpoint and TURN servers. SautikitCredentials.fromMint reads that shape directly, so you can hand it the decoded JSON.

Fetch it again on every reconnect. Tokens expire, and a reconnect is exactly when the old one is most likely to have. That is why the SDK takes a function rather than a string: a phone holding one credential for the life of the app comes back from a dropped socket with a dead token and retries until its budget runs out, reporting a network fault for what is really an expiry.

For a spike, SautikitPhone.withToken(token: …) takes a fixed string. It stops working when that token expires, which is the honest trade and why it is not the main constructor.

The SDK cannot mint its own token, on purpose. Minting needs a workspace API key, and a key shipped inside an app is a key anybody can unzip out of it. The token is short-lived and scoped to one of your numbers, which is the caller ID the person you ring will see.

Permissions #

Androidandroid/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

iOSios/Runner/Info.plist:

<key>NSMicrophoneUsageDescription</key>
<string>Needed to place calls.</string>

Web — served over HTTPS (or localhost). Browsers refuse the microphone on plain HTTP.

What you get #

connect() open the socket and register
call(destination) ring a number in E.164
accept() / reject() answer or refuse an inbound call
hangup() end the call in progress
setMuted(bool) silence this end, keep the call
sendDigits('1') DTMF, for menus and PINs
events a Stream of everything above
dispose() hang up, close the socket, release the microphone

dispose() is not optional. A live peer connection holds the microphone, and on a phone that leaves a recording indicator showing long after the person thinks they have finished.

Two things worth knowing #

call() completes when the invitation is away, not when somebody answers. Wait for Ringing then Answered. A future that completed on answer would leave your caller watching a spinner through the whole ring.

Pass the TURN servers from the token mint. Without them a call works on the same network as the gateway and fails behind most mobile carriers — which is to say, it works in your office and not for your customers.

Licence #

MIT

0
likes
160
points
39
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

Place and receive real phone calls from a Flutter app over SautiKit's voice network. WebRTC audio on Android, iOS, web, macOS and Windows.

Homepage
Repository (GitHub)

Topics

#voip #webrtc #telephony #calling

License

MIT (license)

Dependencies

flutter, flutter_webrtc, web, web_socket_channel

More

Packages that depend on sautikit