flutter_pitel_voip

Integrate VoIP call to your project

N|Solid

flutter_pitel_voip is package support for voip call. Please contact pitel to use the service.

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

Summary

Installation

  1. Install Packages
  • Run this command:
flutter pub add flutter_pitel_voip
  • Or add pubspec.yaml:
flutter_pitel_voip: ^latest
  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 pitel loading
import 'package:flutter_pitel_voip/services/pitel_navigation_service.dart';
  // ....
  return MaterialApp(
    navigatorKey: NavigationService.navigatorKey,
  )

  // or use with go_router
  final router = GoRouter(
    navigatorKey: NavigationService.navigatorKey, 
    routes: [ ... ],
  );

  return MaterialApp.router(
    routerConfig: router,
  )

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.SYSTEM_ALERT_WINDOW" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
 </manifest>
  • Request full screen intent permission (Android 14+)

For Android 14 (API level 34) and above, you need to request the full screen intent permission to show incoming call notifications when the app is locked or in the background:

import 'package:flutter_callkit_incoming_timer/flutter_callkit_incoming.dart';
// Request permission in your app initialization or before making/receiving calls
await FlutterCallkitIncoming.requestFullIntentPermission();

This permission allows the app to launch a full-screen intent for incoming calls, ensuring users can see and answer calls even when the device is locked.

  • In file android/app/proguard-rules.pro. Proguard Rules: The following rule needs to be added in the proguard-rules.pro to avoid obfuscated keys:
# KEEP plugin Android classes 
-keep class com.hiennv.flutter_callkit_incoming.** { *; }

# Keep Gson classes & TypeToken if plugin uses Gson
-keep class com.google.gson.** { *; }
-keepclassmembers class com.google.gson.reflect.TypeToken { *; }

# Fix Conscrypt missing classes for OkHttp
-dontwarn org.conscrypt.**

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).

Example

Please checkout repo github to get example

Usage

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

Note:

  • handleRegister, registerFunc in here
  • Wrap the PitelVoip and PitelVoipCall widgets around your application's root widget (e.g., MaterialApp or CupertinoApp).
Widget build(BuildContext context) {
    return PitelVoip(                           // Wrap with PitelVoip
      handleRegister: handleRegister,           // Handle register
      child: MaterialApp.router(
        ...
      ),
    );
  }
  • In file home_screen.dart. Please follow example. Add WidgetsBindingObserver to handle AppLifecycleState change
...
Widget build(BuildContext context) {
    // Wrap with PitelVoipCall
    return PitelVoipCall(
        goBack: () {
            // go back function
        },
        goToCall: () {
            // go to call screen
        },
        onCallState: (callState) {},
        onRegisterState: (String registerState) {
            // get Register Status in here
        },
      child: ...,
    );
  }

Properties

Prop Description Type Default
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 {
          PitelClient pitelClient = PitelClient.getInstance();

          final PushNotifParams pushNotifParams = PushNotifParams(
            teamId: '${APPLE_TEAM_ID}',
            bundleId: '${BUNDLE_ID}',
          );
          final sipInfoData = SipInfoData.fromJson({
            "accountName": "${Extension}",      // Example 101
            "authPass": "${Password}",
            "registerServer": "${Domain}",
            "outboundServer": "${Domain}",
            "port": PORT,                       // Default 50061
            "displayName": "${Display Name}",   // John, Kate
            "wssUrl": "${WSS Mobile}"
          });

          await pitelClient.registerExtension(
              sipInfoData: sipInfoData,
              pushNotifParams: pushNotifParams,
              appMode: 'dev',                   // 'dev' for debug mode, 'production' for release mode
              shouldRegisterDeviceToken: true); // Set shouldRegisterDeviceToken to true when the user presses the Register button.
        },
        child: const Text("Register"),
      ),
Prop Description Type Default
accountName Extension number String Required
authPass Extension password String Required
registerServer Sip domain String Required
outboundServer Sip domain String Required
port Port String Required
displayName Extension display name String Required
  • Logout extension
await pitelClient.logoutExtension(
  sipInfoData: sipInfoData,
  pushNotifParams: pushNotifParams,
);
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) {
    return CallScreen(
      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
showHoldCall Show action button hold call bool Optional
  • Outgoing call
pitelCall.outGoingCall(
  phoneNumber: "",
  handleRegister: () {
    // handle register function
    await pitelClient.registerExtension(
        sipInfoData: sipInfoData,
        pushNotifParams: pushNotifParams,
        appMode: 'dev',                    // 'dev' for debug mode, 'production' for release mode
        shouldRegisterDeviceToken: false); // Set shouldRegisterDeviceToken to false during an outgoing call.
  }, 
);

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

Libraries

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