Video Call

Last Updated on : 2024-04-26 08:49:27download

The video call capability consists of audio and video features and call management. It enables two-way video calls for control panels and IPCs with screens.

How it works

With the app, users can make and receive video calls to and from an IPC.

  1. Initialize the two-way video call SDK and register the message listener.
  2. When the app makes a call, verify if the target device supports two-way video calls. If so, proceed to step 4.
  3. When the device makes a call to the app:
    • The app receives an MQTT message, displays the call screen, and proceeds to step 4.
    • The app receives a push notification. Tapping the notification will open the call screen and proceed to step 4.
  4. Listen for and synchronize the call status.
  5. Create a P2P connection, turn on the phone’s camera, stream video, and enable audio to initiate a video call.
  6. End a call when it is hung up or canceled or a network issue occurs.

Check two-way video call support

Check if the device supports two-way video calls.

API description

 - (void)fetchDeviceCallAbilityByDevId:(NSString *)devId completion:(ThingSmartCallFetchCompletion)completion

Parameters

Parameter Description
devId The device ID.
completion The callback. A Boolean value is returned, with YES for support.

Example

 [ThingSmartCallChannel.sharedInstance fetchDeviceCallAbilityByDevId:devId completion:^(BOOL result, NSError * _Nullable error) {}];

Initialize and configure the SDK

Initialize the video call module to manage call status. It is recommended to perform the initialization after the user login.

Before making calls using the SDK, it must be pre-initialized and configured.

Start call service

API description

- (void)launch;

Register call UI

- (BOOL)registerCallInterfaceManager:(id<ThingCallInterfaceManager>)callInterfaceManager;

callInterfaceManager

The call page management class handles generating, presenting, and closing a call page.

Register module identifier

Currently, only ThingCallInterfaceManagerScreenIPCIdentifier is supported, which corresponds to call messages.

@property (nonatomic, copy) ThingCallInterfaceManagerIdentifier identifier;

Generate call page

- (id<ThingSmartCallInterface>)generateCallInterfaceWithCall:(id<ThingSmartCallProtocol>)call;

Present call page

- (void)presentInterface:(id<ThingSmartCallInterface>)interface completion:(ThingCallInterfaceManagerCompletion)completion;

Close call page

- (void)dismissInterface:(id<ThingSmartCallInterface>)interface completion:(ThingCallInterfaceManagerCompletion)completion;

Register delegate

The callback to be invoked when a video call exception occurs.

- (BOOL)addDelegate:(id<ThingSmartCallChannelDelegate>)delegate;

MQTT/push call

An incoming call message delivered over MQTT or push is sent to the SDK for management, which will check if the call is active. If an exception occurs, the SDK returns the error code through ThingSmartCallError.

- (void)callChannel:(ThingSmartCallChannel *)callChannel didReceiveInvalidCall:(id<ThingSmartCallProtocol>)call error:(NSError *)error;
- (void)callChannel:(ThingSmartCallChannel *)callChannel didReceiveInvalidPushCall:(id<ThingSmartCallProtocol>)call error:(NSError *)error;

Intercept all MQTT-based video call messages

This method is not recommended.

- (void)callChannel:(ThingSmartCallChannel *)callChannel didReceiveCallEventsMessage:(id<ThingSmartCallEventMessage>)message;

ThingSmartCallType

typedef NS_ENUM(NSUInteger, ThingSmartCallType) {
    ThingSmartCallTypeOneToOne = 1, //one to one
    ThingSmartCallTypeOneToMore = 2, //one to more,if one reject, the call stops.
    ThingSmartCallTypeOneToMoreSpecial = 3, //one to more, if one reject, the call has no effect.
};

ThingSmartCallProtocol

The call model, including the status during a call.

Parameter Description
curId The caller ID.
targetId The recipient ID.
sessionId The ID of the call session.
timeout The timeout period.
extra The additional parameters in map type, converted into JSON as follows: {"bizType":"screen_ipc","channelType":2,"category":"sp_dpsxj"}
accepted A Boolean value indicating whether the call was accepted.
answered A Boolean value indicating whether the call was answered.
end A Boolean value indicating whether the call was ended.
connected A Boolean value indicating whether the P2P connection was created.
outgoing Indicates whether this is an outgoing call.
callType The type of the call, an enum of ThingSmartCallType.

ThingSmartCallEventMessage

The call event message.

Parameter Description
curId The caller ID.
targetId The recipient ID.
sessionId The ID of the call session.
timeout The timeout period.
extra The additional parameters in map type, converted into JSON as follows: {"bizType":"screen_ipc","channelType":2,"category":"sp_dpsxj"}
callEvent The call event enum ThingSmartCallEvent.
eventName The name of the call event ThingSmartCallEventName.
callType The type of the call, an enum of ThingSmartCallType.

Example

#import <ThingSmartCallChannelKit/ThingSmartCallChannelKit.h>

@interface DemoCallManager : NSObject <ThingSmartCallChannelDelegate>

@end

@implementation DemoCallManager

+ (void)load {
    [DemoCallManager.sharedInstance configurateCallSDK];
}

+ (instancetype)sharedInstance {
    static DemoCallManager *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[DemoCallManager alloc] init];
    });
    return instance;
}

- (void)configurateCallSDK {
    [ThingSmartCallChannel.sharedInstance launch];
    [ThingSmartCallChannel.sharedInstance addDelegate:self];
    CameraCallInterfaceManager *interfaceManager = [[CameraCallInterfaceManager alloc] init];
    interfaceManager.identifier = ThingCallInterfaceManagerScreenIPCIdentifier;
    [ThingSmartCallChannel.sharedInstance registerCallInterfaceManager:interfaceManager];
}

#pragma mark - ThingSmartCallChannelDelegate

//receive a call, but it is an invalid call, then will call it, eg: go to device panel or an error page.
- (void)callChannel:(ThingSmartCallChannel *)callChannel didReceiveInvalidPushCall:(id<ThingSmartCallProtocol>)call error:(NSError *)error {
    if ([call.targetId isKindOfClass:NSString.class] && call.targetId.length) {
        NSLog(@"The call is invalid");
    }
}

- (void)callChannel:(ThingSmartCallChannel *)callChannel didReceiveInvalidCall:(id<ThingSmartCallProtocol>)call error:(NSError *)error {
    if (error.code == ThingSmartCallErrorOnCalling) {
        NSLog(@"is on calling");
    }
}

@end

Outgoing call

The IPC SDK initiates a video call.

Check ongoing video call

Check if the SDK is already on a video call. Only one session is allowed at a time. If the SDK is on a call, it will return YES.

API description

- (BOOL)isOnCalling;

Initiate a call

API description

- (void)startCallWithTargetId:(NSString *)targetId timeout:(NSInteger)timeout extra:(NSDictionary *)extra success:(nullable ThingSmartCallSuccess)success failure:(nullable ThingSmartCallFailure)failure;

Parameters

Parameter Description
targetId The recipient ID, which is usually the device ID.
timeout The timeout period.
extra The additional parameters in map type, converted into JSON as follows: {"bizType":"screen_ipc","channelType":2,"category":"sp_dpsxj","keepConnect":false}
success The success callback ThingSmartCallSuccess.
failure The failure callback ThingSmartCallFailure returns NSError.

ThingSmartCallError

typedef NS_ENUM(NSInteger, ThingSmartCallError) {

    ThingSmartCallErrorInvalidParams = -2500,
    ThingSmartCallErrorRequestFailed = -2501,
    ThingSmartCallErrorInvalidResponse = -2502,
    ThingSmartCallErrorInvalidData = -2503,
    ThingSmartCallErrorInterfaceManagerNotFound = -2504,//did not register call interface manager

    ThingSmartCallErrorUndefinedSessionId = -2508,

    //sender
    ThingSmartCallErrorRejected = -2510, //reject
    ThingSmartCallErrorPeerBusy = -2511, //busy
    ThingSmartCallErrorNotAnswer = -2512, //not answer
    ThingSmartCallErrorPeerHangUp = -2513, //hang up

    //receiver
    ThingSmartCallErrorOnCalling = -2520, //on calling
    ThingSmartCallErrorRejectedByOthers = -2521, //rejected by others
    ThingSmartCallErrorAnsweredByOthers = -2522, //answered by others
    ThingSmartCallErrorCancel = -2523, //sender cancel

    //sender & receiver
    ThingSmartCallErrorTimeout = -2530, //timeout
    ThingSmartCallErrorConnectFail = -2531, //connect failed
    ThingSmartCallErrorDisconnect = -2532, //disconnect
    ThingSmartCallErrorStop = -2533, //remote stop

    //others
    ThingSmartCallErrorNetworkChanged = -2570,//network changed
    ThingSmartCallErrorEnterBackground = -2571 //enter background
};

Example

 [ThingSmartCallChannel.sharedInstance startCallWithTargetId:devId timeout:30 extra:extra success:^{} failure:^(NSError * _Nullable error){}];

Integrate push messages

The SDK does not come with the push capability, so you need to manually invoke a specific method to forward push messages.

API description

 - (void)handlePushMessage:(NSDictionary *)message;

Parameters

Parameter Description
message The push dictionary NSDictionary. See Demo for the push message details.

Example

@interface AppDelegate ()

@end

@implementation AppDelegate

- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler {

    if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        NSDictionary *userInfo = response.notification.request.content.userInfo;
        if (userInfo) {
            [self handleRemoteNotificationWithHigherVersion:userInfo];
        }
    }else {
        // Local notification processing.

    }
    completionHandler();
}

- (void)handleRemoteNotificationWithHigherVersion:(NSDictionary *)userInfo {
    NSString *link = [userInfo objectForKey:@"link"];
    NSNumber *ts = [userInfo objectForKey:@"ts"];
    NSNumber *voipEnable = [userInfo objectForKey:@"voipEnable"];

    if ([link isKindOfClass:NSString.class] && link.length > 0 && [link containsString:@"://rtcCall"]) {
        NSURL *url = [NSURL URLWithString:link];
        if ([url.host isEqualToString:@"rtcCall"]) {
            // Parse the parameters in the URL.
            NSDictionary *info = [url queryDictionary];//Pseudocode
            NSString *param = [info thing_stringForKey:@"param"];
            if (![param isKindOfClass:NSString.class]) {
                return;
            }


            NSError *error;
            NSData *jsonData = [param dataUsingEncoding:NSUTF8StringEncoding];
            NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error:&error];
            if (error == nil) {
                return;
            }

            if (dic == nil && ![dic isKindOfClass:NSDictionary.class]) {
                return;
            }

            NSMutableDictionary *map = [dic mutableCopy];
            if (voipEnable) [map setObject:voipEnable forKey:@"voipEnable"];

            [ThingSmartCallChannel.sharedInstance handlePushMessage:map];

            return;
        }
    }
}
@end

Call page

The SDK only provides the video call capability, without the call page UI. Follow ThingSmartCallInterface and implement the interaction between the UI and SDK. It is recommended to use the system’s presentViewController: and dismissViewControllerAnimated: to present and close the call page.

Initialize call page

- (instancetype)initWithCall:(id<ThingSmartCallProtocol>)call;

Parameters

Parameter Description
call The video call model.

Prepare for video call

Prepare for the video call, such as device data synchronization.

- (void)setupCompleted:(void(^)(NSError *error))completed;

Parameters

Parameter Description
completed The completion callback.

Call answered

- (void)callPeerDidRespond;

Call failed

- (void)callEndWithError:(nullable NSError *)error;

Parameters

Parameter Description
error The error NSError.

Perform blocking tasks

Perform tasks that keep the main thread blocked, such as starting audio and video talk.

- (void)executeHeavyTasksCompleted:(void(^ __nullable)(NSError * _Nullable error))completed;

Parameters

Parameter Description
error The error NSError.

Actuator

Synchronize the video call action with the SDK to manage the session status.

@property (nonatomic, weak) id<ThingCallActionExecuter> actionExecuter;

Play ringtone

When a call comes in, the app will play a ringtone and send ring to the device. Ringtone playing on the app is intended to be implemented by you.

- (void)interface:(id<ThingSmartCallInterface>)interface onRing:(id<ThingSmartCallProtocol>)call;

Cancel call

The app cancels an outgoing call before the device answers.

- (void)interface:(id<ThingSmartCallInterface>)interface onCancel:(id<ThingSmartCallProtocol>)call;

End call

The app hangs up an outgoing or incoming call.

- (void)interface:(id<ThingSmartCallInterface>)interface onHangUp:(id<ThingSmartCallProtocol>)call;

Decline call

The app declines an incoming call from the device.

- (void)interface:(id<ThingSmartCallInterface>)interface onReject:(id<ThingSmartCallProtocol>)call;

Answer call

The app answers an incoming call from the device.

- (void)interface:(id<ThingSmartCallInterface>)interface onAccept:(id<ThingSmartCallProtocol>)call;

P2P connection

The app is connected to the device through P2P.

- (void)interface:(id<ThingSmartCallInterface>)interface onConnected:(id<ThingSmartCallProtocol>)call;

Call drop

A call is disconnected due to exceptions like the app moving to the background or network issues.

- (void)interface:(id<ThingSmartCallInterface>)interface onException:(id<ThingSmartCallProtocol>)call error:(nullable NSError *)error;

Example

For more information, see Demo.