WebexBroadcastExtensionKit 3.12.0

WebexBroadcastExtensionKit 3.12.0

Evan ShiZhiyu LiuBharath BalanAkshay AgarwalRavi SarikaNitin Sharma 维护。



  • Webex SDK 团队

Cisco Webex iOS SDK

CocoaPods Travis CI license

Cisco Webex iOS SDK 使您能够轻松地将安全和便利的 Cisco Webex 消息和呼叫功能集成到您的 iOS 应用中。

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

目录

安装

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

  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,您将需要Cisco Webex集成凭据。如果您还没有Cisco Webex账户,请访问Webex for Developers创建您的账户并注册集成。您的应用需要通过OAuth授权流程对现有的Cisco Webex用户进行用户验证,或通过JSON Web Token对没有Cisco Webex账户的访客用户进行验证。

有关此SDK的更多信息,请参阅Webex for Developers网站的iOS SDK区域

示例

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

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

    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的认证创建Webex实例(《JWT-based)

    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部分,在您的容器应用程序中

    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部分,在你的广播上传扩展样本处理器中

    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部分,获取有关容器应用程序 & 广播上传扩展设置应用程序组的更多技术细节

  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. 在您的Pod文件中

    移除之前的SparkSDK:pod 'SparkSDK'

    添加WebexSDK:pod 'WebexSDK'

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

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

    在项目范围内进行替换

    "import SparkSDK" => "import WebexSDK"

  4. 如果您使用Storyboard进行UI

    更改媒体渲染视图的模块,在"Indentity inspector"中

    "SparkSDK" => "WebexSDK"

用途

从SparkSDK到WebexSDK的API更改列表。

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

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

项目名称

© 2016-2021 Cisco Systems, Inc.及其分支机构。版权所有。

有关详细信息,请参阅LICENSE