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
Android:
- Add these settings in
build.gradle
:
jcenter()
maven {
url "https://gitlab.com/api/v4/projects/47675059/packages/maven"
credentials(HttpHeaderCredentials) {
name = "Private-Token"
value = "glpat-AzyyrvKz9_pjsgGW4xfp"
}
authentication {
header(HttpHeaderAuthentication)
}
}
//in dependencies
classpath 'com.google.gms:google-services:4.3.13'
//under buildscript
allprojects {
repositories {
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
maven {
url "https://gitlab.com/api/v4/projects/47675059/packages/maven"
credentials(HttpHeaderCredentials) {
name = "Private-Token"
value = "glpat-AzyyrvKz9_pjsgGW4xfp"
}
authentication {
header(HttpHeaderAuthentication)
}
}
}
}
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.
- Update AndroidManifest.xml:
//need request this permission
<uses-permission android:name="android.permission.INTERNET" />
//add these lines inside <activity>
<intent-filter>
<action android:name="com.omicall.sdk.CallingActivity"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
//add these lines outside <activity>
<receiver
android:name="vn.vihat.omicall.omisdk.receiver.FirebaseMessageReceiver"
android:exported="true"
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:exported="false">
</service>
You can refer AndroidManifest to know more information.
- We registered permissions into my plugin:
<uses-permission android:name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.USE_SIP" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
- 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
-
iOS(Object-C):
-
Assets: Add
call_image
into assets folder to update callkit image. We only support png style. -
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"];
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.
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
bool value = [SwiftOmikitPlugin processUserActivityWithUserActivity: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.
- (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):
-
Assets: Add
call_image
into assets folder to update callkit image. We only support png style. -
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")
provider = CallKitProviderDelegate.init(callManager: OMISIPLib.sharedInstance().callManager)
voipRegistry = PKPushRegistry.init(queue: .main)
pushkitManager = PushKitManager.init(voipRegistry: voipRegistry)
Notes:
- To custom callkit image, you need add image into assets and paste image name into setEnviroment function.
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.
Implement
- 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();
- Create OmiKit: OmiKit need userName, password, realm, host to init enviroment. ViHAT Group will provides these information for you. Please contact for my sales:
await OmicallClient.instance.initCall( userName: "", password: "", realm: "", host: "", isVideo: true/false, );
- Create OmiKit With ApiKey: OmiKit need apikey, username, user id to init enviroment. ViHAT Group will provides api key for you. Please contact for my sales:
await OmicallClient.instance.initCallWithApiKey( usrName: "", usrUuid: "", isVideo: true/false, apiKey: "", );
- 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 descriptipn ); //incomingAcceptButtonImage, incomingDeclineButtonImage, backImage, userImage: Add these into `android/app/src/main/res/drawble`
- Start Serivce: OmiKit need start services and register some events.
-
Upload token: OmiKit need FCM for Android and APNS to push notification on user devices.
final token = await FirebaseMessaging.instance.getToken(); String? apnToken; if (Platform.isIOS) { apnToken = await FirebaseMessaging.instance.getAPNSToken(); } String appId = 'Bundle id on iOS/ App id on Android' await OmicallClient.instance.updateToken( fcmToken: token, apnsToken: apnToken, );
-
Other functions:
- Call with phone number (mobile phone or internal number):
final result = await OmicallClient.instance.startCall( phone, //phone number _isVideoCall, //call video or audio. If true is video call. ); //we will return OmiStartCallStatus with: - invalidUuid: uuid is invalid (we can not find on my page) - invalidPhoneNumber: sip user is invalid. - samePhoneNumber: Can not call same phone number. - maxRetry: We try to refresh call but we can not start your call. - permissionDenied: Check audio permission. - couldNotFindEndpoint: Please login before make your call. - accountRegisterFailed: We can not register your account. - startCallFailed: We can not start you call. - startCallSuccess: Start call successfully. - haveAnotherCall: We can not start you call because you are joining 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:
OmicallClient.instance.joinCall();
- End a call: We will push a event
endCall
and return call information for you.OmicallClient.instance.endCall().then((value) { //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" }
- Toggle the audio: On/off audio a call
OmicallClient.instance.toggleAudio();
- Toggle the speaker: On/off the phone speaker
OmicallClient.instance.toggleSpeaker();
- Send character: We only support
1 to 9
and* #
.OmicallClient.instance.sendDTMF(value);
- Get current user information:
final user = await OmicallClient.instance.getCurrentUser(); Output Sample: { "extension": "111", "full_name": "chau1", "avatar_url": "", "uuid": "122aaa" }
- Get guest user information:
final user = await OmicallClient.instance.getGuestUser(); Output Sample: { "extension": "111", "full_name": "chau1", "avatar_url": "", "uuid": "122aaa" }
- Get user information from sip:
final user = await OmicallClient.instance.getUserInfo(phone: "111"); Output Sample: { "extension": "111", "full_name": "chau1", "avatar_url": "", "uuid": "122aaa" }
- Logout:
OmicallClient.instance.logout();
-
Video Call functions: Support only video call, We need enable video in
init functions
andstart call
to implements under functions.- Switch front/back camera: We use the front camera for first time.
OmicallClient.instance.switchCamera();
- Toggle a video in video call: On/off video in video call
- OmicallClient.instance.toggleVideo();
- Register video event: Need to listen remote video ready
OmicallClient.instance.toggleVideo();
- Remove video event: Need to remove video event
OmicallClient.instance.removeVideoEvent();
- Local Camera Widget: Your camera view in a call
LocalCameraView( width: double.infinity, height: double.infinity, onCameraCreated: (controller) { _localController = controller; //we will return the controller to call some functions. }, )
- Remote Camera Widget: Remote camera view in a call
RemoteCameraView( width: double.infinity, height: double.infinity, onCameraCreated: (controller) { _remoteController = controller; }, )
- More function: Refresh camera
//camera controller receive when you create camera widget. RemoteCameraController? _remoteController; LocalCameraController? _localController; //refresh remote camera void refreshRemoteCamera() { _remoteController?.refresh(); } //refresh remote camera void localRemoteCamera() { _localController?.refresh(); }
-
Event listener:
- Important event
callStateChangeEvent
: We provide it to listen call state change.
- Important event
OmicallClient.instance.controller.callStateChangeEvent
//OmiAction have 2 variables: actionName and data
- Action Name value:
- `onCallStateChanged`: Call state changed.
- `onSwitchboardAnswer`: Switchboard sip is listening.
+ onCallStateChanged is call state tracking event. We will return status of state. Please refer `OmiCallState`.
+ Incoming call state lifecycle: incoming(receive on foreround state) -> early -> connecting -> confirmed -> disconnected
+ Outgoing call state lifecycle: calling -> early (call created) -> connecting -> confirmed -> disconnected
+ onSwitchboardAnswer have callback when employee answered script call.
- Other events:
- Call Quality event: Listen call quality event changed
OmicallClient.instance.setCallQualityListener((data) { final quality = data["quality"] as int; }); //we return `quality` key with: 0 is GOOD, 1 is NORMAL, 2 is BAD
- Mic event: Listen on/off mic in a call
OmicallClient.instance.setSpeakerListener((data) { setState(() { isSpeaker = data; }); }); //data is current speaker status.
- Mute event: Listen on/off muted in a call
OmicallClient.instance.setMuteListener((data) { setState(() { isMuted = data; }); }); //data is current muted status.
- Remote video ready: Listen remote video ready.
OmicallClient.instance.setVideoListener((data) { refreshRemoteCamera(); => need refresh camera refreshLocalCamera(); => need refresh camera });
- User tab a missed call notification:
OmicallClient.instance.setMissedCallListener((data) { final String callerNumber = data["callerNumber"]; final bool isVideo = data["isVideo"]; makeCallWithParams(context, callerNumber, isVideo); }); // data is Map. Data has 2 keys: callerNumber, isVideo
- User tab a call log (only
iOS
):
OmicallClient.instance.setCallLogListener((data) { final callerNumber = data["callerNumber"]; final isVideo = data["isVideo"]; makeCallWithParams( context, callerNumber, isVideo, ); }); // data is Map. Data has 2 keys: callerNumber, isVideo