flutter_pitel_voip
Integrate VoIP call to your project
flutter_pitel_voip
is package support for voip call.
Demo
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.
Features
- Register Extension
- Call
- Hangup
- Turn on/off micro
- Turn on/of speaker
Installation
- Install Packages
- Run this command:
flutter pub add flutter_pitel_voip
- Or add pubspec.yaml:
flutter_pitel_voip: any
- Get package
flutter pub get
- Import
import 'package:flutter_pitel_voip/flutter_pitel_voip.dart';
- 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
inPodfile
platform :ios, '13.0'
- 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);
- In file
call_screen.dart
Example
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 |
showHoldCall | Show action button hold call | bool | 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:
- Access to link https://tryit.jssip.net/
- Enter extension: example 102
- Click Setting icon
- Enter information to input field
- Save
- Click icon -> to connect
Libraries
- component/app_life_cycle/app_life_cycle
- 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/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_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/transports/websocket_web_impl
- sip/src/ua
- sip/src/uri
- sip/src/utils
- utils/audio_helper
- voip_push/android_connection_service
- voip_push/device_information
- 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