omicall_flutter_plugin 3.2.3
omicall_flutter_plugin: ^3.2.3 copied to clipboard
OmiKit Flutter is wrapper SDK for OmiCall for Application easy integrate features of Omicall Like Call App2App/App2Phone, Video Call.
π¦ OMICALL SDK FOR Flutter #
The OmiKit exposes the π¦ omicall_flutter_plugin library.
The most important part of the framework is :
- β Help to easy integrate with Omicall.
- β Easy custom Call UI/UX.
- β Optimize codec voip for you.
- β Full interface to interactive with core function like sound/ringtone/codec.
π Status #
Currently active maintenance and improve performance
Running #
Install via pubspec.yaml:
omicall_flutter_plugin: ^latest_version
Configuration #
π οΈ STEP 1: Config native file #
π Android:
π - Config gradle file
- Add these settings in
build.gradle
:
jcenter()
maven {
url "https://maven.pkg.github.com/omicall/OMICall-SDK"
credentials {
username = OMI_USER // Please connect with developer OMI for get information
password = OMI_TOKEN
}
authentication {
basic(BasicAuthentication)
}
}
//in dependencies
classpath 'com.google.gms:google-services:4.3.13' // You can choose the version of google-services to suit your project
//under buildscript
allprojects {
repositories {
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
maven {
url "https://maven.pkg.github.com/omicall/OMICall-SDK"
credentials {
username = OMI_USER
password = OMI_TOKEN
}
authentication {
basic(BasicAuthentication)
}
}
}
}
If you use the latest Flutter using the build.gradle.kts file, the configuration is as follows:
allprojects {
repositories {
google()
mavenCentral()
maven {
url = uri("https://maven.pkg.github.com/omicall/OMICall-SDK")
credentials {
username = project.findProperty("OMI_USER") as? String ?: ""
password = project.findProperty("OMI_TOKEN") as? String ?: ""
}
authentication {
create<BasicAuthentication>("basic")
}
}
}
}
You can refer android/build.gradle to know more information.
- Add these settings in
app/build.gradle
:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'com.google.gms.google-services'
You can refer android/app/build.gradle to know more information.
π - Config AndroidManifest.xml file
//need request this permission
<manifest
// ......
xmlns:tools="http://schemas.android.com/tools">
// your config .....
<uses-feature android:name="android.hardware.telephony" android:required="false" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
// .... your config
<application
android:name=".MainApplication"
// .... your config
android:alwaysRetainTaskState="true"
android:largeHeap="true"
android:exported="true"
android:supportsRtl="true"
android:allowBackup="false"
android:fullBackupContent="false"
android:enableOnBackInvokedCallback="true"
>
<activity
android:name=".MainActivity"
// .... your config
android:windowSoftInputMode="adjustResize"
android:showOnLockScreen="true"
android:launchMode="singleTask"
android:largeHeap="true"
android:alwaysRetainTaskState="true"
android:supportsPictureInPicture="false"
android:showWhenLocked="true"
android:turnScreenOn="true"
android:exported="true"
>
// .... your config
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.CALL" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:host="incoming_call"
android:scheme="omisdk" />
</intent-filter>
// .... your config
</activity>
// .... your config
<receiver
android:name="vn.vihat.omicall.omisdk.receiver.FirebaseMessageReceiver"
android:exported="true"
android:enabled="true"
tools:replace="android:exported"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</receiver>
<service
android:name="vn.vihat.omicall.omisdk.service.NotificationService"
android:enabled="true"
android:exported="false">
</service>
// .... your config
</application>
</manifest>
π - Config MainActivity file
- In the
MainActivity.kt
file we need you to add the following configurations
import androidx.core.app.ActivityCompat.requestPermissions
import android.app.Activity
import io.flutter.embedding.android.FlutterActivity
import vn.vihat.omicall.omicallsdk.OmicallsdkPlugin
import android.Manifest
import androidx.activity.result.contract.ActivityResultContracts
import android.content.pm.PackageManager
import androidx.core.content.ContextCompat
import android.os.Bundle
import android.content.Intent
import android.util.Log
import vn.vihat.omicall.omisdk.utils.SipServiceConstants
class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
try {
val callPermissions = arrayOf(Manifest.permission.RECORD_AUDIO)
if(!isGrantedPermission(Manifest.permission.RECORD_AUDIO)){
requestPermissions(this,callPermissions,0)
}
val isIncomingCall = intent.getBooleanExtra(SipServiceConstants.ACTION_IS_INCOMING_CALL, false)
OmicallsdkPlugin.onOmiIntent(this, intent)
} catch (e: Throwable) {
e.printStackTrace()
}
}
override fun onNewIntent(intent: Intent){
super.onNewIntent(intent);
OmicallsdkPlugin.onOmiIntent(this, intent)
}
override fun onDestroy() {
super.onDestroy()
OmicallsdkPlugin.onDestroy()
}
override fun onResume(){
super.onResume()
OmicallsdkPlugin.onResume(this);
}
fun isGrantedPermission(permission: String): Boolean {
return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
OmicallsdkPlugin.onRequestPermissionsResult(requestCode, permissions, grantResults, this)
}
// Your config
}
- β¨ Setup push notification : Only support Firebase for remote push notification.
-
β Add
google-service.json
inandroid/app
(For more information, you can refer firebase_core) -
β Add Fire Messaging to receive
fcm_token
(You can refer firebase_messaging to setup notification for Flutter) -
β For more setting information, please refer Config Push for Android
-
Now let's continue configuring iOS, let's go π
π iOS(Object-C):
- π Assets: Add
call_image
into assets folder to update callkit image. We only support png style (This will help show your application icon on iOS CallKit when a call comes in)
- π Add variables in Appdelegate.h:
#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h>
#import <OmiKit/OmiKit-umbrella.h>
#import <OmiKit/Constants.h>
#import <UserNotifications/UserNotifications.h>
PushKitManager *pushkitManager;
CallKitProviderDelegate * provider;
PKPushRegistry * voipRegistry;
- π Edit AppDelegate.m:
#import <OmiKit/OmiKit.h>
#import <omicall_flutter_plugin/omicall_flutter_plugin-Swift.h>
- π Add these lines into
didFinishLaunchingWithOptions
:
[OmiClient setEnviroment:KEY_OMI_APP_ENVIROMENT_SANDBOX userNameKey:@"extension" maxCall:1 callKitImage: @"callkit_image" typePushVoip:@"default" representName:@"OMICALL"];
provider = [[CallKitProviderDelegate alloc] initWithCallManager: [OMISIPLib sharedInstance].callManager];
voipRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
pushkitManager = [[PushKitManager alloc] initWithVoipRegistry:voipRegistry];
if (@available(iOS 10.0, *)) {
[UNUserNotificationCenter currentNotificationCenter].delegate = (id<UNUserNotificationCenterDelegate>) self;
}
π Notes:
- To custom callkit image, you need add image into assets and paste image name into setEnviroment function.
- The variable representName is not required. If it has a value, when a call comes in, by default this name will be displayed on callKit. If nothing is transmitted, internal calls will display the Employee's name or the employee's internal
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
bool value = [SwiftOmikitPlugin processUserActivityWithUserActivity:userActivity];
return value;
}
// This action is used to close ongoing calls when the user kills the app
- (void)applicationWillTerminate:(UIApplication *)application {
@try {
[OmiClient OMICloseCall];
}
@catch (NSException *exception) {
}
}
- π Add these lines into
Info.plist
:
<key>NSCameraUsageDescription</key>
<string>Need camera access for video call functions</string>
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for make Call</string>
- π‘ Save token for
OmiClient
: if you addedfirebase_messaging
in your project so you don't need add these lines.
- (void)application:(UIApplication*)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)devToken
{
// parse token bytes to string
const char *data = [devToken bytes];
NSMutableString *token = [NSMutableString string];
for (NSUInteger i = 0; i < [devToken length]; i++)
{
[token appendFormat:@"%02.2hhX", data[i]];
}
// print the token in the console.
NSLog(@"Push Notification Token: %@", [token copy]);
[OmiClient setUserPushNotificationToken:[token copy]];
}
β¨ Only use under lines when added firebase_messaging
plugin in your project
-
β Setup push notification: We only support Firebase for push notification.
-
β Add
google-service.json
inandroid/app
(For more information, you can refer firebase_core) -
β Add Firebase Messaging to receive
fcm_token
(You can refer firebase_messaging to setup notification for Flutter) -
β For more setting information, please refer Config Push for iOS
π iOS(Swift):
-
π Notes: The configurations are similar to those for object C above, with only a slight difference in the syntax of the funcs
-
π Add variables in Appdelegate.swift:
import OmiKit
import PushKit
import NotificationCenter
var pushkitManager: PushKitManager?
var provider: CallKitProviderDelegate?
var voipRegistry: PKPushRegistry?
- π Add these lines into
didFinishLaunchingWithOptions
:
OmiClient.setEnviroment(KEY_OMI_APP_ENVIROMENT_SANDBOX, prefix: "", userNameKey: "extension", maxCall: 1, callKitImage: "callkit_image" typePushVoip:@"default")
provider = CallKitProviderDelegate.init(callManager: OMISIPLib.sharedInstance().callManager)
voipRegistry = PKPushRegistry.init(queue: .main)
pushkitManager = PushKitManager.init(voipRegistry: voipRegistry)
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
var value = SwiftOmikitPlugin.processUserActivity(userActivity: userActivity)
return value
}
- Add these lines into
Info.plist
:
<key>NSCameraUsageDescription</key>
<string>Need camera access for video call functions</string>
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for make Call</string>
- π‘ Save token for
OmiClient
: if you addedfirebase_messaging
in your project so you don't need add these lines.
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let deviceTokenString = deviceToken.hexString
OmiClient.setUserPushNotificationToken(deviceTokenString)
}
extension Data {
var hexString: String {
let hexString = map { String(format: "%02.2hhx", $0) }.joined()
return hexString
}
}
β¨ Only use under lines when added firebase_messaging
plugin in your project
-
β Setup push notification: We only support Firebase for push notification.
-
β Add
google-service.json
inandroid/app
(For more information, you can refer firebase_core) -
β Add Firebase Messaging to receive
fcm_token
(You can refer firebase_messaging to setup notification for Flutter) -
β For more setting information, please refer Config Push for iOS
β Important release note
We support 2 environments. So you need set correct key in Appdelegate.
- KEY_OMI_APP_ENVIROMENT_SANDBOX support on debug mode
- KEY_OMI_APP_ENVIROMENT_PRODUCTION support on release mode
- Visit on web admin to select correct enviroment.
π οΈ STEP 2: Integrate into Flutter code π #
Request permission
- π We need you request permission about call before make call:
+ android.permission.CALL_PHONE (for android)
+ Permission.audio
+ Permission.microphone
+ Permission.camera (if you want to make Video calls)
- π Set up for Firebase:
await Firebase.initializeApp();
// If you only use Firebase on Android. Add these line `if (Platform.isAndroid)`
// Because we use APNS to push notification on iOS so you don't need add Firebase for iOS.
-
π Important function.
-
π Start Serivce: OmiKit need start services and register some events.
// Call in the root widget
OmicallClient.instance.startServices();
π‘ You need to log in to OMI's switchboard system, we provide you with 2 functions with 2 different functions:
π Notes: The information below is taken from the API, you should connect with our Technical team for support
- β func initCall: This func is for employees. They can call any telecommunications number allowed in your business on the OMI system.
String? token = await FirebaseMessaging.instance.getToken();
if (Platform.isIOS) {
token = await FirebaseMessaging.instance.getAPNSToken();
}
await OmicallClient.instance.initCall(
userName: String, // Replace with your username
password:String, // Replace with your password
realm: String, // Replace with your realm
host: String, // Replace with your host
isVideo: bool, // true if video call is enabled, otherwise false
fcmToken: String // For iOS, use APNSToken; for Android, FCM token
projectId: String // Replace with your Firebase project ID
);
// result is true then user login successfully.
- β func initCallWithApiKey: is usually used for your client, who only has a certain function, calling a fixed number. For example, you can only call your hotline number
String? token = await FirebaseMessaging.instance.getToken();
if (Platform.isIOS) {
token = await FirebaseMessaging.instance.getAPNSToken();
}
await OmicallClient.instance.initCallWithApiKey(
usrName:String, // Replace with your username
usrUuid: String, // Replace with your user UUID
isVideo: bool, // true if video call is enabled, otherwise false
apiKey:String, // Replace with your API key
fcmToken: String // Note: with IOS, we need APNSToken, and android is FCM_Token,
projectId: String // Replace with your Firebase project ID
);
// result is true then user login successfully.
- β Get call when user open app from killed status(only iOS):
final result = await OmicallClient.instance.getInitialCall();
///if result is not equal False => have a calling.
-
β Config push notification: With iOS, I only support these keys:
prefixMissedCallMessage
,missedCallTitle
,userNameKey
. With Android, We don't supportmissedCallTitle
:OmicallClient.instance.configPushNotification( notificationIcon : "calling_face", //notification icon on Android prefix : "Cuα»c gα»i tα»i tα»«: ", incomingBackgroundColor : "#FFFFFFFF", incomingAcceptButtonImage : "join_call", //image name incomingDeclineButtonImage : "hangup", //image name backImage : "ic_back", //image name: icon of back button userImage : "calling_face", //image name: icon of user default prefixMissedCallMessage: 'Cuα»c gα»i nhα»‘ tα»«' //config prefix message for the missed call missedCallTitle: 'Cuα»c gα»i nhα»‘', //config title for the missed call userNameKey: 'uuid', //we have 3 values: uuid, full_name, extension channelId: 'channelid.callnotification' // need to use call notification, audioNotificationDescription: "" //audio description videoNotificationDescription: "" //video description representName: "" // Optional value, if nothing is passed down or nil, will display the employee's name or extension number when a call comes in. If you declare a value, this value will be displayed on CallKit when there is an incoming call ); //incomingAcceptButtonImage, incomingDeclineButtonImage, backImage, userImage: Add these into `android/app/src/main/res/drawble`
copied to clipboard -
β OMI Plugin functions:
π Call with Phone Number (Mobile Phone or Internal Number)
// Used to initiate a call, to any number
final result = await OmicallClient.instance.startCall(
phone, // phone number
_isVideoCall // if true, it's a video call; otherwise, it's an audio call.
);
// After calling func, please wait and check the results. Once in state 8 navigate to your ActiveCall screen
Note |
---|
You must await the call. When the result equals 8, it means the call was started successfullyβuse this status to trigger navigation or further actions. |
OmiStartCallStatus: |
- invalidUuid (0): The provided UUID is invalid (cannot be found in our system). |
- invalidPhoneNumber (1): The SIP user (phone number) is invalid. |
- samePhoneNumber (2): Cannot call the same phone number. |
- maxRetry (3): We attempted to refresh the call, but we couldn't start it. |
- permissionDenied (4): Check if the audio permission is granted. |
- couldNotFindEndpoint (5): Please log in before making your call. |
- accountRegisterFailed (6): We cannot register your account. |
- startCallFailed (7): We cannot start your call. |
- startCallSuccess (8): The call has started successfully. |
- haveAnotherCall (9): Cannot start the call because you are already in another call. |
π Call with UUID (only support with Api key):
final result = OmicallClient.instance.startCallWithUUID(
uuid, //your user id
_isVideoCall, //call video or audio. If true is video call.
);
// Result is the same with startCall
π Accept a call:
Used to join (pick up) any incoming call
OmicallClient.instance.joinCall();
π End a Call
When a call ends, an event endCall
is pushed and the call information is returned.
OmicallClient.instance.endCall().then((callInfo) {
// callInfo contains the call details
print(callInfo);
});
/* Sample output:
{
"transaction_id": "ea7dff38-cb1e-483d-8576-xxxxxxxxxxxx",
"direction": "inbound",
"source_number": 111,
"destination_number": 110,
"time_start_to_answer": 1682858097393,
"time_end": 1682858152181,
"sip_user": 111,
"disposition": "answered"
}
*/
π Toggle the Audio
Toggle the audio on/off during a call.
OmicallClient.instance.toggleAudio();
Toggle the Speaker
π Toggle the phone speaker on/off.
OmicallClient.instance.toggleSpeaker();
π Toggle the Hold
Used to hold an ongoing call
OmicallClient.instance.toggleHold();
π Send Character
Send DTMF characters. Supported characters: 1
to 9
, *
and #
.
OmicallClient.instance.sendDTMF(value);
π Transfer call
Used to forward the current ongoing call to any employee in your business
// phoneNumber: String - is number internal employee in your business
OmicallClient.instance.transferCall(phoneNumber: "101");
π Get Current User Information
Retrieve information of the current user.
final user = await OmicallClient.instance.getCurrentUser();
// Sample output:
{
"extension": "111",
"full_name": "chau1",
"avatar_url": "",
"uuid": "122aaa"
}
π Get Guest User Information
Retrieve information of the guest user.
final user = await OmicallClient.instance.getGuestUser();
// Sample output:
{
"extension": "111",
"full_name": "chau1",
"avatar_url": "",
"uuid": "122aaa"
}
π Get User Information from SIP
Retrieve user information based on a SIP phone number.
final user = await OmicallClient.instance.getUserInfo(phone: "111");
// Sample output:
{
"extension": "111",
"full_name": "chau1",
"avatar_url": "",
"uuid": "122aaa"
}
π Logout
Log out the current user.
OmicallClient.instance.logout();
Video Call Functions ππ
π Note: These functions support video calls only. Make sure you enable video in the initialization functions and when starting a call.
-
π Switch Front/Back Camera
Use this function to switch between the front and back cameras. By default, the front camera is used for the initial call.OmicallClient.instance.switchCamera();
copied to clipboard -
π Toggle Video During Call
Turn the video on or off during an active call.OmicallClient.instance.toggleVideo();
copied to clipboard -
π Register Video Event
Listen for remote video readiness. (Replace with the actual function if different.)OmicallClient.instance.registerVideoEvent();
copied to clipboard -
π Remove Video Event
Remove the remote video event listener.OmicallClient.instance.removeVideoEvent();
copied to clipboard -
π Local Camera Widget
Display your local camera view during a call.LocalCameraView( width: double.infinity, height: double.infinity, onCameraCreated: (controller) { _localController = controller; // The controller can be used for further actions. }, )
copied to clipboard -
π Remote Camera Widget
Display the remote camera view during a call.RemoteCameraView( width: double.infinity, height: double.infinity, onCameraCreated: (controller) { _remoteController = controller; }, )
copied to clipboard -
π Refresh Camera Functions
Use the controllers to refresh the camera views when needed.// Assume controllers are defined: RemoteCameraController? _remoteController; LocalCameraController? _localController; // Refresh the remote camera void refreshRemoteCamera() { _remoteController?.refresh(); } // Refresh the local camera void refreshLocalCamera() { _localController?.refresh(); }
copied to clipboard
Event listener β¨:
-
π Important Event:
callStateChangeEvent
Listen to call state changes. The event returns anOmiAction
object that contains two variables:actionName
anddata
.OmicallClient.instance.controller.callStateChangeEvent.listen((action) { // Process action.actionName and action.data debugPrint("Received action: ${action.actionName} with data: ${action.data}"); });
copied to clipboardβ Action Name Values:
onCallStateChanged
: Call state has changed.onSwitchboardAnswer
: The switchboard SIP is listening.
β Call State Status:
unknown (0)
calling (1)
incoming (2)
early (3)
connecting (4)
confirmed (5)
disconnected (6)
hold (7)
β Details for
onCallStateChanged
:isVideo
:bool
(true for video call)status
:number
(matching one of the statuses above)callerNumber
: Phone numberincoming
:bool
(indicates incoming or outgoing call)_id
: (optional, call identifier)
β Lifecycle:
- Incoming call:
incoming
βconnecting
βconfirmed
βdisconnected
- Outgoing call:
calling
βearly
βconnecting
βconfirmed
βdisconnected
-
π Other Events:
-
π Call Quality Event:
Listen to call quality changes. The event returns a Map with keys such asquality
, and a nestedstat
object.OmicallClient.instance.setCallQualityListener((data) { final quality = data["quality"] as int; // 0: GOOD, 1: NORMAL, 2: BAD final req = data["stat"]["req"] as double; // Time taken for the call final mos = data["stat"]["mos"] as double; // MOS value final jitter = data["stat"]["jitter"] as double; // Jitter final latency = data["stat"]["latency"] as double;// Latency final ppl = data["stat"]["ppl"] as double; // Packet loss percentage final lcn = data["stat"]["lcn"] as int; // Loss connect count final isNeedLoading = data["isNeedLoading"] as bool; // Show loading if true debugPrint("Call quality: $quality, req: $req, mos: $mos, jitter: $jitter, latency: $latency, ppl: $ppl, lcn: $lcn, isNeedLoading: $isNeedLoading"); });
copied to clipboard -
π Speaker Event:
Listen for speaker status changes.OmicallClient.instance.setSpeakerListener((data) { setState(() { isSpeaker = data; }); }); // data: current speaker status (bool)
copied to clipboard -
π Mute Event:
Listen for mute status changes.OmicallClient.instance.setMuteListener((data) { setState(() { isMuted = data; }); }); // data: current mute status (bool)
copied to clipboard -
π Hold Event:
Listen for hold status changes.OmicallClient.instance.setHoldListener((data) { setState(() { isHold = data; }); }); // data: current hold status (bool)
copied to clipboard -
π Remote Video Ready Event:
Listen for when remote video is ready. Refresh the camera views as needed.OmicallClient.instance.setVideoListener((data) { refreshRemoteCamera(); // refresh remote camera view refreshLocalCamera(); // refresh local camera view });
copied to clipboard -
π Missed Call Notification:
Triggered when a user taps a missed call notification. The event returns a Map with keyscallerNumber
andisVideo
.OmicallClient.instance.setMissedCallListener((data) { final String callerNumber = data["callerNumber"]; final bool isVideo = data["isVideo"]; makeCallWithParams(context, callerNumber, isVideo); }); // data: Map with "callerNumber" and "isVideo"
copied to clipboard -
π Call Log Event (iOS Only):
Triggered when the user taps a call log entry.OmicallClient.instance.setCallLogListener((data) { final String callerNumber = data["callerNumber"]; final bool isVideo = data["isVideo"]; makeCallWithParams(context, callerNumber, isVideo); }); // data: Map with "callerNumber" and "isVideo"
copied to clipboard
-
- π Table describing code_end_call status
Code | Description |
---|---|
600, 503 |
These are the codes of the network operator or the user who did not answer the call |
408 |
Call request timeout (Each call usually has a waiting time of 30 seconds. If the 30 seconds expire, it will time out) |
403 |
Your service plan only allows calls to dialed numbers. Please upgrade your service pack |
404 |
The current number is not allowed to make calls to the carrier |
480 |
The number has an error, please contact support to check the details |
603 |
The call was rejected. Please check your account limit or call barring configuration! |
850 |
Simultaneous call limit exceeded, please try again later |
486 |
The listener refuses the call and does not answer |
601 |
Call ended by the customer |
602 |
Call ended by the other employee |
603 |
The call was rejected. Please check your account limit or call barring configuration |
850 |
Simultaneous call limit exceeded, please try again later |
851 |
Call duration limit exceeded, please try again later |
852 |
Service package not assigned, please contact the provider |
853 |
Internal number has been disabled |
854 |
Subscriber is in the DNC list |
855 |
Exceeded the allowed number of calls for the trial package |
856 |
Exceeded the allowed minutes for the trial package |
857 |
Subscriber has been blocked in the configuration |
858 |
Unidentified or unconfigured number |
859 |
No available numbers for Viettel direction, please contact the provider |
860 |
No available numbers for VinaPhone direction, please contact the provider |
861 |
No available numbers for Mobifone direction, please contact the provider |
862 |
Temporary block on Viettel direction, please try again |
863 |
Temporary block on VinaPhone direction, please try again |
864 |
Temporary block on Mobifone direction, please try again |
865 |
he advertising number is currently outside the permitted calling hours, please try again later |