WebexSDK 3.12.0

WebexSDK 3.12.0

Evan ShiZhiyu LiuBharath BalanAkshay AgarwalRavi SarikaNitin Sharma 维护。



WebexSDK 3.12.0

  • 作者为
  • Webex SDK 团队

Cisco Webex iOS SDK

CocoaPods Travis CI license

Cisco Webex iOS SDK 可以让您轻松地将安全且便捷的 Cisco Webex 消息和呼叫功能集成到您的 iOS 应用中。

此 SDK 使用 Swift 5 编写,并需要 iOS 11 或更高版本。

目录

安装

假设您已经有了 Xcode 项目,例如用于您的 iOS 应用的 MyWebexApp,以下是使用 CocoaPods 集成 Webex iOS SDK 到您 Xcode 项目的步骤

  1. 安装 CocoaPods

    gem install cocoapods
  2. 配置 Cocoapods

    pod setup
  3. 在您的 MyWebexApp 项目目录中创建一个新的文件 Podfile,包含以下内容

    source 'https://github.com/CocoaPods/Specs.git'
    
    use_frameworks!
    
    target 'MyWebexApp' do
      platform :ios, '11.0'
      pod 'WebexSDK'
    end
    
    target 'MyWebexAppBroadcastExtension' do
        platform :ios, '11.2'
        pod 'WebexBroadcastExtensionKit'
    end
  4. 从您的 MyWebexApp 项目目录安装 Webex iOS SDK

    pod install

用法

要使用SDK,您需要Webex集成凭据。如果您还没有Webex账户,请访问Webex开发者创建账户并注册您的集成。对于现有的Webex用户,您的应用需要通过OAuth授权流进行用户认证,对于没有Webex账户的访客用户,需要通过JSON Web Token进行认证。

有关此SDK的更多信息,请参阅Webex开发者网站的iOS SDK区域

示例

以下是如何在您的应用中使用iOS SDK的一些示例。

  1. 使用Webex ID认证(基于OAuth)创建Webex实例

    let clientId = "$YOUR_CLIENT_ID"
    let clientSecret = "$YOUR_CLIENT_SECRET"
    let scope = "spark:all"
    let redirectUri = "Webexdemoapp://response"
    
    let authenticator = OAuthAuthenticator(clientId: clientId, clientSecret: clientSecret, scope: scope, redirectUri: redirectUri)
    let webex = Webex(authenticator: authenticator)
    
    if !authenticator.authorized {
        authenticator.authorize(parentViewController: self) { success in
            if !success {
                print("User not authorized")
            }
        }
    }
  2. 使用Guest ID认证(基于JWT)创建Webex实例

    let authenticator = JWTAuthenticator()
    let webex = Webex(authenticator: authenticator)
    
    if !authenticator.authorized {
        authenticator.authorizedWith(jwt: myJwt)
    }
  3. 注册设备以发送和接收通话

    webex.phone.register() { error in
        if let error = error {
            // Device not registered, and calls will not be sent or received
        } else {
            // Device registered
        }
    }
  4. 使用Webex服务

    webex.spaces.create(title: "Hello World") { response in
        switch response.result {
        case .success(let space):
            // ...
        case .failure(let error):
            // ...
        }
    }
    
    // ...
    
    webex.memberships.create(spaceId: spaceId, personEmail: email) { response in
        switch response.result {
        case .success(let membership):
            // ...
        case .failure(let error):
            // ...
        }
    }
    
  5. 发起通话

    webex.phone.dial("[email protected]", option: MediaOption.audioVideo(local: ..., remote: ...)) { ret in
        switch ret {
        case .success(let call):
            call.onConnected = {
                // ...
            }
            call.onDisconnected = { reason in
                // ...
            }
        case .failure(let error):
            // failure
        }
    }
  6. 接收通话

    webex.phone.onIncoming = { call in
        call.answer(option: MediaOption.audioVideo(local: ..., remote: ...)) { error in
        if let error = error {
            // success
        }
        else {
            // failure
        }
    }
  7. 发起空间通话

    webex.phone.dial(spaceId, option: MediaOption.audioVideo(local: ..., remote: ...)) { ret in
        switch ret {
        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
        }
    }
  8. 屏幕共享(仅查看)

    webex.phone.dial("[email protected]", option: MediaOption.audioVideoScreenShare(video: (local: ..., remote: ...))) { 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
        }
    }
  9. 发送消息

    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, html: html, plain: text)
    webex.messages.post(text, toPersonEmail: emailAddress, completionHandler: { response in
        switch response.result {
        case .success(let message):
            // ...
        case .failure(let error):
            // ...
        }
    }
  10. 接收消息事件

    webex.messages.onEvent = { messageEvent in
        switch messageEvent{
        case .messageReceived(let message):
            // ...
            break
        case .messageDeleted(let messageId):
            // ...
            break
        }
    }
  11. 发送消息已读回执

    webex.messages.markAsRead(spaceId: spaceId, messageId: messageId, completionHandler: { response in
         switch response.result {
         case .success(_):
             // ...
         case .failure(let error):
             // ...
         }
    })
  12. 屏幕共享(发送)

    12.1 在您的容器应用中

    webex.phone.dial("[email protected]", option: MediaOption.audioVideoScreenShare(video: ..., screenShare: ..., applicationGroupIdentifier: "group.your.application.group.identifier"))) { ret in
        switch ret {
        case .success(let call):
            call.oniOSBroadcastingChanged = {
                event in
                if #available(iOS 11.2, *) {
                    switch event {
                    case .extensionConnected :
                        call.startSharing() {
                            error in
                            // ...
                        }
                        break
                    case .extensionDisconnected:
                        call.stopSharing() {
                            error in
                            // ...
                        }
                        break
                    }
                }
            }
            }
        case .failure(let error):
            // failure
        }
    }

    12.2 在您的广播上传扩展示例处理程序中

    override func broadcastStarted(withSetupInfo setupInfo: [String : NSObject]?) {
        // User has requested to start the broadcast. Setup info from the UI extension can be supplied but optional.
        WebexBroadcastExtension.sharedInstance.start(applicationGroupIdentifier: "group.your.application.group.identifier") {
            error in
            if let webexError = error {
               // ...
            } else {
                WebexBroadcastExtension.sharedInstance.onError = {
                    error in
                    // ...
                }
                WebexBroadcastExtension.sharedInstance.onStateChange = {
                    state in
                    // state change
                }
            }
        }
    }
    
    override func broadcastFinished() {
        // User has requested to finish the broadcast.
        WebexBroadcastExtension.sharedInstance.finish()
    }
    
    override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {
        switch sampleBufferType {
            case RPSampleBufferType.video:
                // Handle video sample buffer
                WebexBroadcastExtension.sharedInstance.handleVideoSampleBuffer(sampleBuffer: sampleBuffer)
                break
            case RPSampleBufferType.audioApp:
                // Handle audio sample buffer for app audio
                break
            case RPSampleBufferType.audioMic:
                // Handle audio sample buffer for mic audio
                break
        }
    }

    12.3 了解有关容器应用及广播上传扩展设置App Group的更多技术细节

  13. 在会议中接收更多视频流

    class VideoCallViewController: MultiStreamObserver {
        ...
        var onAuxStreamChanged: ((AuxStreamChangeEvent) -> Void)? = {
            ...
            switch event {
            case .auxStreamOpenedEvent(let view, let result):
                switch result {
                    case .success(let auxStream):
                        ...
                    case .failure(let error):
                        ...
                }
            case .auxStreamPersonChangedEvent(let auxStream,_,_):
                    ...
            case .auxStreamSendingVideoEvent(let auxStream):
                ...
            case .auxStreamSizeChangedEvent(let auxStream):
                ...
            case .auxStreamClosedEvent(let view, let error):
                ...
            }
        }
    
        var onAuxStreamAvailable: (() -> MediaRenderView?)? = {
            ...
            return self.mediaRenderViews.filter({!$0.inUse}).first?
        }
    
        var onAuxStreamUnavailable: (() -> MediaRenderView?)? = {
            ...
            return self.mediaRenderViews.filter({$0.inUse}).last?
        }
    
        override func viewWillAppear(_ animated: Bool) {
            ...
            // set the observer of this call to get multi stream event.
            self.call.multiStreamObserver = self
            ...
        }
    }
  14. 接收成员事件

    webex.memberships.onEvent = { membershipEvent in
          switch membershipEvent {
          case .created(let membership):
              // ...
          case .deleted(let membership):
              // ...
          case .update(let membership):
              // ...
          case .seen(let membership, let lastSeenId):
              // ...
          }
    }
  15. 获取空间中所有成员的已读状态

    webex.memberships.listWithReadStatus(spaceId: spaceId, completionHandler: { response in
          switch response.result {
          case .success(let readStatuses):
              // ...
          case .failure(let error):
              // ...
          }
    })
  16. 接收空间事件

    webex.spaces.onEvent = { spaceEvent in
          switch spaceEvent {
          case .create(let space):
              // ...
          case .update(let space):
              // ...
          case .spaceCallStarted(let spaceId):
              // ...
          case .spaceCallEnded(let spaceId):
              // ...
          }
    }
  17. 获取登录用户的空间的已读状态

    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):
              // ...
          }
    })
  18. 获取空间会议详细信息

    webex.spaces.getMeetingInfo(spaceId: spaceId, completionHandler: { response in
          switch response.result {
          case .success(let meetingInfo):
              // ...
          case .failure(let error):
              // ...
          }
    })
  19. 获取正在进行通话的空间的列表

    webex.spaces.listWithActiveCalls(completionHandler: { (result) in
        switch result {
        case .success(let spaceIds):
            // ...
        case .failure(_ ):
            // ...
        }
    })
  20. 更改活动演讲者和其他参会者视频的布局

    let option: MediaOption = MediaOption.audioVideo(local: ..., remote: ...)
    option.layout = .grid
    
    webex.phone.dial(spaceId, option: option) { ret in
        // ...
    }
  21. 背景噪声消除(BNR)

    21.1 启用BNR

    webex.phone.audioBNREnabled = true

    21.2 设置BNR模式,默认为.HP。只有当设置audioBNREnabled为true时才生效。

    webex.phone.audioBNRMode = .HP

Cisco SparkSDK迁移

本指南的目的是帮助您从Cisco SparkSDK迁移到Cisco WebexSDK。

假设您已经有一个集成SparkSDK的项目。

  1. 在您的Podfile中

    移除之前的SparkSDK: pod 'SparkSDK'

    添加WebexSDK: pod 'WebexSDK'

  2. 转到项目目录,并运行

    pod install
  3. 替换代码中的sdk导入信息

    在项目范围内替换

    "import SparkSDK" => "import WebexSDK"

  4. 如果您使用故事板进行UI

    在"Identity Inspector"中更改Media Render View的模块

    "SparkSDK" => "WebexSDK"

使用方法

从SparkSDK到WebexSDK的API变更列表。

描述 SparkSDK使用 WebexSDK使用
创建新实例 let spark = Spark(authenticator: authenticator) let webex = Webex(authenticator: authenticator)
"室"客户端重命名为"空间"客户端 spark.rooms.list(roomId:{rooomId}) webex.spaces.list(spaceId:{roomId})
"SparkError"重命名为"WebexError" let error = SparkError.Auth let error = WebexError.Auth

建议在项目代码中将包含"spark"的变量替换为"webex"。

授权协议

© 2016-2020 Cisco Systems, Inc.及其关联公司。版权所有。

有关详细信息,请参阅授权协议