3.2.74 β€’ Published 4 months ago

omikit-plugin v3.2.74

Weekly downloads
-
License
MIT
Repository
github
Last release
4 months ago

πŸ“¦ OMICALL SDK FOR React-Native

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.

πŸ“ Status

Currently active maintenance and improve performance

πŸ› οΈ Configuration

πŸ› οΈ Install

βœ… Install via npm:

npm install omikit-plugin@latest

βœ… Install via yarn:

yarn add omikit-plugin --latest

πŸ› οΈ Step 1: Config native file

πŸš€ Android:

πŸ“Œ 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

βœ… For React Native < 0.74

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

βœ… For React Native > 0.74

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 ....
}
  • ✨ Setup remote push notification: Only support Firebase for remote push notification.

    • βœ… Add google-service.json in android/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 πŸš€

πŸš€ Config for IOS
πŸ“Œ 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 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 added Cloud 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 in android/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

❌ Currently, OMICALL does not support React Native new architect.

πŸ“Œ 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

πŸ“Œ iOS(Swift):

πŸ“ 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 added firebase_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 in android/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.

πŸ› οΈ Step 2: Integrate into React Native code

πŸš€ Request permission

πŸ“Œ 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.

πŸš€ OMIKIT-Plugin functions πŸš€

πŸ“Œ 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:<br>
 β€’	Do not call this function multiple times; it should be called only once when the application starts. <br>
 β€’	Ensure that `omikit-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: <br>
 - 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 

```javascript
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

MessageStatusDescription
"INVALID_UUID"0uid is invalid (we can not find on my page)
"INVALID_PHONE_NUMBER"1sip user is invalid
"SAME_PHONE_NUMBER_WITH_PHONE_REGISTER"2Cannot call same phone number
"MAX_RETRY"3Call timeout exceeded, please try again later
"PERMISSION_DENIED"4The user has not granted MIC or audio permissions
"COULD_NOT_FIND_END_POINT"5Please login before making your call
"REGISTER_ACCOUNT_FAIL"6Can't log in to OMI (maybe wrong login information)
"START_CALL_FAIL"7Call failed, please try again
"HAVE_ANOTHER_CALL"9There is another call in progress; please wait for that call to end
"START_CALL_SUCCESS"8START 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();

πŸš€πŸš€ Events listener πŸš€πŸš€

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 an OmiAction object containing two properties: actionName and data.

  • πŸ“ 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 to OmiCallState for detailed status descriptions.

πŸ“ž Call State Lifecycle

  • βœ… 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

CodeDescription
600, 503These are the codes of the network operator or the user who did not answer the call
408Call request timeout (Each call usually has a waiting time of 30 seconds. If the 30 seconds expire, it will time out)
403Your service plan only allows calls to dialed numbers. Please upgrade your service pack
404The current number is not allowed to make calls to the carrier
480The number has an error, please contact support to check the details
603The call was rejected. Please check your account limit or call barring configuration!
850Simultaneous call limit exceeded, please try again later
486The listener refuses the call and does not answer
601Call ended by the customer
602Call ended by the other employee
603The call was rejected. Please check your account limit or call barring configuration
850Simultaneous call limit exceeded, please try again later
851Call duration limit exceeded, please try again later
852Service package not assigned, please contact the provider
853Internal number has been disabled
854Subscriber is in the DNC list
855Exceeded the allowed number of calls for the trial package
856Exceeded the allowed minutes for the trial package
857Subscriber has been blocked in the configuration
858Unidentified or unconfigured number
859No available numbers for Viettel direction, please contact the provider
860No available numbers for VinaPhone direction, please contact the provider
861No available numbers for Mobifone direction, please contact the provider
862Temporary block on Viettel direction, please try again
863Temporary block on VinaPhone direction, please try again
864Temporary block on Mobifone direction, please try again
865he advertising number is currently outside the permitted calling hours, please try again later

⚠️ Issues

✨ iOS

  • Must use "Rosetta Destination" to run debug example app on macOS Apple chip
3.2.39

8 months ago

3.2.68

5 months ago

3.2.67

5 months ago

3.2.69

5 months ago

3.2.60

6 months ago

3.2.62

6 months ago

3.2.61

6 months ago

3.2.64

6 months ago

3.2.63

6 months ago

3.2.66

5 months ago

3.2.65

5 months ago

3.2.71

5 months ago

3.2.70

5 months ago

3.2.73

4 months ago

3.2.72

4 months ago

3.2.74

4 months ago

3.2.46

6 months ago

3.2.45

7 months ago

3.2.48

6 months ago

3.2.47

6 months ago

3.2.49

6 months ago

3.2.40

8 months ago

3.2.42

7 months ago

3.2.41

7 months ago

3.2.44

7 months ago

3.2.43

7 months ago

3.2.57

6 months ago

3.2.56

6 months ago

3.2.59

6 months ago

3.2.51

6 months ago

3.2.50

6 months ago

3.2.53

6 months ago

3.2.52

6 months ago

3.2.55

6 months ago

3.2.54

6 months ago

3.2.35

1 year ago

3.2.34

1 year ago

3.2.37

1 year ago

3.2.36

1 year ago

3.2.38

12 months ago

3.2.33

1 year ago

3.2.32

1 year ago

3.2.29

1 year ago

3.2.31

1 year ago

3.2.30

1 year ago

3.2.28

1 year ago

3.2.27

1 year ago

3.2.26

1 year ago

3.2.24

2 years ago

3.2.25

2 years ago

3.2.23

2 years ago

3.2.21

2 years ago

3.1.9

2 years ago

3.1.8

2 years ago

3.2.2

2 years ago

3.0.4

2 years ago

3.2.1

2 years ago

3.0.3

2 years ago

3.2.0

2 years ago

3.2.6

2 years ago

3.0.8

2 years ago

3.2.5

2 years ago

3.2.4

2 years ago

3.0.6

2 years ago

3.2.3

2 years ago

3.0.5

2 years ago

3.2.9

2 years ago

3.2.8

2 years ago

3.2.7

2 years ago

3.0.9

2 years ago

3.2.12

2 years ago

3.1.2

2 years ago

3.2.15

2 years ago

3.1.1

2 years ago

3.2.14

2 years ago

3.1.0

2 years ago

3.2.17

2 years ago

3.1.7

2 years ago

3.2.16

2 years ago

3.1.6

2 years ago

3.2.19

2 years ago

3.1.5

2 years ago

3.2.18

2 years ago

3.1.4

2 years ago

3.2.11

2 years ago

3.2.10

2 years ago

2.3.2

2 years ago

2.4.0

2 years ago

2.3.1

2 years ago

2.3.4

2 years ago

2.3.3

2 years ago

3.0.2

2 years ago

3.0.1

2 years ago

3.0.0

2 years ago

2.3.0

2 years ago

2.2.1

2 years ago

2.1.2

2 years ago

2.0.3

2 years ago

2.2.0

2 years ago

2.1.1

2 years ago

2.0.2

2 years ago

2.2.3

2 years ago

2.2.2

2 years ago

2.1.3

2 years ago

2.0.4

2 years ago

2.2.4

2 years ago

2.0.1

2 years ago

2.0.0

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago

0.3.1

2 years ago

0.3.0

2 years ago

0.2.0

2 years ago

0.1.0

2 years ago