Skip to content

Basic Usage Guide

Bharath Balan edited this page May 7, 2024 · 6 revisions

To use the SDK, you will need Cisco Webex integration credentials. If you do not already have a Cisco Webex account, visit Webex for Developers to create your account and register your integration. Make sure you select Yes for Will this integration use a mobile SDK?. Your app will need to authenticate users via an OAuth grant flow for existing Cisco Webex users or a JSON Web Token for guest users without a Cisco Webex account.

See the iOS SDK area of the Webex for Developers site for more information about this SDK.

Example

Here are some examples of how to use the iOS SDK in your app.

  1. Create the Webex instance using Webex ID authentication (OAuth-based):

    let clientId = "$YOUR_CLIENT_ID"
    let clientSecret = "$YOUR_CLIENT_SECRET"
    let scope = "spark:all" // space separated list of scopes. spark:all is always required
    let redirectUri = "https://webexdemoapp.com/redirect"
    
    let authenticator = OAuthAuthenticator(clientId: clientId, clientSecret: clientSecret, scope: scope, redirectUri: redirectUri, emailId: "user@example.com")
    let webex = Webex(authenticator: authenticator)
    webex.enableConsoleLogger = true 
    webex.logLevel = .verbose // Highly recommended to make this end-user configurable incase you need to get detailed logs.
    
    webex.initialize { isLoggedIn in
            if isLoggedIn {
                print("User is authorized")
            } else {
                authenticator.authorize(parentViewController: self) { result in
                if result == .success {
                    print("Login successful")
                    webex.onInitialSpacesSyncCompleted = {
                        print("Spaces initial sync successful")
                    }
                } else {
                    print("Login failed")
                }
            }
            }
        }
    
     
  2. Create the Webex instance with Guest ID authentication (JWT-based):

    let authenticator = JWTAuthenticator()
    let webex = Webex(authenticator: authenticator)
    
    webex.initialize { [weak self] isLoggedIn in
            guard let self = self else { return }
            if isLoggedIn {
                print("User is authorized")
            } else {
                authenticator.authorizedWith(jwt: myJwt) { result in
                    switch result {
                    case .failure(let error):
                        print("JWT Login failed")
                    case .success(let authenticated):
                        if authenticated {
                            print("JWT Login successful")
                            webex.onInitialSpacesSyncCompleted = {
                                print("Spaces initial sync successful")
                            }
                        }
                    }
                })
            }
        }
  3. Register for the WebexAuthDelegate instance to receive all authentication-related event callbacks.

    public protocol WebexAuthDelegate: AnyObject {
    
    /// This will notify when the user is logged out and re-login is required
    ///
    /// - since: 3.11.2
    func onReLoginRequired()
    }

    Usage:

    extension AppDelegate: WebexAuthDelegate {
        func onReLoginRequired() {
            print("onReLoginRequired called")
        }   
    }
    
    webex.authDelegate = UIApplication.shared.delegate as! AppDelegate
  4. Use Webex service:

    webex.spaces.create(title: "Hello World") { result in
        switch result {
        case .success(let space):
            // ...
        case .failure(let error):
            // ...
        }
    }
    
    // ...
    
    webex.memberships.create(spaceId: spaceId, personEmail: email) { result in    
        switch result {
            case .success(let membership):
                // ...
            case .failure(let error):
                // ...
            }
        }
    }
  5. Make an outgoing call: Use the webex.phone.dialPhoneNumber() api to dial phone numbers. Incase of meeting links, meeting ids, spaces(only 1:1 spaces), meeting numbers, sip uris and email addresses, you can use the regular webex.phone.dial() api. If you use webex.phone.dialPhoneNumber()to dial anything other than phone numbers, you will get a call failure with INVALID_API_ERROR. e.g:

       webex.phone.dialPhoneNumber("+1800123456", option: MediaOption.audioVideo(local: ..., remote: ...)) { result in
       switch result {
       case .success(let call):
           call.onConnected = {
               // ...
           }
           call.onDisconnected = { reason in
               // ...
           }
       case .failure(let error):
           // failure
       }
    }
    webex.phone.dial("coworker@example.com", option: MediaOption.audioVideo(local: ..., remote: ...)) { result in
        switch result {
        case .success(let call):
            call.onConnected = {
                // ...
            }
            call.onDisconnected = { reason in
                // ...
            }
        case .failure(let error):
            // failure
        }
    }
  6. Make an outgoing CUCM call:

    webex.phone.dial("+1180012345", option: MediaOption.audioVideo(local: ..., remote: ...)) { result in
        switch result {
        case .success(let call):
            call.onConnected = {
                // ...
            }
            call.onDisconnected = { reason in
                // ...
            }
        case .failure(let error):
            // failure
        }
    }
  7. Receive a call:

    webex.phone.onIncoming = { call in
        call.answer(option: MediaOption.audioVideo(local: ..., remote: ...)) { error in
        if let error = error {
            // failure
        }
        else {
            // success
        }
    }
  8. Make an space call:

    webex.phone.dial(spaceId, option: MediaOption.audioVideo(local: ..., remote: ...)) { result in
        switch result {
        case .success(let call):
            call.onConnected = {
                // ...
            }
            call.onDisconnected = { reason in
                // ...
            }
            call.onCallMembershipChanged = { changed in
                switch changed {
                case .joined(let membership):
                    //
                case .left(let membership):
                    //
                default:
                    //
                }                
            }            
        case .failure(let error):
            // failure
        }
    }

NOTE: Creating an instant meeting by dialing into a space is deprecated. A meeting can be created using the meetings endpoint and can be joined in SDK client using the meeting link or meeting ID.

  1. Screen share (view only):

    var selfVideoView = MediaRenderView()
    var remoteVideoView = MediaRenderView()
    var screenShareView = MediaRenderView()
    webex.phone.dial("coworker@example.com", option: MediaOption.audioVideoScreenShare(video: (local: selfVideoView, remote: remoteVideoView), screenShare: screenShareView)) { ret in
        switch ret {
        case .success(let call):
            call.onConnected = {
                // ...
            }
            call.onDisconnected = { reason in
                // ...
            }
            call.onMediaChanged = { changed in
                switch changed {
                    ...
                case .remoteSendingScreenShare(let sending):
                    call.screenShareRenderView = sending ? view : nil
                }
            }
        case .failure(let error):
            // failure
        }
    }

NOTE: Screen sharing will only work using v3 SDK with the latest WebexBroadcastExtensionKit.

  1. Post a message:

    let plain = "foo"
    let markdown = "**foo**"
    let html = "<strong>foo</strong>"
    let text = Message.Text.html(html: html)
    webex.messages.post(text, toPersonEmail: emailAddress, completionHandler: { response in
        switch response.result {
        case .success(let message):
            // ...
        case .failure(let error):
            // ...
        }
    }
    let text = Message.Text.markdown(markdown: markdown) 
    webex.messages.post(text, toPersonEmail: emailAddress) { result in
        switch result {
        case .success(let message):
            // ...
        case .failure(let error):
            // ...
        }
    }
  2. Receive a message event:

    webex.messages.onEvent = { messageEvent in
        switch messageEvent{
        case .messageReceived(let message):
            // ...
        case .messageDeleted(let messageId):
            // ...
        }
    }
  3. send read receipt of a message

    webex.messages.markAsRead(spaceId: spaceId, messageId: messageId, completionHandler: { result in
         switch result {
         case .success(_):
             // ...
         case .failure(let error):
             // ...
         }
    })
  4. receive a membership event

    webex.memberships.onEvent = { membershipEvent in
          switch membershipEvent {
          case .created(let membership):
              // ...
          case .deleted(let membership):
              // ...
          case .update(let membership):
              // ...
          case .messageSeen(let membership, let lastSeenId):
              // ...
          }
    }
  5. get read statuses of all memberships in a space

    webex.memberships.listWithReadStatus(spaceId: spaceId, completionHandler: { response in
          switch response.result {
          case .success(let readStatuses):
              // ...
          case .failure(let error):
              // ...
          }
    })
  6. receive a space event

    webex.spaces.onEvent = { spaceEvent in
          switch spaceEvent {
          case .create(let space):
              // ...
          case .update(let space):
              // ...
          case .spaceCallStarted(let spaceId):
              // ...
          case .spaceCallEnded(let spaceId):
              // ...
          }
    }
  7. get read status of a space for login user

    webex.spaces.getWithReadStatus(spaceId: spaceId, completionHandler: { response in
          switch response.result {
          case .success(let spaceInfo):
              if let lastActivityDate = spaceInfo.lastActivityDate,
                  let lastSeenDate = spaceInfo.lastSeenActivityDate,
                  lastActivityDate > lastSeenDate {
    
                  // space is unreadable
    
              } else {
    
                  // space is readable
              }
          case .failure(let error):
              // ...
          }
    })
  8. get meeting detail of a space

    webex.spaces.getMeetingInfo(spaceId: spaceId, completionHandler: { result in
          switch result {
          case .success(let meetingInfo):
              // ...
          case .failure(let error):
              // ...
          }
    })
  9. get a list of spaces that have ongoing call

    webex.spaces.listWithActiveCalls(completionHandler: { result in
        switch result {
        case .success(let spaceIds):
            // ...
        case .failure(_ ):
            // ...
        }
    })
  10. Change the layout for the active speaker and other attendee composed video

    let option: MediaOption = MediaOption.audioVideo(local: ..., remote: ...)
    option.compositedVideoLayout = .grid
    
    webex.phone.dial(spaceId, option: option) { ret in
        // ...
    }
  11. Background Noise Removal(BNR)

    19.1 Enable BNR

    webex.phone.audioBNREnabled = true

    19.2 Set BNR mode, the default is .HP. It only affects if setting audioBNREnabled to true.

    webex.phone.audioBNRMode = .HP
  12. Get the supported product mode capability for the current user

    let capability: ProductCapability = webex.people.getProductCapability()
    let hasCalling = capability.isCallingSupported
    let hasMeeting = capability.isMeetingSupported
    let hasMessaging = capability.isMessagingSupported