The OmiKit exposes the 📦 omikit-plugin.
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 inteface to interactive with core function like sound/ringtone/codec.
Currently active maintenance and improve performance
✅ Install via npm:
npm install omikit-plugin@latest
✅ Install via yarn:
yarn add omikit-plugin --latest
📌 Config gradle file
- Add these settings in
build.gradle
:
jcenter() // This func will replace soon
maven {
url "https://maven.pkg.github.com/omicall/OMICall-SDK"
credentials {
username = project.findProperty("OMI_USER") ?: "" // Please connect with developer OMI for get information
password = project.findProperty("OMI_TOKEN") ?: ""
}
authentication {
basic(BasicAuthentication)
}
}
// gradle.properties
OMI_USER=omicall
OMI_TOKEN=${OMI_TOKEN} // connect with dev off OMI for get token
// 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 {
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url("$rootDir/../node_modules/react-native/android")
}
maven {
// Android JSC is installed from npm
url("$rootDir/../node_modules/jsc-android/dist")
}
mavenCentral {
// We don't want to fetch react-native from Maven Central as there are
// older versions over there.
content {
excludeGroup "com.facebook.react"
}
}
google()
maven { url 'https://www.jitpack.io' }
maven {
url "https://maven.pkg.github.com/omicall/OMICall-SDK"
credentials {
username = project.findProperty("OMI_USER") ?: ""
password = project.findProperty("OMI_TOKEN") ?: ""
}
authentication {
basic(BasicAuthentication)
}
}
}
}
You can refer android/build.gradle to know more informations.
- Add these settings in
app/build.gradle
:
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
You can refer android/app/build.gradle to know more informations.
📌 Config AndroidManifest.xml file
<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"
android:alwaysRetainTaskState="true"
android:largeHeap="true"
android:exported="true"
android:supportsRtl="true"
android:allowBackup="false"
android:enableOnBackInvokedCallback="true"
// ... your config
>
<activity
android:name=".MainActivity"
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
>
// ... 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
public class MainActivity extends ReactActivity {
// your config ...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
reactApplicationContext = new ReactApplicationContext(this);
}
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent != null) {
OmikitPluginModule.Companion.onGetIntentFromNotification(reactApplicationContext, intent, this);
}
}
@Override
protected void onResume() {
super.onResume();
OmikitPluginModule.Companion.onResume(this);
Intent intent = getIntent();
if (intent != null) {
OmikitPluginModule.Companion.onGetIntentFromNotification(reactApplicationContext, intent, this);
}
// your config ...
}
}
class MainActivity : ReactActivity() {
// your config ....
private var reactApplicationContext: ReactApplicationContext? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val reactInstanceManager: ReactInstanceManager = reactNativeHost.reactInstanceManager
val currentContext = reactInstanceManager.currentReactContext
if (currentContext != null && currentContext is ReactApplicationContext) {
reactApplicationContext = currentContext
Log.d("MainActivity", "ReactApplicationContext is available.")
} else {
Log.d("MainActivity", "ReactApplicationContext Not ready yet, will listen to the event.")
}
reactInstanceManager.addReactInstanceEventListener(object : ReactInstanceManager.ReactInstanceEventListener {
override fun onReactContextInitialized(reactContext: com.facebook.react.bridge.ReactContext) {
if (reactContext is ReactApplicationContext) {
reactApplicationContext = reactContext
Log.d("MainActivity", "ReactApplicationContext đã được khởi tạo.")
}
}
})
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
if (intent != null) {
reactApplicationContext?.let {
OmikitPluginModule.Companion.onGetIntentFromNotification(it, intent, this)
} ?: Log.e("MainActivity", "ReactApplicationContext has not been initialized in onNewIntent.")
} else {
Log.e("MainActivity", "Intent in onNewIntent is null.")
}
}
override fun onResume() {
super.onResume()
reactApplicationContext?.let {
OmikitPluginModule.Companion.onResume(this)
intent?.let { intent ->
OmikitPluginModule.Companion.onGetIntentFromNotification(it, intent, this)
}
} ?: Log.e("MainActivity", "ReactApplicationContext has not been initialized in onResume.")
}
// your config ....
}
import com.google.firebase.FirebaseApp;
// This is important because we push incoming calls via Firebase.
class MainApplication : Application() {
override fun onCreate() {
super.onCreate()
if (FirebaseApp.getApps(this).isEmpty()) {
FirebaseApp.initializeApp(this)
}
}
}
-
✨ Setup remote push notification: Only support Firebase for remote push notification.
-
✅ Add
google-service.json
inandroid/app
(For more information, you can refer Core/App) -
✅ Add Firebase Messaging to receive
fcm_token
(You can refer Cloud Messaging to setup notification for React native) -
✅ For more setting information, please refer Config Push for Android
-
Now let's continue configuring iOS, let's go 🚀
-
✅ 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 for Old Architecture:
#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h>
#import <OmiKit/OmiKit-umbrella.h>
#import <OmiKit/Constants.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, UNUserNotificationCenterDelegate>
@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, strong) PushKitManager *pushkitManager;
@property (nonatomic, strong) CallKitProviderDelegate * provider;
@property (nonatomic, strong) PKPushRegistry * voipRegistry;
@end
- ✅ Add variables in Appdelegate.h for New Architecture:
#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h>
#import <OmiKit/OmiKit-umbrella.h>
#import <OmiKit/Constants.h>
@interface AppDelegate : NSObject <UIApplicationDelegate, UNUserNotificationCenterDelegate, RCTBridgeDelegate>
@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, strong) PushKitManager *pushkitManager;
@property (nonatomic, strong) CallKitProviderDelegate * provider;
@property (nonatomic, strong) PKPushRegistry * voipRegistry;
@end
- ✅ Update AppDelegate.m:
#import <OmiKit/OmiKit.h>
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// ----- Start OmiKit Config ------
[OmiClient setEnviroment:KEY_OMI_APP_ENVIROMENT_SANDBOX userNameKey:@"full_name" maxCall:2 callKitImage:@"call_image" typePushVoip:TYPE_PUSH_CALLKIT_DEFAULT];
_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;
}
// ----- End OmiKit Config ------
return YES;
}
//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
NSLog(@"User Info : %@",notification.request.content.userInfo);
completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
}
// This function is used to send an event back into the app when the user presses on a missed call notification
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
NSDictionary *userInfo = response.notification.request.content.userInfo;
if (userInfo && [userInfo valueForKey:@"omisdkCallerNumber"]) {
NSLog(@"User Info : %@",userInfo);
[OmikitNotification didRecieve:userInfo];
}
completionHandler();
}
// This function will terminate all ongoing calls when the user kills the app
- (void)applicationWillTerminate:(UIApplication *)application {
@try {
[OmiClient OMICloseCall];
}
@catch (NSException *exception) {
}
}
- 📝 Tips: Error Use of undeclared identifier 'OmikitNotification' at file
AppDelegate.m
, please import this line below
#if __has_include("OmikitNotification.h")
#import "OmikitNotification.h"
#elif __has_include(<OmikitPlugin/OmikitPlugin-Swift.h>)
#import <OmikitPlugin/OmikitPlugin-Swift.h>
#else
#import <omikit_plugin/OmikitNotification.h>
#endif
- Add these lines into
Info.plist
:
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for make Call</string>
//If you implement video call
<key>NSCameraUsageDescription</key>
<string>Need camera access for video call functions</string>
- 💡 Save token for
OmiClient
: if You addedCloud 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];
const unsigned char *data = (const unsigned char *)[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 Cloud 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 Core/App) - ✅ Add Firebase Messaging to receive
fcm_token
(You can refer Cloud Messaging to setup notification for React Native) - ✅ 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.
📝Note: At Tab Build Setting off Target Project, you need set: Enable Modules (C and Objective C) : YES
📌 Config turn Off for new architect
✅ For iOS
use_react_native!(
:path => config[:reactNativePath],
:new_arch_enabled => false, // <=== add this line
... your config
)
✅ For Android
- Open file android/gradle.properties and add line below:
# Turn off New Architecture
newArchEnabled=false
📝 Notes: The configurations are similar to those for object C above, with only a slight difference in the syntax of the functions
- ✅ 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, userNameKey: "extension", maxCall: 1, callKitImage: "call_image")
provider = CallKitProviderDelegate.init(callManager: OMISIPLib.sharedInstance().callManager)
voipRegistry = PKPushRegistry.init(queue: .main)
pushkitManager = PushKitManager.init(voipRegistry: voipRegistry)
- ✅ 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 Cloud 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 Core/App) - ✅ Add Firebase Messaging to receive
fcm_token
(You can refer Cloud Messaging to setup notification for React Native) - ✅ 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.
📌 We need you request permission about call before make call:
- ✅ You can use react-native-permissions to do this
-Android:
+ PERMISSIONS.ANDROID.RECORD_AUDIO
+ PERMISSIONS.ANDROID.CALL_PHONE
+ PERMISSIONS.ANDROID.CAMERA; (if you want to make Video calls)
-IOS:
+ PERMISSIONS.IOS.MICROPHONE;
+ PERMISSIONS.IOS.CAMERA; (if you want to make Video calls)
- ✅ Set up Cloud Messaging plugin:
//if you use only on Android. you only implement for Android.
//because we use APNS to push notification on iOS so you don't need add Firebase for iOS.
//But you can use firebase-messaging to get APNS token for iOS.
📌 startServices()
✅ Description:
The startServices()
function is used to initialize necessary services in omikit-plugin
.
It should only be called once in the root file of your application.
- Usage:
// Import startServices from omikit-plugin
import { startServices } from 'omikit-plugin';
// Call startServices() to initialize the required services
startServices();
- 📝 Notes:
• Do not call this function multiple times; it should be called only once when the application starts.
• Ensure thatomikit-plugin
is installed before using this function.
Add the following code to the root file of your application, such as App.js
or index.js
📌 initCallWithApiKey()
📝 Notes: The information below is taken from the API, you should connect with our Technical team for support
✅ Description:
- The
initCallWithApiKey()
function 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
import { initCallWithApiKey, getCurrentUser } from 'omikit-plugin';
import messaging from '@react-native-firebase/messaging';
let token: String;
// Retrieve the appropriate push notification token based on the platform
if (Platform.OS === "ios") {
token = await messaging.getAPNSToken(); // Get APNS token for iOS
} else {
token = await messaging.getToken(); // Get FCM token for Android
}
// Define the login information required for call initialization
const loginInfo = {
usrUuid: usrUuid, // Unique user identifier
fullName: fullName, // User's full name
apiKey: apiKey, // API key for authentication
phone: phone, // User's phone number
fcmToken: token, // FCM token for Android, APNS token for iOS
isVideo: isVideo, // Determines if video calls are enabled
projectId: projectId // Firebase project ID
};
// Initialize call functionality using the provided API key
const result = await initCallWithApiKey(loginInfo);
/* ❌ ❌ NOTE: Please check the user information again, if the object is not empty then you have successfully logged in.
Otherwise, if you have not successfully logged in, you should not navigate to the call screen. When startCall with empty information, it may crash your application or not be clear when receiving the startCall error ❌❌*/
// Example:
if (result){
const infoUser = await getCurrentUser()
if (infoUser != null && Object.keys(infoUser).length > 0) {
// ✅ Login OMI Success
// Can navigate to call screen or start call 🚀 🚀
}
}
📌 initCallWithUserPassword()
📝 Notes: The information below is taken from the API, you should connect with our Technical team for support
✅ Description:
- The
initCallWithUserPassword()
function is for employees. They can call any telecommunications number allowed in your business on the OMI system.
import { initCallWithUserPassword, getCurrentUser } from 'omikit-plugin';
import messaging from '@react-native-firebase/messaging';
let token: String;
// Retrieve the appropriate push notification token based on the platform
if (Platform.OS === "ios") {
token = await messaging.getAPNSToken(); // Get APNS token for iOS
} else {
token = await messaging.getToken(); // Get FCM token for Android
}
// Define the login information required for call initialization
const loginInfo = {
userName: userName, // User's SIP username (string)
password: password, // User's SIP password (string)
realm: realm, // SIP server domain (string)
isVideo: isVideo, // Enables or disables video calls (boolean: true/false)
fcmToken: token, // FCM token for Android, APNS token for iOS
projectId: projectId // Firebase project ID
};
// Initialize call functionality using username and password authentication
const result = await initCallWithUserPassword(loginInfo);
/* ❌ ❌ NOTE: Please check the user information again, if the object is not empty then you have successfully logged in.
Otherwise, if you have not successfully logged in, you should not navigate to the call screen. When startCall with empty information, it may crash your application or not be clear when receiving the startCall error ❌❌*/
// Example:
if (result){
const infoUser = await getCurrentUser()
if (infoUser != null && Object.keys(infoUser).length > 0) {
// ✅ Login OMI Success
// Can navigate to call screen or start call 🚀 🚀
}
}
📌 configPushNotification()
✅ Description: Config push notification: func is used to configure the incoming call popup UI on Android and the representative name for iOS
import { configPushNotification } from 'omikit-plugin';
// Configure push notifications for incoming calls
configPushNotification({
notificationIcon: "calling_face", // Notification icon for Android (located in drawable folder)
prefix: "Cuộc gọi tới từ: ", // Prefix for incoming call notifications
incomingBackgroundColor: "#FFFFFFFF", // Background color for incoming call screen
incomingAcceptButtonImage: "join_call", // Image for the accept call button
incomingDeclineButtonImage: "hangup", // Image for the decline call button
backImage: "ic_back", // Image for the back button
userImage: "calling_face", // Default user image for incoming calls
prefixMissedCallMessage: "Cuộc gọi nhỡ từ", // Prefix message for missed call notifications
missedCallTitle: "Cuộc gọi nhỡ", // Title for missed call notifications
userNameKey: "uuid", // User identification key: options are "uuid", "full_name", or "extension"
channelId: "com.channel.sample", // Custom notification channel ID for Android
audioNotificationDescription: "", // Description for audio call notifications
videoNotificationDescription: "", // Description for video call notifications
representName: "" // Representative name to display for all incoming calls (e.g., business name)
});
// Note: Ensure that the following images are added to `android/app/src/main/res/drawable`:
// - incomingAcceptButtonImage (join_call)
// - incomingDeclineButtonImage (hangup)
// - backImage (ic_back)
// - userImage (calling_face)
📌 getInitialCall()
✅ Description: Get call when user open application at first time
import { getInitialCall } from 'omikit-plugin';
// Check if there is an ongoing call when the app initializes
const callingInfo = await getInitialCall();
if (callingInfo !== false) {
// If there is an active call, navigate to the call screen
navigation.navigate('DialCall' as never, callingInfo as never);
}
// If callingInfo is not false, it means the user has an ongoing call.
📌 startCall()
✅ Description: Used to initiate a call to a random number, telecommunication number, hotline or internal number
import { startCall } from 'omikit-plugin';
// Start a call with the given phone number
const result = await startCall({
phoneNumber: phone, // The phone number to call
isVideo: false // Set to true for a video call, false for an audio call
});
✨ The result returned by startCall()
is an object with the following structure:
result = {
"_id": String // This is call_id. it just have id for iOS,
"status": Number // This is result code when make,
"message": String // This is a string key, describing the status of the call
}
📝 Detailed Description of Possible Results
Message | Status | Description |
---|---|---|
"INVALID_UUID" |
0 | uid is invalid (we can not find on my page) |
"INVALID_PHONE_NUMBER" |
1 | sip user is invalid |
"SAME_PHONE_NUMBER_WITH_PHONE_REGISTER" |
2 | Cannot call same phone number |
"MAX_RETRY" |
3 | Call timeout exceeded, please try again later |
"PERMISSION_DENIED" |
4 | The user has not granted MIC or audio permissions |
"COULD_NOT_FIND_END_POINT" |
5 | Please login before making your call |
"REGISTER_ACCOUNT_FAIL" |
6 | Can't log in to OMI (maybe wrong login information) |
"START_CALL_FAIL" |
7 | Call failed, please try again |
"HAVE_ANOTHER_CALL" |
9 | There is another call in progress; please wait for that call to end |
"EXTENSION_NUMBER_IS_OFF" |
10 | Extension number off User is turn Off |
"START_CALL_SUCCESS" |
8 | START CALL SUCCESSFULLY |
📌 startCallWithUuid()
✅ Description: Call with UUID (only support with Api key):
import { startCallWithUuid } from 'omikit-plugin';
// Initiate a call using the user's UUID. This function works similarly to `startCall()`.
const result = await startCallWithUuid({
usrUuid: uuid, // The user's UUID (unique identifier)
isVideo: false // Set to true for a video call, false for an audio call
});
// The result returned has the same structure as that from `startCall()`.
📌 joinCall()
✅ Description: Used to join (pick up) any incoming call
import {joinCall} from 'omikit-plugin';
await joinCall();
📝 Note: When calling joinCall
, sdk will check permission of microphone and camera. If have any permission denied, sdk will send a event onRequestPermissionAndroid
with list permission you need to request. You need to request permission before calling joinCall
again.
📌 transferCall()
✅ Description: Used to forward the current ongoing call to any employee in your business
import {transferCall} from 'omikit-plugin';
transferCall({
phoneNumber: 102 // employee's internal number
})
📌 endCall()
✅ Description: We will push a event endCall
for you.
import {endCall} from 'omikit-plugin';
const value = await endCall();
//value is call information
Sample output:
{
"transaction_id":ea7dff38-cb1e-483d-8576...........,
"direction":"inbound",
"source_number":111,
"destination_number":110,
"time_start_to_answer":1682858097393,
"time_end":1682858152181,
"sip_user":111,
"disposition":"answered"
}
📌 toggleMute()
✅ Description: Toggle the audio, On/off audio a call
import {toggleMute} from 'omikit-plugin';
toggleMute();
📌 toggleSpeaker()
✅ Description: Toggle the speaker, On/off the phone speaker
import {toggleSpeaker} from 'omikit-plugin';
toggleSpeaker();
📌 toggleHold()
✅ Description: hold current call
import {toggleHold} from 'omikit-plugin';
toggleHold();
📌 sendDTMF()
✅ Description: Send character: We only support 1 to 9
and * #
.
// FUNC IS USED when the user wants key interaction during a call. For example, press key 1, 2, 3.. to move to group
import {sendDTMF} from 'omikit-plugin';
sendDTMF({
character: text,
});
📌 getCurrentUser()
✅ Description: Retrieves the current user's information.
import {getCurrentUser} from 'omikit-plugin';
final user = await getCurrentUser();
✨ Output Sample:
{
"extension": "111",
"full_name": "chau1",
"avatar_url": "",
"uuid": "122aaa"
}
📌 getGuestUser()
✅ Description: Get guest user information:
import {getGuestUser} from 'omikit-plugin';
final user = await getGuestUser();
✨ Output Sample:
{
"extension": "111",
"full_name": "chau1",
"avatar_url": "",
"uuid": "122aaa"
}
📌 ggetUserInfo()
✅ Description: Get user information from internal number
import {getUserInfo} from 'omikit-plugin';
final user = await ggetUserInfo("111");
✨ Output Sample:
{
"extension": "111",
"full_name": "chau1",
"fullName": "chau1",
"avatar_url": "",
"avatarUrl": "",
"uuid": "122aaa"
}
📌 endCall()
✅ Description: End a completed call (including rejecting a call).
import {endCall} from 'omikit-plugin';
endCall();
📌 rejectCall()
✅ Description: Used to reject an incoming call when the user has not accepted it yet.
📝 Note: Do not use this function to end an ongoing call.
import {rejectCall} from 'omikit-plugin';
rejectCall();
📌 logout()
✅ Description: logout and remove all information.
import {logout} from 'omikit-plugin';
logout();
📌 systemAlertWindow()
✅ Description: Check system alert window permission (only Android).
import {systemAlertWindow} from 'omikit-plugin';
const isAllow = await systemAlertWindow();
//true => allow
//false => denied
📌 openSystemAlertSetting()
✅ Description: Open to enable system alert window (only Android).
import {openSystemAlertSetting} from 'omikit-plugin';
if (Platform.OS === 'android') {
openSystemAlertSetting();
}
📌 getCurrentAudio()
✅ Description: Get current information of audio devices
import {getCurrentAudio} from 'omikit-plugin';
getCurrentAudio().then((data: any) => {
console.log(data); // [{"name": "Speaker", "type": "Speaker"}]
// Note: Data is an array containing information about audio devices, with parameters:
// - name: Name of the audio device
// - type: Audio device type (e.g. "Speaker", "Receiver", etc.)
});
📌 setAudio()
✅ Description: set Audio calls the current device
import { getAudio, setAudio} from 'omikit-plugin';
const audioList = await getAudio(); // Get a list of supported audio device types
console.log("audioList --> ", audioList) // audioList --> [{"name": "Receiver", "type": "Receiver"}, {"name": "Speaker", "type": "Speaker"}]
const receiver = audioList.find((element: any) => {
return element.type === 'Receiver'; // type: "Speaker" is the external speaker, Receiver is the internal speaker
});
setAudio({
portType: receiver.type,
});
📝 Video Call functions: Support only video call, You need enable video in init functions
and start call
to implements under functions.
✅ Description: Video Call functions: Support only video call, You need enable video in init functions
and start call
to implements under functions.
📌 Switch front/back camera: We use the front camera for first time.
import {switchOmiCamera} from 'omikit-plugin';
switchOmiCamera();
📌 Toggle a video in video call: On/off video in video call
import {toggleOmiVideo} from 'omikit-plugin';
toggleOmiVideo();
📌 Local Camera Widget: Your camera view in a call
import { OmiLocalCameraView } from 'omikit-plugin';
<OmiLocalCameraView style={styles.localCamera} />
📌 Remote Camera Widget: Remote camera view in a call
import { OmiRemoteCameraView } from 'omikit-plugin';
<OmiRemoteCameraView style={styles.remoteCamera} />
📌 More function: Refresh local camera
import {refreshLocalCamera} from 'omikit-plugin';
refreshLocalCamera();
📌 More function: Refresh remote camera
import {refreshRemoteCamera} from 'omikit-plugin';
refreshRemoteCamera();
📌 Register event: Register remote video ready: only visible on iOS
import {registerVideoEvent} from 'omikit-plugin';
registerVideoEvent();
import { omiEmitter } from 'omikit-plugin';
/*
❌ ❌ With TypeScript, in Android, it seems our omiEmitter is not working properly. Please use the following manual declaration, to ensure performance
*/
// 📌 For TypeScript, Android
import { NativeEventEmitter, NativeModules } from "react-native";
const { OmikitPlugin } = NativeModules;
const omiEmitter = new NativeEventEmitter(OmikitPlugin);
useEffect(() => {
omiEmitter.addListener(OmiCallEvent.onCallStateChanged, onCallStateChanged);
omiEmitter.addListener(OmiCallEvent.onMuted, onMuted);
omiEmitter.addListener(OmiCallEvent.onSpeaker, onSpeaker);
omiEmitter.addListener(OmiCallEvent.onHold, onHold);
omiEmitter.addListener(OmiCallEvent.onClickMissedCall, clickMissedCall);
omiEmitter.addListener(OmiCallEvent.onSwitchboardAnswer, onSwitchboardAnswer);
omiEmitter.addListener(OmiCallEvent.onCallQuality, onCallQuality);
if(Platform.OS == "android") {
omiEmitter.addListener(OmiCallEvent.onRequestPermissionAndroid, onRequestPermission);
}
if (Platform.OS === 'ios') {
registerVideoEvent();
omiEmitter.addListener(
OmiCallEvent.onRemoteVideoReady,
refreshRemoteCameraEvent
);
}
return () => {
omiEmitter.removeAllListeners(OmiCallEvent.onCallStateChanged);
omiEmitter.removeAllListeners(OmiCallEvent.onMuted);
omiEmitter.removeAllListeners(OmiCallEvent.onHold);
omiEmitter.removeAllListeners(OmiCallEvent.onSpeaker);
omiEmitter.removeAllListeners(OmiCallEvent.onSwitchboardAnswer);
if(Platform.OS == "android") {
omiEmitter.removeAllListeners(OmiCallEvent.onRequestPermissionAndroid);
}
if (Platform.OS === 'ios') {
removeVideoEvent();
omiEmitter.removeAllListeners(OmiCallEvent.onRemoteVideoReady);
}
};
}, []);
-
✅ Important Event:
onCallStateChanged
This event is used to listen for call state changes. The emitted event is anOmiAction
object containing two properties:actionName
anddata
. -
📝 Action Name Values:
-
onCallStateChanged
: Indicates that the call state has changed. -
onSwitchboardAnswer
: Indicates that the switchboard SIP is listening. -
Call Status Values:
-
unknown
(0) -
calling
(1) -
incoming
(2) -
early
(3) -
connecting
(4) -
confirmed
(5) -
disconnected
(6) -
hold
(7)
-
-
Note: The
onCallStateChanged
event tracks the current state of the call. Please refer toOmiCallState
for detailed status descriptions.
-
✅ Incoming Call Lifecycle:
incoming
→connecting
→confirmed
→disconnected
-
✅ Outgoing Call Lifecycle:
calling
→early
→connecting
→confirmed
→disconnected
// The event is updated every time the call status changes
const onCallStateChanged = (data: any) => {
// ⚠️ ⚠️ Currently, we support two data formats: camelCase and snake_case. Snake_case is used for data v1, while camelCase is for v2. We encourage customers to use camelCase instead of snake_case, as we plan to completely remove the snake_case format in the future ❌ ❌
/*
Call state change event data (Object) includes:
- _id: string (UUID of the call)
- callInfo: object (Detailed call information)
- callerNumber: string (Phone number of the caller)
- code_end_call, codeEndCall: number (Status code when the call ends)
- destination_number, destinationNumber?: string (Destination phone number, optional)
- direction: string ("inbound" or "outbound", call direction)
- disposition: string (Call answer status)
- incoming: boolean (true if it is an incoming call)
- isVideo: boolean (true if it is a video call)
- sip_user, sipUser: string (Current SIP user)
- source_number, sourceNumber: string (SIP number of the user)
- status: string (value matching with List status call)
- time_end, timeEnd: number (Timestamp when the call ended)
- time_start_to_answer, timeStartToAnswer: number (Time taken to answer the call)
- transaction_id, transactionId: string (OMI Call unique ID)
- typeNumber: string ("", "internal", "phone", "zalo")
*/
};
// Event returned when the user mutes the call
const onMuted = (isMuted: boolean) => {
// isMuted: true when muted call
}
// Event returns value when user holds call
const onHold = (isHold: boolean) => {
// isHold: true when hold call
}
// The event updates the quality of an ongoing call
const onCallQuality = (data: any) => {
const { quality } = data;
// quality: int is mean quality off calling
// 1 is good, 2 is medium, 3 is low
}
// Even when user turn on speakerphone
const onSpeaker = (isSpeaker: boolean) => {
// isSpeaker: true, false
// True mean speaker devices is open
}
// * onSwitchboardAnswer have callback when employee answered script call.
const onSwitchboardAnswer = (data: any) => {
const { sip } = data
// sip: String
}
✨ Table describing code_end_call, codeEndCall
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 |
- Must use "Rosetta Destination" to run debug example app on macOS Apple chip