Skip to main content

Integrate Voip call to your project

N|Solid

flutter_pitel_voip is package support for voice-over-IP (VoIP) call. Support VoIP call between 2 extension or outgoing call mobile phone number.

Demo

Register extension call

Pitel Connect Flow

When user make call from Pitel Connect app, Pitel Server pushes a notification for all user login (who receives the call). When user "Accept" call, extension will re-register to receive call. Pitel Connect Flow

Features

  • Register Extension
  • Call
  • Hangup
  • Turn on/off micro
  • Turn on/of speaker

Installation

  1. Install Packages
  • Run this command:
flutter pub add flutter_pitel_voip
  • Add pubspec.yaml:
flutter_pitel_voip: ^<latest-version>
  1. Get package
flutter pub get
  1. Import
import "package:flutter_pitel_voip/flutter_pitel_voip.dart";
  1. Configure Project
  • In file app.dart config easyloading
import 'package:flutter_easyloading/flutter_easyloading.dart';
// ....
return MaterialApp.router(
// ...
builder: EasyLoading.init(),
)

Android:

  • In file android/app/src/main/AndroidManifest.xml
 <manifest...>
...
// Request permission
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
</manifest>

IOS

  • Request permission in file Info.plist
<key>NSMicrophoneUsageDescription</key>
<string>Use microphone</string>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>processing</string>
<string>remote-notification</string>
<string>voip</string>
</array>
  • Make sure platform ios 13.0 in Podfile
platform: ios, "13.0";
  1. Pushkit/ Push notification - Received VoIP and Wake app from Terminated State.

    Note Please check PUSH_NOTIF.md. setup Pushkit (for IOS), push notification (for Android).

Troubleshooting

[Android only]: If you give a error flutter_webrtc when run app in android. Please update code in file

$HOME/.pub-cache/hosted/pub.dartlang.org/flutter_webrtc-{version}/android/build.gradle
dependencies {
// Remove
// implementation 'com.github.webrtc-sdk:android:104.5112.03'

// Replace
implementation 'io.github.webrtc-sdk:android:104.5112.09'
}

Example

Please checkout repo github to get example

Usage

  • In file app.dart, Wrap MaterialApp with PitelVoip widget Please follow example

Note: handleRegisterCall, handleRegister, registerFunc in here

Widget build(BuildContext context) {
return PitelVoip( // Wrap with PitelVoip
handleRegister: handleRegister, // Handle register
handleRegisterCall: handleRegisterCall, // Handle register call
child: MaterialApp.router(
...
),
);
}
  • In file home_screen.dart. Please follow example. Add WidgetsBindingObserver to handle AppLifecycleState change
...
Widget build(BuildContext context) {
return PitelVoipCall( // Wrap with PitelVoipCall
bundleId: '${bundle_id}',
appMode: 'dev', // dev or production
sipInfoData: sipInfoData,
goBack: () {
// go back function
},
goToCall: () {
// go to call screen
},
onCallState: (callState) {
// IMPORTANT: Set callState to your global state management. Example: bloc, getX, riverpod,..
// Example riverpod
// ref.read(callStateController.notifier).state = callState;
},
onRegisterState: (String registerState) {
// get Register Status in here
},
child: ...,
);
}

Properties

PropDescriptionTypeDefault
bundleIdbundleId IOS, packageId androidStringRequired
appModedebug mode or release modeStringRequired
sipInfoDataSIP information data() Required
goBackgoback navigation() Required
goToCallnavigation, go to call screen() Required
onCallStateset call status(callState) Required
onRegisterStateget extension register status(String registerState) Required
childchild widgetWidgetRequired

Register extension from data of Tel4vn provide. Example: 101, 102,… Create 1 button to fill data to register extension.

ElevatedButton(
onPressed: () asyns {
final PushNotifParams pushNotifParams = PushNotifParams(
teamId: '${apple_team_id}',
bundleId: '${bundle_id}',
);
final sipInfoData = SipInfoData.fromJson({
"authPass": "${Password}",
"registerServer": "${Domain}",
"outboundServer": "${Outbound Proxy}",
"port": PORT,
"accountName": "${UUser}", // Example 101
"displayName": "${Display Name}",
"wssUrl": "${URL WSS}",
"apiDomain": "${URL API}"
});

final pitelClient = PitelServiceImpl();
final pitelSetting = await pitelClient.setExtensionInfo(sipInfoData, pushNotifParams);
// IMPORTANT: Set pitelSetting to your global state management. Example: bloc, getX, riverpod,..
// Example riverpod
// ref.read(pitelSettingProvider.notifier).state = pitelSettingRes;
},
child: const Text("Register"),),
  • Logout extension
pitelClient.logoutExtension(sipInfoData);
import 'package:flutter/material.dart';
import 'package:flutter_pitel_voip/flutter_pitel_voip.dart';
class CallPage extends StatelessWidget {
const CallPage({super.key});
@override
Widget build(BuildContext context) {
// IMPORTANT: Get callState from your global state management. Example: bloc, getX, riverpod,..
// Example riverpod
// final callState = ref.watch(callStateController);

return CallScreen(
callState: callState, // callState from state management you set before
goBack: () {
// Call your go back function in here
},
bgColor: Colors.cyan,
);
}
}

Properties

PropDescriptionTypeDefault
goBackgo back navigation() Required
bgColorbackground colorColorRequired
txtMuteText display of micro muteStringOptional
txtUnMuteText display of micro unmuteStringOptional
txtSpeakerText display speakerStringOptional
txtOutgoingText display direction outgoing callStringOptional
txtIncomingText display direction incoming callStringOptional
textStyleStyle for mic/speaker textTextStyleOptional
titleTextStyleStyle for display phone number textTextStyleOptional
timerTextStyleStyle for timer textTextStyleOptional
directionTextStyleStyle for direction textTextStyleOptional
  • Outgoing call
pitelCall.outGoingCall(
phoneNumber: "",
handleRegisterCall: (){},
);

Properties

PropDescriptionTypeDefault
phoneNumberphone number for call outStringRequired
handleRegisterCallre-register when call out() Required
nameCallerset name callerStringOptional

How to test

Using tryit to test voip call connection & conversation Link: https://tryit.jssip.net/ Setting:

  1. Access to link https://tryit.jssip.net/
  2. Enter extension: example 102
  3. Click Setting icon
  4. Enter information to input field tryit
  5. Save
  6. Click icon -> to connect