Avaya Client SDK

< Back to Package Overview

Initializing the SDK

This article discusses how to initialize, reinitialize, and shutdown the Avaya Client SDK Communications Package for iOS within your application.

Creating and configuring a Client

The central class of the Avaya Client SDK is CSClient. Each application using the Client SDK will have its own instance of CSClient and will maintain a reference to this object in order to create a CSUser and access features within the SDK.

Configuring a Client

As part of the process to create your client instance, you must create a CSClientConfiguration object that defines your application. There are two ways to create CSClientConfiguration object.

  1. By initializing the configuration details with the attribute Data directory.

    NSString *dataDirectory = 
        [NSString stringWithFormat:@"%@/%@", NSHomeDirectory(), @"TestApplication"];
    
    CSClientConfiguration *clientConfiguration = [[CSClientConfiguration alloc]
    initWithDataDirectory: dataDirectory ];
    

    The Client SDK uses the default values for the Product Name, Product Version, Platform, Build number, OS version and Vendor for constructing the User-Agent string. The default values are set based on the Application's build properties and platform.

    You can get the User-Agent name generated by the Client SDK by using the API userAgentName

    NSString *userAgentName = clientConfiguration.userAgentName;
    

    You can always override the default values for all the configuration details.

    clientConfiguration.productName = "TestApplication";
    
  2. By initializing the configuration details with the attributes like Data directory, Product name, Product version, Platform, OS version, Build number and Vendor name. The attributes you define within ClientConfiguration will be used to identify your application in the network.

    NSString *dataDirectory = 
        NSString stringWithFormat:@"%@/%@", NSHomeDirectory(), @"TestApplication"];
    
    NSString *platformVersion =
        [[NSProcessInfo processInfo] operatingSystemVersionString];
    
    CSClientConfiguration *clientConfiguration = [[CSClientConfiguration alloc]
        initWithDataDirectory: dataDirectory
                productName: @"TestApplication"
                productVersion: @"1"
                platform: @"iOS"
                osVersion: platformVersion
                buildNumber: @"1"
                vendorName: @"Avaya"];
    

Also, you can always set the custom User-Agent string by using userAgentName. Note that, setting the custom User-Agent might not enable all the server capabilities as the format of the User-Agent string is server-specific.

clientConfiguration.userAgentName = "TestApplication";

Note:

  • Once the User-Agent string is set explicitly using API userAgentName, changing any of the attributes of CSClientConfiguration instance like ProductName will not be reflected on the User-Agent string.
  • Since there are few server-specific requirements for the format of the User-Agent string, we recommend you to use the first API and let the Client SDK construct the User-Agent string by using the default values to enable complete server capabilities.

Set a user agent unique instance id defined in RFC 5626. Generate unique value once (e.g. UUID [RFC4122]) and then save this in persistent storage for all future use. You can use [[uiDevice identifierForVendor]UUIDString] instead of this.

NSString* userAgentInstanceId;
if ([persistentStorage.userAgentInstanceId length] > 0) {
    userAgentInstanceId = persistentStorage.userAgentInstanceId;
}
else {
    CFUUIDRef uuid = CFUUIDCreate(NULL);
    userAgentInstanceId = 
        (__bridge_transfer NSString *)CFUUIDCreateString(NULL, uuid);
    CFRelease(uuid);

    persistentStorage.userAgentInstanceId = userAgentInstanceId;
}
clientConfiguration.userAgentInstanceId = userAgentInstanceId;

Next, create a <CSClientDelegate> instance. This protocol will be used to handle events that occur during the lifecycle of your client, such as the shutdown event. Your implementation of the CSClientConfiguration and <CSClientDelegate> are then used to construct the CSClient object that will be used by your application.

@interface ApplicationClientDelegate() 
...
@end

@implementation ApplicationClientDelegate

    - (void)client:(CSClient *)client didCreateUser:(CSUser *)user {
    {
        // Called to report the specified user has 
        // been created successfully
        // Add code here to handle user created
    }

    - (void)client:(CSClient *)client didRemoveUser:(CSUser *)user {
    {
        // Called to report the specified user has 
        // been removed
        // Add code here to handle user removed
    }

    - (void)clientDidShutdown:(CSClient *)client {
    {
        // Called to report Client shutdown has been completed
        // Add code here to handle shutdown of the Client
    }

    ...

@end

Creation of the Client object

After you instantiate and set up required configuration object and <CSClientDelegate>, you are now ready to create the CSClient object. Instantiate the CSClient object by calling its initWithConfiguration: delegate: delegateQueue: method.

ApplicationClientDelegate* applicationClientDelegate =
    [[ApplicationClientDelegate alloc] init];
CSClient* client = [[CSClient alloc] 
    initWithConfiguration: clientConfiguration
    delegate: applicationClientDelegate
    delegateQueue: dispatch_get_main_queue()];

By default, CSClient operates an event loop on the main thread. To handle callbacks from the client on the application thread (typically the UI thread), the client delivers callbacks via a main dispatch queue. If you must change this behavior, you can specify your own dispatch queue using the CSClient constructor.

Creating and configuring a User

A CSUser object defines all of the capabilities available to the end user of your application. Creating a CSUser is very similar to creating a CSClient.

Configuring a User

First, create a CSUserConfiguration object:

CSUserConfiguration* userConfiguration = [[CSUserConfiguration alloc] init];

You can use the localCallLogFilePath property of the CSUserConfiguration object to specify path to the call log file.

    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSArray *basePathsArray = [fileManager URLsForDirectory:NSDocumentDirectory 
                                                  inDomains:NSUserDomainMask];
    NSURL *callLogFilePath = [basePathsArray[0] URLByAppendingPathComponent:
        @"CallLog.xml"];    
    userConfiguration.localCallLogFilePath = callLogFilePath;

The CSUserConfiguration object will be used to define the services that will be available to end users of your application. Each service is configured individually; its configuration is stored in a dedicated object, referenced from the CSUserConfiguration object.

Service configuration starts with obtaining a reference to the desired service configuration from CSUserConfiguration. Once you have completed the configuration for the service, or re-configuration of the service, save the configuration back to the CSUserConfiguration object.

Note: More information on service configuration can be found in the article Configuring the SDK.

Example: Configuring the Call Service for SIP

Start by obtaining any existing service configuration (memory for CSSIPUserConfiguration is allocated during creating CSUser):

CSSIPUserConfiguration* sipUserConfiguration = 
    userConfiguration.SIPUserConfiguration;

Enable the service:

sipUserConfiguration.enabled = YES;

Configure the SIP parameters supplied by your administrator:

sipUserConfiguration.userId = @""; // Provided by your administrator
sipUserConfiguration.domain = @""; // Provided by your administrator

Next, you must configure the connection parameters for the SIP server. This will take the form of one or more server configurations represented as CSSignalingServer objects encapsulated in a single CSConnectionPolicy object:

CSSignalingServer* signalingServer = [CSSignalingServer 
    serverWithTransportType: CSTransportTypeTLS 
    // Provided by your administrator
                   hostName: "" 
                       port:                      
    // Allow the Client SDK to manage failback
             failbackPolicy: CSFailbackPolicyAutomatic]; 

sipUserConfiguration.connectionPolicy = [CSConnectionPolicy
    connectionPolicyWithSignalingServer: signalingServer];

To successfully register to the SIP server a password corresponding to the username will be required. The password required for the SIP service is not defined as part of the service configuration. Passwords are requested by and communicated to the Client SDK using the <CSCredentialProvider> protocol:

sipUserConfiguration.credentialProvider = self;

And finally save your configuration back to your user object:

userConfiguration.SIPUserConfiguration = sipUserConfiguration;

Note: More information on how to manage passwords using the <CSCredentialProvider> can be found in the article Working with Credentials.

Creation of the User object

After you instantiate and set up any required configuration objects, you are now ready to create the CSUser.

Creating a user is an asynchronous operation. The result of this operation is delivered through completion handler void (^)(CSUser *user, NSError *error). The example below shows a pattern you will see used commonly throughout the Client SDK. Many SDK functions result in network activity and these operations are performed asynchronously, with the results being provided via a completion handler on the main thread (or the thread associated with the dispatch queue optionally specified during CSClient creation).

void (^completionHandler)(CSUser *user, NSError *error) = 
    ^(CSUser *user, NSError *error) {
        if (user) {
            self.mUser = user;
            [self addDelegates: user];
            [user start];
        }

        if (error) {
            NSLog(@"Failed to create user.\nError: %ld - %@",
                (long)error.code, error.localizedDescription);
        }
    };

[client createUserWithConfiguration: userConfiguration
                  completionHandler: completionHandler];

If the user is successfully created, the completion handler is called with new user object. At this point you can register listeners for any Client SDK services that you wish to observe events for, and then call the start method of your CSUser to start all services.

The start method triggers the network activity required to register with any services configured. Once a successful connection has been established to the infrastructure, API's dependent on infrastructure services will be accessible through the CSUser service.

If the user is not created, the completion handler is called with error object.

Reinitializing a Service

To reinitialize a CSUser object to apply new configuration settings you must perform the following steps:

To remove a CSUser from the CSClient use the removeUser:gracefulRemove: method. The removeUser:gracefulRemove: method supports both graceful and ungraceful invocation.

[client removeUser: user gracefulRemove: YES];

For more information on the differences between graceful and ungraceful invocation please refer to the section Shutdown the Client.

To confirm that the user has been removed the calling application will receive notification via the client:didRemoveUser: callback on the <CSClientDelegate> implementation object.

Applying the new configuration and starting the user follows the same process as described in the section Creating a User.

Note: Removing the CSUser will stop all services configured for the CSUser. Support to reconfigure services individually is a feature planned for a future release.

Shutdown the Client

The CSClient shutdown: method can be called in one of two ways:

  • Graceful Shutdown
  • Ungraceful Shutdown

When a graceful shutdown is invoked:

[client shutdown: YES];

Client SDK attempts to unregister with each infrastructure service.

Client SDK waits until confirmation is provided by each infrastructure service. Once confirmation from all infrastructure services is received, the shutdown and cleanup of internal resources will be done. The graceful shutdown operation is dependent on a network response from one or more infrastructure services. When errors occur this process may take as long as the network timeout on each infrastructure connection to complete.

When an ungraceful shutdown is invoked:

[client shutdown: NO];

All network connections are immediately terminated, CSUser objects controlled by the CSClient object are removed, and internal resources are immediately released.

When shutdown is complete and all resources are released clientDidShutdown: is called on the <CSClientDelegate> to notify the calling application that the process has completed.