Title: Cisco Jabber Guest for iOS SDK Developer Guide
Version: v11.2.3
Publisher: DevNet, Cisco's Developer Program
Publisher Address: Cisco Systems, Inc., 150 W Tasman Dr, San Jose, CA 95134, USA
Published: Jan 2020
Introduction
Overview
Jabber Guest for iOS allows external (public) users to call internal enterprise endpoints and engage in two-way video communications over the public Internet. When configured correctly, the Jabber Guest Web Server allows guests to establish video calls that reach inside the firewall to contact support, experts, and other services from their iOS device. This functionality is enabled through the Jabber Guest Software Development Kit (SDK) for iOS. The Jabber Guest SDK for iOS coordinates and simplifies the implementation, use, and quality of two-way video calls from within your application. This document covers the software and resources a developer would need to use the Jabber Guest SDK to integrate into their iOS mobile applications.
Audience
This document is intended for developers or information technology professionals using or familiar with Cisco telecommunications equipment who want to integrate with their Jabber Guest Web Server by using a mobile device. The document assumes the reader is comfortable with Objective-C for iOS and common iOS design patterns.
Terminology
This section covers terminology in use within the SDK and components of the SDK itself.
Remote View
A Remote View is a view that represents the called party’s video during an active call.
Self View
A Self View is a view that represents the local user’s transmitted video during an active call.
URI
A URI is a Uniform Resource Identifier that is used to identify and potentially pass arguments of the targeted called party.
Components
For full descriptions and method or properties definitions, refer to the API Reference documentation for more information.
CJGuestCall
The CJGuestCall class is a singleton that consolidates the lifecycle and interaction with a Jabber Guest call. It represents all of the capabilities and state of the active or pending call. For example, muting and unmuting video is controlled through this class. Getting information such as whether or not video is active or what state the call is in can be accessed through this state through registered notifications.
CJGuestCallBarView
This view has on-screen controls for the user to modify the state of an active call. These controls include things like Mute, Stop, Keypad, and End Call.
CJGuestCallKeypadView
A DTMF keypad that can send digits to the targeted called party.
CJGuestCallSelfView
This view encapsulates the Self View, including the ability to switch cameras and control orientation.
CJGuestCallViewController
The CJGuestCallViewController class is a packaged collection of visual components working together to give developers a quick and easy way to integrate common Jabber Guest call functionality into their application. It includes a Remote View, Self View, and a Call Bar in a common configuration.
Strategies for Using Jabber Guest Framework
The framework is designed with flexibility in mind. The framework can be split into three levels.
- The high-level componet is CJGuestCallViewController, which is a view controller built from the mid-level views. It is intended to be used for demo purposes, and is not highly customizable.
- The mid-level components are several views that can be used together to integrate Jabber Guest quickly into your app, and customize it for your needs. These components include the CJGuestCallBarView, CJGuestCallKeypadView, and CJGuestCallSelfView.
- At the lowest level is CJGuestCall, which gives you direct access to the Jabber Guest call object.
Apps should make use of the mid-level views and CJGuestCall to integrate Jabber Guest.
Requirements
This section describes the requirements for implementing a Jabber Guest for iOS solution.
Requirement | Details |
---|---|
Jabber Guest Server | The version of SDK to be used must match the server version that will be servicing clients. |
Xcode | The minimum Xcode requirement is Xcode 7.0. |
iOS | The minimum iOS requirement is iOS 8. |
Architectures | armv7 and arm64 are supported. The Xcode iOS simulator (i386) is not supported. |
Installation
This section describes some basic installation procedures.
Downloading the SDK
Current versions of the SDK are available at http://jabberdeveloper.com. You will need to login with your Cisco credentials to access and download the SDK.
Unpacking the SDK
The Jabber Guest SDK for iOS is distributed as a zip file. The sdk folder contains the framework for iOS named JabberGuest.framework.
Including the SDK in Your Project
- Drag the JabberGuest.framework bundle to the Frameworks group of your project.
- When prompted, select Copy items into destination’s group folder.
- Click Finish.
- Right-click JabberGuest.framework in your project, and select Show in Finder.
- Open the Resources folder and drag the JabberGuest.bundle to the Frameworks folder.
- When prompted ensure Copy items into destination’s group folder is NOT selected.
- Click Finish.
- Open the Supporting Files folder and rename main.m to main.mm (add another m to change it to a Obj-C++ source file).
- Select your project from the Project Navigator, and choose your application’s project.
- Open the Build Settings tab.
- Change the filter in the Build Settings bar from Basic to All.
- In the Build Active Architecture Only section, select No.
- In the Valid Architectures section, enter armv7 arm64 if your app is an universal binary, otherwise choose either armv7 or arm64.
- In the Other Linker Flags section, add -ObjC.
- Must have the C++ Standard Library build setting set to libc++ (LLVM C++ standard library with C++11 support).
- In the Enable Bitcode section, choose the No.
- Select your application’s target.
- Open the Build Phases tab, and in the Link Binary With Libraries section, add the following frameworks and dynamic libraries:
- AvFoundation.framework
- VideoToolbox.framework
- AudioToolbox.framework
- CoreMedia.framework
- MediaPlayer.framework
- QuartzCore.framework
- Security.framework
- CallKit.framework
- SystemConfiguraiton.framework
- libiconv.dylib
- libresolv.dylib
- To build a Swift based app, add a bridging header. Create a new header file and name it <ProjectName>-Bridging-Header.h. Bridging header is used to import the header files. Import the header file for Jabber Guest - #import <JabberGuest/JabberGuest.h>
- Under Target in Build setttings, in the Swift Compiler - Code Generation -> Objective-C Bridging header section add the bridging header
Updating your Application’s plist File
The plist file must be updated to note the application will continue to play audio in the background.
- Open your application’s Info.plist file, which is usually found within the Supporting Files folder of your project.
- Right-click in the editor and select Add Row.
- From the drop-down list, select Required background modes.
- Open Required background modes, open Item 0, and from the drop-down list, select App plays audio or streams audio/video using AirPlay.
If you would like to use the Cisco custom fonts in your app, you will need to update your application’s Info.plist file and add the following custom fonts.
- Open your application’s Info.plist, which is usually found within the Supporting Files folder of your project.
- Right-click in the editor and select Add Row.
- From the drop down-list , select Fonts provided by the application.
- Open Fonts provided by the application, add rows within this section for each of the fonts you would like to add.
- Open Item 0, add JabberGuest.bundle/CiscoSansTTLight.ttf
- Open Item 1, add JabberGuest.bundle/CiscoSansLight.otf
- Open Item 2, add JabberGuest.bundle/CiscoSansTTRegular.ttf
- Open Item 3, add JabberGuest.bundle/CiscoSansExtraLight.otf
- Open Item 4, add JabberGuest.bundle/CiscoSansTTBold.ttf
Upgrading the SDK in Your Project
Upgrading the framework in your existing app consists of removing the old framework and copying over the new one.
First, remove the old framework from your app. You must delete the bundles in a specific order, otherwise Xcode will not be able to move the framework to the trash.
- Select the JabberGuest.bundle from the Frameworks group in your project.
- Delete it and make sure to click Move To Trash in the dialog box.
- Select the JabberGuest.framework from the Frameworks group in your project.
- Delete it and make sure to click Move To Trash in the dialog box.
- Verify these two bundles no longer appear in the Frameworks group in your project.
Second, add the new framework to your app. Refer to the first six steps in Including the SDK in Your Project. You typically do not need to reconfigure the build settings of your project. The release notes will mention if a change is needed. After adding the latest framework, do a clean and build.
URL Schemes
The Jabber Guest Demo app is configured to handle the Jabber Guest scheme. You can have your app handle your own custom URL scheme. To get a basic understanding of how to implement a customer URL scheme, read Implementing Custom URL Schemes.
Opening a Jabber Guest URL
The code shown in the right hand panel can be placed in an app to open a Jabber Guest URL that is using the default scheme. The Jabber Guest Demo app can handle this URL. If you have your own customer URL scheme and app to handle it, you can use your own scheme instead.
The method assumes that a serverName and URI property holding the appropiate values are available.
- (void)launchJabberGuest:(id)sender {
NSString * serverName = self.serverName;
NSString * encodedURI = [self.uri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL * url = [NSURL URLWithString:[@"jabberguest://" stringByAppendingFormat:@"%@?uri=%@", serverName, encodedURI]];
UIApplication * thisApp = [UIApplication sharedApplication];
if ([thisApp canOpenURL:url]) {
[thisApp openURL:url];
} else {
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:@"No JabberGuest App Found"
message:@"The JabberGuest App is not installed."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alertView show];
}
}
Implementing a Custom URL Scheme
To have your app handle the custom URL, you need modify your applications Info.plist and implement the openURL delegate.
Adding Your Scheme to Info.plist
- Open your apps Info.plist file.
- Right-click in the editor and select Add Row.
- From the drop-down list select URL types.
- Open URL types, open Item 0, and add a unique name for your URL scheme to the value of URL Identifier. Example: com.yourcompany.JabberGuest
- Click the + button next to the URL Identifier key.
- From the drop-down list select URL Schemes.
- Open URL Schemes, open Item 0, and add the name of your URL scheme. Example: yourcompany-JabberGuest or yourcompany.JabberGuest
- Choose a unique URL scheme name. Apple documentation states the following:
If more than one third-party app registers to handle the same URL scheme, there is currently no process for determining which app will be given that scheme.
The openURL delegate
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
CJGuestCallViewController * jabberGuest = [[CJGuestCallViewController alloc] init];
[jabberGuest configureFromURL:url];
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:jabberGuest];
[self.window setRootViewController:nc];
return YES;
}
If you are using the high-level CJGuestCallViewController object, in your application’s delegate implement the code in the right hand panel. The method configureFromURL: will pull the host name and the URI to call from the URL.
- (void)configureFromURL:(NSURL *)url
{
self.serverName = [url host];
NSDictionary *query = [JabberGuest parseQueryString:[url query]];
self.toURI = [query objectForKey:@"uri"];
}
If you want to control the handling of the URL in your code, or you are not using the CJGuestCallViewController, the configureFromURL: method is implemented in the CJGuestCallViewController as shown in the right hand panel.
Views
The Jabber Guest SDK for iOS comes with several custom views that can be used to implement the most common Jabber Guest functionality.
The Remote View
The remote view is your window to the incoming video stream. You only need to point CJGuestCall to an UIImageView to use as the remote view, and the incoming video buffers will be displayed on that UIImageView. If you would like the video to fit inside the remote view and retain its aspect ratio, then set the content mode of the UIImageView to UIViewContentModeScaleAspectFit. If you use any other content mode with the UIImageView (a common second choice is UIViewContentModeScaleAspectFill), then you will likely want to call setClipsToBounds:YES on the UIImageView to have the video clipped. Otherwise it can extend outside its frame’s bounds and draw over other parts of your interface.
UIImageView * remoteView = [[UIImageView alloc] initWithFrame:CGRectMake((self.view.frame.size.width - 720) / 2.0,
0.0,
720,
480)];
[remoteView setContentMode:UIViewContentModeScaleAspectFit];
[self.view addSubview:remoteView];
[[CJGuestCall sharedInstance] setRemoteView:remoteView];
The code in the right hand panel sets the remote view to an UIImageView that is 720 points wide by 480 points high and centered at the top of the current frame.
CJGuestCall * call = [CJGuestCall sharedInstance];
[call setServerName:@"your.jabber.guest.server"];
[call setToURI:@"your.uri"];
[call startCall: ^(BOOL isActivated) {
if (isActivated)
; // call started
else
; // user chose not to activate video license, call did not start
}];
When the call is connected, incoming video will be displayed on the remoteView UIImageView. To start the call, place the below code in a button, or other convenient spot in your app.
The Self View
The self view is your window to the outgoing video stream. You have two choices for how to present the self view. You can either use the CJGuestCallSelfView, which wraps up camera switching functionality along with displaying the outgoing video, or you can set the property selfView on CJGuestCall, which uses the provided UIImageView to mirror outgoing video buffers.
CJGuestCallSelfView
The code in the right hand panel creates an instance of CJGuestCallSelfView that is 240 points wide by 360 points high and centered at the top of the current frame. CJGuestCallSelfView, by default, uses a content mode of UIViewContentModeScaleAspectFill and does clip to bounds.
CJGuestCallSelfView * guestCallSelfView = [[CJGuestCallSelfView alloc] initWithFrame:CGRectMake((self.view.frame.size.width - 240) / 2.0,
remoteView.frame.origin.y + remoteView.frame.size.height + 20.0,
240,
360)];
[self.view addSubview:guestCallSelfView];
CJGuestCall selfView
You only need to point CJGuestCall to an UIImageView to use as the self view. If you would like the video to fit inside the self view and retain its aspect ratio, then set the content mode of the UIImageView to UIViewContentModeScaleAspectFit. If you use any other content mode with the UIImageView (a common second choice is UIViewContentModeScaleAspectFill), then you will likely want to call setClipsToBounds:YES on the UIImageView to have the video clipped. Otherwise it can extend outside its frame’s bounds and draw over other parts of your interface.
UIImageView * selfView = [[UIImageView alloc] initWithFrame:CGRectMake((self.view.frame.size.width - 240) / 2.0,
0.0,
240,
360)];
[selfView setContentMode:UIViewContentModeScaleAspectFit];
[self.view addSubview:selfView];
[[CJGuestCall sharedInstance] setSelfView:selfView];
The code in the right hand panel sets the self view to an UIImageView that is 240 points wide by 360 points high and centered at the top of the current frame.
[[CJGuestCall sharedInstance] startSelfView:^(BOOL isActivated) {
if (isActivated)
; // self view started
else
; // user chose not to activate video license, self view did not start
}];
To start the self view, call startSelfView on the CJGuestCall instance as shown in the right hand panel.
Aspect Ratio
When you create the frame for your self view, make sure to use an aspect ratio that correlates to the camera on your device. We find 3:4 offers a good self view.
The Call Bar View
The call bar view is a bar of buttons that allows a user of your app to manipulate the Jabber Guest call once it starts. It consists of four buttons:
- Mute mutes the audio on the first touch. Touching it a second time will unmute the audio.
- Video turns off the video on the first touch. Touching it a second time will turn on the video.
- Keypad displays a DTMF keypad. Touching it a second time will hide the keypad.
- Hook starts or ends the call.
The call bar view is encapsulated in CJGuestCallBarView. The size of the call bar is fixed by the number of buttons, one to four, that are shown on the bar. To determine the size of any given call bar, use the button size constants CJGuestCallBarButtonWidth and CJGuestCallBarButtonHeight. The width of the call bar will be the number of buttons shown multiplied by CJGuestCallBarButtonWidth. The height of the call bar is always equal to CJGuestCallBarButtonHeight, since the call bar is always a single row of buttons.
CJGuestCallBarView * callBar = [[CJGuestCallBarView alloc] initWithOrigin:CGPointMake((self.view.frame.size.width - (CJGuestCallBarButtonWidth * 4)) / 2.0,
self.view.frame.size.height - CJGuestCallBarButtonHeight)];
callBar.delegate = self;
[self.view addSubview:callBar];
The code in the right hand panel creates an instance of the call bar centered at the bottom of the current frame. The call bar is, by default, created with all four buttons showing.
@interface YourViewController () <CJGuestCallBarViewDelegate>
- (void)callBarView:(CJGuestCallBarView *)callBarView clickedButton:(CJGuestCallBarButtonType)buttonType
{
NSLog(@"Call Bar View : %@ button was clicked", [CJGuestCallBarView stringFromGuestCallBarButton:buttonType]);
}
To have a view controller be notified when a button is touched on the call control view, you will need to implement the CJGuestCallControlViewDelegate protocol. Refer to the right hand panel.
The callControlView:clickedButtonAtIndex: method will be called when a button is touched on the call control view. The index is enumerated with CJGuestCallControlButtonType, which you can use to determine which button was touched. To get a string representation of the button that was touched, use stringFromGuestCallControlButton:. The code above uses this method to log the button that was touched in the call control view.
The Keypad View
The keypad view is a DTMF dialer that allows a user to dial DTMF digits. If you are using CJGuestCallBarView, then the Keypad button is already wired to use the keypad view and you don’t have to worry about it. It will just work. If, on the other hand, you are writing your own custom call bar or need a keypad for any reason, then you can use this keypad view directly.
CJGuestCallKeypadView * keypadView = [[CJGuestCallKeypadView alloc] initWithOrigin:CGPointMake(0,0)];
[self.view addSubview:keypadView];
The keypad view is encapsulated in CJGuestCallKeypadView. The code in the right hand panel creates an instance of the keypad view with an origin point at the top left corner of the screen.
Once an instance is created it is ready to dial digits after the call is connected. No other code is necessary to make it work.
Transitions
Handling transitions correctly with your app during a live video and/or audio call is critical for a pleasant user experience. This section details how to handle these transitions.
Audio Background Mode
The UIBackgroundModes key needs to be configured to provide audio in your app’s plist file. These details are covered in Updating your Application’s plist File.
Handling Transitions
In your app’s delegate, implement the code in the right hand panel. This will allow audio to continue to transmit and receive while your app is in the background. It will also mute the video transmitting while your app is in the background and unmute the video when your app goes back to the foreground.
- (void)applicationWillTerminate:(UIApplication *)application
{
[[CJGuestCall sharedInstance] endCall];
}
Add the code in the right hand panel to your app’s delegate to handle your app terminating.
CJGuestCallViewController
If you are using the high-level CJGuestCallViewController piece of the SDK, these transition details are wrapped up into helper methods that you can call directly on the CJGuestCallViewController object. These are here for your convenience, using them allows you to have a working demo in a matter of minutes.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[jabberGuest enterBackground];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[jabberGuest enterForeground];
}
- (void)applicationWillTerminate:(UIApplication *)application
{
[jabberGuest terminate];
}
If you want to use these helper methods, implement the code in the right hand panel in your app’s delegate. This code assumes you have an instance of the CJGuestCallViewController object named jabberGuest available.
Screen Share
Remote Screen Share
Jabber Guest iOS SDK version 10.6 can receive remote screen share.
CJGuestCallViewController
If you are using the high-level CJGuestCallViewController object, then your app can view the remote screen share without any additional code changes.
myCJGuestCallViewController.confirmBeforeHangupDuringScreenShare = YES;
If your app wants to prompt the user for confirmation before ending a call while screen share is active, add the line of code in the right hand panel during initialization.
Using CJGuest Call Object
If you are using CJGuest call object, you can register for notifications to this call object.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleShareActiveStateChanged:) name:CJGuestCallRemotePresoVideoActiveNotification object:nil];
To receive the notification when CJGuestCall:remotePresoActive changes, add an observer using the method you created to handle the notification as the selector, for the notification CJGuestCallRemotePresoVideoActiveNotification. Refer to the right hand panel.
- (void)handleShareActiveStateChanged:(NSNotification *)notification
{
CJGuestCall *call = [ notification object];
if(call.remotePresoActive) {
NSLog(@"screen share is active”);
} else {
NSLog(@"screen share is no longer active”);
}
}
Create a method, shown in the right hand panel, to handle the notification.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleShareStarted:) name:CJGuestCallRemotePresoVideoStartedNotification object:nil];
To receive the notification when the first frame of the screen share has arrived, add an observer using the method you created to handle the notification as the selector, for the notification CJGuestCallRemotePresoVideoStartedNotification, as shown in the right hand panel.
- (void)handleShareStartedStateChanged:(NSNotification *)notification
{
NSLog(@"first frame of screen share has arrived");
}
Create a method to handle this notification, as shown in the right hand panel.
Certificates
By default, CJGuestCall uses a UIAlertView to prompt users of your app if they wish to continue placing a call when the certificate provided is invalid. This behavior can be overridden by implementing your own invalid certificate handling.
If you are using the high-level CJGuestCallViewController object, then you can not override the default invalid certificate behavior. You can simply skip this section.
CJGuestInvalidCertDelegate
This delegate allows you to control your app’s behavior when encountering an invalid certificate.
To use this delegate to overide the default invalid certificate behavior, first you need to implement onInvalidCert:certSubjectCN:referenceID:invalidReason:subjectCertificateData:intermediateCACertificateData:invalidCertCallback: to accept or reject the certificate. From inside this method, to accept the certificate call accept on the CJGuestInvalidCertCallback argument. To reject the certificate call reject on the CJGuestInvalidCertCallback argument. Second, set the invalidCertDelegate property on CJGuestCall to your implementation.
@interface YourClass () <CJGuestCallBarViewDelegate>
- (id)init
{
self = [super init];
if (self) {
CJGuestCall * call = [CJGuestCall sharedInstance];
...
[call setInvalidCertDelegate:self];
...
}
return self;
}
-(void) onInvalidCert:(NSString*)certFingerprint
certSubjectCN:(NSString*)certSubjectCN
referenceID:(NSString*)referenceID
invalidReason:(NSArray*)invalidReason
subjectCertificateData:(NSString*)subjectCertificateData
intermediateCACertificateData:(NSArray*)intermediateCACertificateData
invalidCertCallback:(id)invalidCertCallback
{
[invalidCertCallback accept];
}
An implementation that accepts all invalid certificates is shown in the right hand panel.
To reject all invalid certificates you would call reject instead, [invalidCertCallback reject].
Auto Call
If Guest server supports auto-call feature, the call will start automatically in exact seconds since you get the configuration from server the first time, i.e, when the program is cross-launched.
Using CJGuest Call Object
You can set a CJGuestServerConfiguraionCallDelegate to autoStartCallDelegate of CJGuest Call Object. If you do so, you will be notified through
-(void) serverConfiguraionDidRetriveWithScheduledCallInfo:(NSInteger)secs;
with auto-call timing in seconds once you get the configuration from server and be notified through
-(void) scheduledCallDidExecute;
when the auto call begins calling.
You should set the delegate before setting the serverName as it will trigger the retriving of configuration. The former delegate callback will always be called when the configuration is ready, with -1 for no auto-call configured.
If you ignore the new delegate, the auto-call feature will be disabled even the server configures it.
Video License
The Jabber Guest SDK for iOS uses H.264 AVC video, which requires activation of a license agreement by each user. When your application calls either startCall: or startSelfView:, or uses CJGuestViewController or CJGuestCallSelfView, the user will be prompted to activate the video license with a UIAlertView. From the UIAlertView, the license can be activated, viewed, or the user can choose to cancel the activation.
No local or remote video will be rendered until the user chooses to activate the video license.
[activeCall startCall: ^(BOOL isActivated) {
if ( isActivated )
; // call started
else
; // user chose not to activate video license, call did not start
} ];
startCall: and startSelfView: both take a completion block which will be executed once the user dismisses the UIAlertView by either choosing to activate the license or choosing to cancel the activation. The isActivated argument will be set to TRUE if the license was activated, and FALSE if the activation was cancelled. See the example in the right hand panel.
An example using Swift is shown in the right hand panel.
call.startCall { (isActivated:Bool) -> Void in
if(isActivated) {
} else {
}
}
Once the user activates the video license, they will not be prompted to do so again for subsequent calls. If the app is uninstalled and reinstalled, the video license will need to be reactivated.
[[CJGuestVideoLicense sharedInstance] disableActivation];
If your company has its own license agreement for H.264 AVC video from MPEG LA, and you wish to disable the display of the video license UIAlertView, place the code shown in the right hand panel in your app before calls are made.
[activeCall startCall: nil];
See the Jabber Guest SDK for iOS sample apps for examples of where to place this call. If this call is made to disable activation, then you can pass in a nil block to startCall: and startSelfView:, since the user will not be prompted to activate the license. See the example in the right hand panel.
If you disable the built-in activation capability of the Jabber SDK for iOS, you do so at your own risk and are responsible for any royalties or other fees associated with your use of the H.264 AVC video codec.
Error Handling
Error Notifications
Errors are communicated through notifications. We recommend that you read NSNotificationCenter Class Reference first.
- (void)handleError:(NSNotification *)notification
{
NSError * error = [[notification userInfo] valueForKey:CJGuestCallErrorKey];
NSLog(@"Jabber Guest error: %s", error.localizedDescription.UTF8String);
}
Create a method to handle these notifications. The notification will contain a key-value pair in the userInfo dictionary with the key CJGuestCallErrorKey. The value of this pair is the actual NSError instance. The error code is enumerated by CJGuestErrorCode. In the code shown in the right hand panel the description of the error is logged.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleError:) name:CJGuestCallErrorNotification object:nil];
To receive the notification, add an observer using the method you created to handle the notification as the selector, for the notification CJGuestCallErrorNotification. See the right hand panel.
Logs
Jabber Guest logs diagnostic information in the Application Support directory of your app. It creates a Logs sub-directory and places dated text files with the .log extension into it. If you need to programatically enable or disable logging to console and disk file, you can use +[CJGuestCall setGlobalLoggingEnabled:](introduced in Jabber Guest for iOS SDK 10.6.11)
You can retrieve these logs through the Organizer. Or, if you need to programatically retrieve the logs, you can use [CJGuestCall getAllLogs] to get an array of file names for every Jabber Guest log file on the device.
Troubleshooting
This section will cover some common problems we have seen. For details on handling errors and viewing logs, see the Error Handling section.
Linker Errors
If you see a few hundred linker errors about the standard library while trying to build your app with the framework, run through this checklist.
- At least one file in your application needs to be a .mm file. You can either change your main.m file in the Supporting Files folder to main.mm, or you can just add an empty file to your project and name it anything with the extension .mm.
- Must have a target deployment of 8.0 or above in your project settings.
- Must have the C++ Standard Library build setting set to libc++ (LLVM C++ standard library with C++11 support).
Other common errors
- If you see this error while trying to run your application [UIColor colorWithARGB:]: unrecognized selector sent to class, make sure you have the Other Linker Flags set to -ObjC
Sample Apps
If a sample app fails to build, and the error suggests it can not find the framework or some component of the framework, make sure you have followed all the instructions in the sample’s ReadMe to add the framework correctly to the sample. They are not distributed with the framework in place, in order to make the size of the framework distribution package smaller.