Avaya Client SDK

< Back to Package Overview

Answering a Video Call

Using the Avaya Client SDK, you can easily integrate the ability for users of your application to make and receive audio or video calls.

To receive and answer an incoming video call, you must complete the following activities.

  • Implement the call service listener to monitor for call service events
  • Detect the presence of offered video
  • Obtain resources for answering a video call
  • Accept the incoming video call
  • Activate video resources
  • End the call

Implement the call service listener

In order to get notifications for any incoming calls, your application can define an object that implements the CallServiceListener interface and add this listener object to the CallService object to receive call service notifications.

class AppCallServiceHandler implements CallServiceListener
{
@Override
public void onIncomingCall(CallService callService, Call call) {
    // Called to report that there is an incoming call. 
    // Add code here to handle this incoming call (eg, update UI to alert
    // user, provide options for handling the call, ... etc).
}

@Override
public void onCallRemoved(CallService callService, Call call) {
    // Called to report that the call has been removed before answer
    // Add code here to handle the removed call (eg, update UI to remove
    // the call... etc).
}
...
};

You can create a call service handler and add it as a listener to the call service.

AppCallServiceHandler callServiceHandler = new AppCallServiceHandler();
CallService callService = mUser.getCallService();
callService.addListener(callServiceHandler);

When there is an incoming call, the CallServiceListener.onIncomingCallReceived() function is called with a Call object in the arguments. After receiving the Call, you can implement a CallListener interface and add the listerner to the Call object to monitor call progress events.

class CallHandler implements CallListener
{
    @Override
    public void onCallVideoChannelsUpdated(Call call,  
                                            List videoChannels) {
        // Called to report that a video channels updated 
        // Add code here to handle video channels update
    }
    ...
};

You can instantiate a call handler (CallHandler) and add it as a listener to the call.

CallHandler callHandler = new CallHandler();
call.addListener(callServiceHandler);

Detect the presence of offered video

Any incoming call may include video, and the App needs to use the IncomingVideoStatus API on the Call to determine the call's offer status. The API returns one of three values which the application must handle

  • SUPPORTED. The calling party included video when making the call. If desired, the application can answer with bi-directional or reception-only video.
  • INDEFINITE. The calling party may or may not have included video when making the call. Due to requirements of some calling endpoints, it's highly recommended that the application answer with reception-only video. If this is not done, some endpoints will never be able to establish a video session with the application.
  • OFF. The calling party did not include video when making the call. The application should not answer the call with video.
IncomingVideoStatus incomingVideoStatus = call.getIncomingVideoStatus();

Obtain resources for answering a video call

The application needs to obtain one or two resources when answering a call with video. If the application wishes to transmit video, it should find a video camera. Camera availability is verified through the VideoCaptureController class. This class manages most aspects of camera operation, including verification of available hardware. Regardless of camera need, a video interface is required.

if (video-transmission-desired) {

VideoCaptureController() videoCaptureController = new VideoCaptureController();

    // Assign a default camera; this could be user selectable according 
    // to your implementation
    callHandler.mCameraForCall = VideoCamera.Front;

    if (!videoCaptureController.hasVideoCamera(callHandler.mCameraForCall)) {
    // No camera. Reset to null.
    callHandler.mCurrentCamera = null;

    // The app will have to recover somehow. In this case, assume that video
    // reception is desired instead.
    }

    VideoInterface videoInterface = mUser.getMediaEngine().getVideoInterface();
}

Accept the incoming video call

The application accepts a video call by setting video mode prior to invoking call.accept().


// Set the desired direction on the video channel
if (video-transmission-desired && callHandler.mCurrentCamera != null) {
call.setVideoMode(VideoMode.SEND_RECEIVE);
}
else {
call.setVideoMode(VideoMode.RECEIVE_ONLY);
}

// Answer the call. Note that there's no guarantee that it will 
// start with the expected video direction (or any) video.

call.accept();

Activate video resources

One video-related callback must be implemented on the Call's CallListener to allow your application to transmit or receive video with directions matching the one negotiated by the remote endpoint. Although bi-directional or receive-only video is requested by the local application, the remote's video direction may not be compatible.

public void onCallVideoChannelsUpdated(Call call,  List list) {

// adjust render surface and camera usage to match the final video direction. 
// This is done by examining the final video direction that was returned from
// the remote address

if (list.size() > 0) {
    VideoChannel channel = list.get(0);
    int channelId = channel.getChannelId();
    MediaDirection mediaDirection = channel.getNegotiatedDirection();

    if (mediaDirection == MediaDirection.SEND_RECEIVE || 
        mediaDirection == MediaDirection.SEND_ONLY) {
        // These two video directions imply that video transmission
        // must be started locally.
        // As such, create a surface to render local video,
        // attach the surface to the camera, 
        // attach the camera to the video channel,
        // and activate the camera.

        // Start video transmission
        final VideoSink videoSink;
        videoSink = videoInterface.getLocalVideoSink(channelId);
        videoCapControl.getVideoSource().setVideoSink(videoSink);
        videoCapControl.setLocalVideoLayer(localVideoLayer);

        if (callHandler.mCameraForCall != null) {
            videoCapControl.useVideoCamera(callHandler.mCameraForCall, null);
        }
    }
    if (mediaDirection == MediaDirection.SEND_RECEIVE || 
        mediaDirection == MediaDirection.RECEIVE_ONLY) {
        // These two video directions imply that video reception
        // must be started locally.
        // Create a surface to render remote video
        // and attach the surface to the video channel.
        // Start video rendering
        if (videoInterface.getRemoteVideoSource(channelId) != null) {
            remoteVideoLayer = new VideoLayerRemote();
            videoInterface.getRemoteVideoSource(channelId)
            .setVideoSink(remoteVideoLayer);
        }
    }  
    // Any other video direction implies video is not available
    // If the call has video before this update it should be stopped.
}

End the call

To terminate the call from the application, you can use the end() function on the call object.

call.end();

The onCallEnded callback event is sent to the call listener when the call has been ended. Use this event to update the UI of your application. Ending the call will deallocate the video channel and release the video camera automatically, but any render surface allocated by the application will need to be released by it. Again, see SdkSampleApp for the steps.