flutter_pitel_voip

Integrate VoIP call to your project

N|Solid

flutter_pitel_voip is package support for voip call.

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
  • Or add pubspec.yaml:
flutter_pitel_voip: any
  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 12.0 in Podfile
platform :ios, '12.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

Prop Description Type Default
bundleId bundleId IOS, packageId android String Required
appMode debug mode or release mode String Required
sipInfoData SIP information data () {} Required
goBack goback navigation () {} Required
goToCall navigation, go to call screen () {} Required
onCallState set call status (callState) {} Required
onRegisterState get extension register status (String registerState) {} Required
child child widget Widget Required

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

Prop Description Type Default
goBack go back navigation () {} Required
bgColor background color Color Required
txtMute Text display of micro mute String Optional
txtUnMute Text display of micro unmute String Optional
txtSpeaker Text display speaker String Optional
txtOutgoing Text display direction outgoing call String Optional
txtIncoming Text display direction incoming call String Optional
textStyle Style for mic/speaker text TextStyle Optional
titleTextStyle Style for display phone number text TextStyle Optional
timerTextStyle Style for timer text TextStyle Optional
directionTextStyle Style for direction text TextStyle Optional
  • Outgoing call
pitelCall.outGoingCall(
  phoneNumber: "",
  handleRegisterCall: (){},
);

Properties

Prop Description Type Default
phoneNumber phone number for call out String Required
handleRegisterCall re-register when call out () {} Required
nameCaller set name caller String Optional

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

Libraries

sip/src/transactions/ack_client
component/button/action_button
voip_push/android_connection_service
web_service/api_web_service
component/app_life_cycle/app_life_cycle
model/http/base_header
sip/src/event_manager/call_events
screens/call_screen/call_page
screens/call_screen/call_screen
screens/call_screen/widgets/call_timer
sip/src/config
sip/src/constants
sip/src/data
voip_push/device_information
sip/src/dialog
sip/src/digest_authentication
sip/src/rtc_session/dtmf
sip/src/enum_helper
sip/src/event_manager/event_manager
sip/src/event_manager/events
sip/src/exceptions
flutter_pitel_voip
model/http/get_extension_info
model/http/get_profile
model/http/get_sip_info
sip/src/grammar
sip/src/grammar_parser
web_service/http_service
component/button/icon_text_button
sip/src/rtc_session/info
sip/src/event_manager/internal_events
sip/src/transactions/invite_client
sip/src/transactions/invite_server
sip/src/logger
model/http/login
sip/src/message
sip/src/event_manager/message_events
sip/src/name_addr_header
sip/src/transactions/non_invite_client
sip/src/transactions/non_invite_server
sip/src/parser
pitel_sdk/pitel_api
pitel_sdk/pitel_call
component/pitel_call_state
pitel_sdk/pitel_client
config/pitel_config
model/pitel_error
pitel_sdk/pitel_log
pitel_plugin/pitel_plugin
pitel_sdk/pitel_profile
component/pitel_rtc_video_renderer
component/pitel_rtc_video_view
services/pitel_service
services/pitel_service_interface
component/pitel_ua_helper
screens/pitel_voip/pitel_voip
screens/pitel_voip_call/pitel_voip_call
services/models/pn_push_params
web_service/portal_service
voip_push/push_notif
model/http/push_notif_model
services/models/push_notif_params
web_service/push_notif_service
sip/src/event_manager/refer_events
sip/src/rtc_session/refer_notifier
sip/src/rtc_session/refer_subscriber
sip/src/event_manager/register_events
sip/src/registrator
sip/src/request_sender
sip/src/dialog/request_sender
sip/src/rtc_session
sip/src/sanity_check
web_service/sdk_service
model/sip_account
services/sip_info_data
sip/src/sip_message
component/sip_pitel_helper_listener
model/sip_server
sip/sip_ua
only expose the bare minimum of internals required
sip/src/sip_ua_helper
sip/src/socket
sip/src/stack_trace_nj
sip/src/timers
sip/src/transactions/transaction_base
sip/src/transactions/transactions
sip/src/transport
sip/src/event_manager/transport_events
sip/src/ua
sip/src/uri
sip/src/utils
screens/call_screen/widgets/voice_header
voip_push/voip_notif
sip/src/transports/websocket_dart_impl
sip/src/transports/websocket_interface
sip/src/transports/websocket_web_impl