1.概述
1.1 阅读对象
本文档为技术文档,需要阅读者:
- 具备基本的iOS开发能力
- 准备接入CC视频的直播SDK相关功能
- 对CC云直播产品使用方法有基础的了解,使用帮助地址
1.2 功能特性
功能 | 描述 |
---|---|
直播视频 | 观看直播视频 |
文档展示 | 能够观看当前直播文档,文档添加水印 |
线路更换 | 观看卡顿请换个线路 |
清晰度 | 支持直播多清晰度切换播放 |
答题卡 | 支持实时检测课堂学生的掌握程度 |
问答 | 能够发送问题和接受回答信息 |
简介 | 支持对直播间的信息展示 |
问卷 | 支持对观看直播的人进行信息采集 |
广播 | 支持发送全体消息 |
连麦 | 支持与直播人员进行音视频沟通 |
签到 | 支持签到功能 |
抽奖 | 支持抽奖功能 |
随堂测 | 支持随堂测互动 |
修改昵称 | 支持自定义昵称 |
聊天互动 | 支持与房间内的其他人聊天互动和一对一私聊 |
跑马灯 | 支持直播防录屏功能 |
2.开发准备
2.1 开发环境
- Xcode : Xcode 开发IDE
- Version 10.0 及以上
2.2 SDK配置
2.2.1 CocoaPods集成
已安装CocoaPods
如果是有连麦的SDK:
pod 'CCLivePlaySDK', '~> 3.8.0'
如果是无连麦的SDK:
v3.11.2 之前的版本请用如下链接:
pod 'CCLivePlaySDK', :podspec => 'https://raw.githubusercontent.com/CCVideo/Live_iOS_Play_SDK/3.8.0/CCLivePlaySDK.podspec'
v3.11.2 之后的版本请用如下链接:
pod 'CCLivePlaySDK', :podspec => 'https://hdgit.bokecc.com/ccvideo/Live_iOS_Play_SDK/raw/3.11.2/CCLivePlaySDK.podspec'
PS:其中3.8.0与3.11.2为SDK版本号可自行更改。
未安装CocoaPods
-
安装CocoaPods
打开终端:>_ 1、查看当前Ruby版本
ruby -v
2、升级Ruby环境,首先需要安装rvm(第一步要下载一些东西等两分钟左右)
curl -L get.rvm.io | bash -s stable source ~/.bashrc source ~/.bash_profile
3、查看rvm版本
rvm -v 显示如下(或者是其他版本) rvm 1.29.3 (latest) by Michal Papis, Piotr Kuczynski, Wayne E. Seguin [https://rvm.io]
4、列出ruby可安装的版本信息
rvm list known 显示如下 # MRI Rubies [ruby-]1.8.6[-p420] [ruby-]1.8.7[-head] # security released on head [ruby-]1.9.1[-p431] [ruby-]1.9.2[-p330] [ruby-]1.9.3[-p551] [ruby-]2.0.0[-p648] [ruby-]2.1[.10] [ruby-]2.2[.10] [ruby-]2.3[.7] [ruby-]2.4[.4] [ruby-]2.5[.1] // 重点在这里 重点在这里 重点在这里 [ruby-]2.6[.0-preview2] // 测试版 ruby-head .....
5、安装一个ruby版本
rvm install 2.5.1 // 注意:安装过程中需要两次按下 Enter 键, 第二次按下后需要输入电脑访问密码(不可见,只管输入就行); // 如果你电脑没有安装Xcode和Command Line Tools for Xcode以及Homebrew 会自动下载安装,建议提前安装这三者. 这里很多小伙伴会遇到错误,大部分是因为没有安装Homebrew造成,所以所以所以要提前安装比较好 /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
6、设置为默认版本
rvm use 2.5.1 --default
7、更换源
sudo gem update --system gem sources --remove https://rubygems.org/ gem sources --add https://gems.ruby-china.com/
8、为了验证你的Ruby镜像是并且仅是ruby-china,执行以下命令查看
gem sources -l 如果是以下结果说明正确,如果有其他的请自行百度解决 *** CURRENT SOURCES *** https://gems.ruby-china.com/
9、这时候才正式开始安装CocoaPods
sudo gem install -n /usr/local/bin cocoapods
10、如果安装了多个Xcode使用下面的命令选择(一般需要选择最近的Xcode版本)
sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer
11、安装本地库
pod setup
12、执行以上命令后
Setting up CocoaPods master repo $ /usr/bin/git clone https://github.com/CocoaPods/Specs.git master --progress Cloning into 'master'... remote: Counting objects: 1879515, done. remote: Compressing objects: 100% (321/321), done. Receiving objects: 21% (404525/1879515), 73.70 MiB | 22.00 KiB/ 然后就是漫长的等待,当然,网络好的情况下会更快
-
在Podfile文件中添加
如果是有连麦的SDK: pod 'CCLivePlaySDK', '~> 3.8.0' 如果是无连麦的SDK: v3.11.2 之前的版本请用如下链接: pod 'CCLivePlaySDK', :podspec => 'https://raw.githubusercontent.com/CCVideo/Live_iOS_Play_SDK/3.8.0/CCLivePlaySDK.podspec' v3.11.2 之后的版本请用如下链接: pod 'CCLivePlaySDK', :podspec => 'https://hdgit.bokecc.com/ccvideo/Live_iOS_Play_SDK/raw/3.11.2/CCLivePlaySDK.podspec' PS:其中3.8.0与3.11.2为SDK版本号可自行更改。
3. 在终端中执行
pod install
**ps:目前CocoaPods集成仅支持3.8.0及以后的版本,旧版本暂不支持CocoaPods集成**
### 2.2.2 手动集成
1.将SDK文件夹内的所有文件拖到项目中
command + b 编译,如果报错" file '...xxx/IJKMediaFramework.framework/IJKMediaFramework' for architecture arm64 " 解决方案: Targets -> Build Settings -> 搜索 "Enable Bitcode" 设置为 "NO"
2.command + r 运行
如果报错" dyld: Library not loaded: @rpath/XXX.framework " 解决方案: Targets -> Build Phases -> 点击左上角 "+" 按钮 -> 选择 "New Copy Files Phase" -> 点击新添加的 Copy Files 前面的下拉箭头 -> Destination 选择 "Frameworks" -> 点击当前目录下的 "+" 将SDK包含的.framework 包添加即可
## 2.3 日志存储
在AppDelegate.m文件导入头文件
#import "CCSDK/SaveLogUtil.h"
在启动方法中添加日志存储
- (BOOL)application:(UIApplication )application didFinishLaunchingWithOptions:(NSDictionary )launchOptions { /
- @brief 是否存储日志 */ [[SaveLogUtil sharedInstance]isNeedToSaveLog:YES]; return YES; }
## 2.4 错误码
服务错误类型
ERROR_SERVICE_TYPE
ERROR_ROOM_STATE = 1001 直播间状态不可用,可能没有开始推流 ERROR_USELESS_INFO = 1002 没有获取到有用的视频信息 ERROR_PASSWORD = 1003 密码错误
系统错误类型
ERROR_SYSTEM_TYPE
ERROR_RETURNDATA = 1004 返回内容格式错误 ERROR_PARAMETER = 1005 直播间信息填写错误 ERROR_NETWORK = 1006 网络异常 ERROR_LOGINDATA = 1007 登录 ERROR_PLAYERURL = 1008 视频播放地址 ERROR_QUESTIONLIST = 1009 问卷列表 ERROR_STATISTICAL = 1010 问卷统计 ERROR_DOCLIST = 1011 文档列表 ERROR_HISTORY = 1012 历史信息 PRACTICE_LIST = 1013 随堂测试 PRACTICECOMMIT = 1014 提交随堂测试 PRACTICESTATIS = 1015 获取随堂测统计 PRACTICERANK = 1016 获取随堂测排名 ERROR_SOCKET = 1017 socket加载失败 ERROR_PUNCH = 1018 获取打卡信息失败 ERROR_PUNCHCOMMIT = 1019 获取打卡提交结果失败 ERROR_DRMURL = 1020 获取加密地址失败
# 3.快速集成
## 3.1 配置参数
3.1.1 调用方法
/**
- @brief 登录房间
- @param parameter 配置参数信息
- 必填参数 userId; //用户ID
- 必填参数 roomId; //房间ID
- 必填参数 viewerName; //用户名
- 必填参数 token; //房间密码
- (已弃用!) security //是否使用https
- (选填参数) viewercustomua; //用户自定义参数,需和后台协商,没有定制传@"" */
- (id)initLoginWithParameter:(PlayParameter )parameter; /*
- @brief 进入房间,并请求画图聊天数据并播放视频(可以不登陆,直接从此接口进入直播间)
- @param parameter 配置参数信息
- 必填参数 userId; //用户ID
- 必填参数 roomId; //房间ID
- 必填参数 viewerName; //用户名称
- 必填参数 token; //房间密码
- 必填参数 docParent; //文档父类窗口
- 必填参数 docFrame; //文档区域
- 必填参数 playerParent; //视频父类窗口
- 必填参数 playerFrame; //视频区域
- 必填参数 scalingMode; //屏幕适配方式
- (已弃用!) security //是否使用https
- 必填参数 defaultColor; //ppt默认底色,不写默认为白色
- 必填参数 PPTScalingMode; //PPT适配方式 PPT适配模式分为四种,1.一种是全部填充屏幕,可拉伸变形,2.第二种是等比缩放,横向或竖向贴住边缘,另一方向可以留黑边,3.第三种是等比缩放,横向或竖向贴住边缘,另一方向出边界,裁剪PPT,不可以留黑边,4.根据直播间文档显示模式的返回值进行设置(推荐)(The New Method)
- 必填参数 pauseInBackGround; //后台是否继续播放,注意:如果开启后台播放需要打开 xcode->Capabilities->Background Modes->on->Audio,AirPlay,and Picture in Picture
- (选填参数)viewercustomua; //用户自定义参数,需和后台协商,没有定制传@"" */
- (id)initWithParameter:(PlayParameter *)parameter;
代理方法
/**
- @brief 登录成功 */
- (void)loginSucceedPlay; /**
- @brief 登录失败 */ -(void)loginFailed:(NSError *)error reason:(NSString *)reason;
/**
- @brief 请求成功 / -(void)requestSucceed; /*
- @brief 登录请求失败 */ -(void)requestFailed:(NSError *)error reason:(NSString *)reason;
3.1.2 集成
导入头文件
#import "CCSDK/RequestData.h"//SDK
声明变量
@property (nonatomic,strong)RequestData * requestData;//sdk
配置参数:PlayParameter的属性如下
/**
- @brief 用户ID / @property(nonatomic, copy)NSString userId;//用户ID /
- @brief 房间ID / @property(nonatomic, copy)NSString roomId;//房间ID /
- @brief 用户名称 / @property(nonatomic, copy)NSString viewerName;//用户名称 /
- @brief 房间密码 / @property(nonatomic, copy)NSString token;//房间密码 /
- @brief 用户自定义参数,需和后台协商,没有定制传@"" / @property(nonatomic, copy)NSString viewerCustomua;//用户自定义参数,需和后台协商,没有定制传@"" /
- json格式字符串,可选,自定义用户信息,该信息会记录在用户访问记录中,用于统计分析使用(长度不能超过1000个字符,若直播间启用接口验证则该参数无效)如果不需要的话就不要传值
- 格式如下:
- viewercustominfo: '{"exportInfos": [ {"key": "城市", "value": "北京"}, {"key": "姓名", "value": "哈哈"}]}' / @property(nonatomic, copy)NSString viewercustominfo; /
- @brief 文档父类窗口 / @property(nonatomic,strong)UIView docParent;//文档父类窗口 /
- @brief 文档区域 / @property(nonatomic,assign)CGRect docFrame;//文档区域 /*
- @brief 视频父类窗口 / @property(nonatomic,strong)UIView playerParent;//视频父类窗口 /
- @brief 视频区域 / @property(nonatomic,assign)CGRect playerFrame;//视频区域 /*
- @brief
- 0:IJKMPMovieScalingModeNone
- 1:IJKMPMovieScalingModeAspectFit
- 2:IJKMPMovieScalingModeAspectFill
- 3:IJKMPMovieScalingModeFill / @property(assign, nonatomic)NSInteger scalingMode;//屏幕适配方式,含义见上面 /*
- @brief ppt默认底色,不写默认为白色 / @property(nonatomic,strong)UIColor defaultColor;//ppt默认底色,不写默认为白色 /
- @brief /后台是否继续播放,注意:如果开启后台播放需要打开 xcode->Capabilities->Background Modes->on->Audio,AirPlay,and Picture in Picture / @property(nonatomic,assign)BOOL pauseInBackGround;//后台是否继续播放,注意:如果开启后台播放需要打开 xcode->Capabilities->Background Modes->on->Audio,AirPlay,and Picture in Picture /*
- @brief PPT适配模式分为四种,
- 1.一种是全部填充屏幕,可拉伸变形,
- 2.第二种是等比缩放,横向或竖向贴住边缘,另一方向可以留黑边,
- 3.第三种是等比缩放,横向或竖向贴住边缘,另一方向出边界,裁剪PPT,不可以留黑边
- 4.根据直播间文档显示模式的返回值进行设置(推荐) / @property(assign, nonatomic)NSInteger PPTScalingMode;//PPT适配方式,含义见上面 /*
- @brief PPT是否允许滚动 / @property(nonatomic, assign)BOOL pptInteractionEnabled; /*
- @brief 设置当前的文档模式,
- 1.切换至跟随模式(默认值)值为0,
- 2.切换至自由模式;值为1, / @property(assign, nonatomic)NSInteger DocModeType;//设置当前的文档模式 /*
- @brief 聊天分组id
-
使用聊天分组功能时传入,不使用可以不传
*/ @property(copy, nonatomic)NSString *groupid;
开始配置
第一步:实例化参数类 PlayParameter *parameter = [[PlayParameter alloc] init]; //配置PlayParameter里面的属性,如userId,roomId等! 第二步实例化RequestData类 _requestData = [[RequestData alloc] initWithParameter:parameter]; 第三步添加代理 _requestData.delegate = self;
添加代理
@interface 您的控制器 ()
实现代理
/**
- @brief 请求成功 */ -(void)requestSucceed {
} /**
- @brief 登录请求失败 */ -(void)requestFailed:(NSError *)error reason:(NSString *)reason {
}
**至此您的项目已经可以运行了,并且已经集成好了视频和文档基本功能;如果不需要文档功能则不配置文档相关属性即可**
## 3.2 观看直播
3.2.1 代理方法(可选)
/**
- @brief 主讲开始推流 */
- (void)onLiveStatusChangeStart;
/**
- @brief 停止直播,endNormal表示是否异常停止推流,这个参数对观看端影响不大 */
- (void)onLiveStatusChangeEnd:(BOOL)endNormal;
/**
- @brief 收到踢出消息,停止推流并退出播放(被主播踢出)(change)
-
dictionary[@"kick_out_type"] 踢出类型
-
dictionary[@"viewerid"] 用户ID
-
kick_out_type: 踢出类型
-
10 在允许重复登录前提下,后进入者会登录会踢出先前登录者
-
20 讲师、助教、主持人通过页面踢出按钮踢出用户
*/
- (void)onKickOut:(NSDictionary *)dictionary;
/**
- @brief 收到播放直播状态 0直播 1未直播 */
- (void)getPlayStatue:(NSInteger)status;
/**
- @brief 直播间被禁 */
- (void)theRoomWasBanned;
/**
- @brief 直播间解禁 */
- (void)theRoomWasCleared;
/**
- @brief 客户端关闭摄像头 数据源类型 数据源值 数据源类型描述 数据源类型描述值 source_type 0 source_type_desc 数据源类型:默认值, source_type 10 source_type_desc 数据源类型:摄像头打开 source_type 11 source_type_desc 数据源类型:摄像头关闭 source_type 20 source_type_desc 数据源类型:图片 source_type 30 source_type_desc 数据源类型:插播视频 source_type 40 source_type_desc 数据源类型:区域捕获 source_type 50 source_type_desc 数据源类型:桌面共享 source_type 60 source_type_desc 数据源类型:自定义场景
ps: source_type 参数 0 值 应用场景:
- 文档模式下 0 默认值
- 非文档模式下 0 无意义
- 低版本客户端 0 无意义 source_type 参数 60 值 应用场景: 当以上场景无法满足要求时,主播可自定义场景,用户不需要关心自定义场景细节内容 */
- (void)receivedSwitchSource:(NSDictionary *)dic;
/**
- @brief 视频或者文档大窗
- isMain 1为视频为主,0为文档为主" */
- (void)onSwitchVideoDoc:(BOOL)isMain; /**
- @brief 加载视频失败 */
- (void)play_loadVideoFail; /**
- @brief 视频状态
- rseult playing/paused/loading/buffing */ -(void)videoStateChangeWithString:(NSString *) result;
3.2.2 主动方法(可选)
/**
- @brief 改变播放器frame */
- (void)changePlayerFrame:(CGRect) playerFrame;
/**
- @brief 改变播放器父窗口 */
- (void)changePlayerParent:(UIView *) playerParent;
/**
- @brief 播放器暂停 */
- (void)pausePlayer;
/**
- @brief 播放器播放 */
- (void)startPlayer;
/**
- @brief 播放器关闭并移除 */
- (void)shutdownPlayer;
/**
- @brief 播放器停止 */
- (void)stopPlayer;
/**
- @brief 重新加载视频,参数force表示是否强制重新加载视频,
- 一般重新加载视频的时间间隔应该超过3秒,如果强制重新加载视频,时间间隔可以在3S之内 */ -(void)reloadVideo:(BOOL)force;
/**
- @brief 播放器是否播放 */
- (BOOL)isPlaying;
/**
- @brief 设置后台是否可播放 */
- (void)setpauseInBackGround:(BOOL)pauseInBackGround; /**
- @brief 销毁文档和视频,清除视频和文档的时候需要调用,退出播放页面的时候也需要调用 */
- (void)requestCancel; /**
- @brief 获取直播开始时间和直播时长
- liveDuration 直播持续时间,单位(s),直播未开始返回-1"
- liveStartTime 新增开始直播时间(格式:yyyy-MM-dd HH:mm:ss),如果直播未开始,则返回空字符串 */
- (void)startTimeAndDurationLiveBroadcast:(NSDictionary )dataDic; /* 获取已播放时长,调用后会响应onLivePlayedTime方法,调用间隔三秒 */
- (void)getLivePlayedTime; /**
- @brief 回调已播放时长, 如果未开始,则time为-1
-
触发此方法需要调用getLivePlayedTime
*/
- (void)onLivePlayedTime:(NSDictionary *)dic;
## 3.3 文档功能
3.3.1 代理方法(可选)
/**
- @brief 获取文档内白板或者文档本身的宽高,来进行屏幕适配用的 */
- (void)getDocAspectRatioOfWidth:(CGFloat)width height:(CGFloat)height;
/**
- @brief 获取ppt当前页数和总页数(The new method)
- 回调当前翻页的页数信息
- 白板docTotalPage一直为0, pageNum从1开始
- 其他文档docTotalPage为正常页数,pageNum从0开始
- @param dictionary 翻页信息
- dictionary :{docId 文档ID
-
docName 文档名
-
docTotalPage 文档总页数
-
pageNum 文档页码}
*/
- (void)onPageChange:(NSDictionary *) dictionary;
/**
- @brief 双击ppt */
- (void)doubleCllickPPTView;
/**
- @brief 获取所有文档列表
-
@param listDic [{ docId //文档ID docName //文档名称 docTotalPage //文档总页数 iconSrc //图标地址 pages [{ pageIndex //当前页位置 src //当前页地址 title //当前页标题 }]}]
*/
- (void)receivedDocsList:(NSDictionary *)listDic;
/**
- @brief 视频或者文档大窗
- isMain 1为视频为主,0为文档为主" */
- (void)onSwitchVideoDoc:(BOOL)isMain; /**
- @brief 文档加载状态
- index
-
0 文档组件初始化完成
-
1 动画文档加载完成
-
2 非动画文档加载完成
-
3文档组件加载失败
-
4文档图片加载失败
-
5文档动画加载失败
-
6画板加载失败
*/
- (void)docLoadCompleteWithIndex:(NSInteger)index;
3.3.2 主动方法(可选)
/**
- @brief 获取文档区域内白板或者文档本身的宽高比,返回值即为宽高比,做屏幕适配用 */
- (CGFloat)getDocAspectRatio;
/**
- @brief 改变文档区域大小,主要用在文档生成后改变文档窗口的frame */
- (void)changeDocFrame:(CGRect) docFrame;
/**
- @brief 改变文档父窗口 */
- (void)changeDocParent:(UIView *) docParent;
/**
- @brief 切换当前的文档模式
- 1.切换至跟随模式(默认值)值为0,
- 2.切换至自由模式;值为1, */
- (void)changeDocMode:(NSInteger)mode;
/**
- @brief 查找并获取当前文档的信息
- @param docId 文档的docId
- @param pageIndex 跳转的页数 */
- (void)changePageToNumWithDocId:(NSString )docId pageIndex:(NSInteger)pageIndex; /* 重新加载文档 */
- (void)docReload; /** 改变文档背景颜色
@param hexColor 字符串,传颜色的HEXColor 如:#000000 */
- (void)changeDocWebColor:(NSString )hexColor; /*
- 获取ppt列表(只能在登陆成功后调用) */
- (void)getDocsList;
## 3.4 房间信息
代理方法(可选)
/**
- @brief 获取房间信息,主要是要获取直播间模版来类型,根据直播间模版类型来确定界面布局
- 房间简介:dic[@"desc"];
- 房间名称:dic[@"name"];
- 房间模版类型:[dic[@"templateType"] integerValue];
- 模版类型为1: 聊天互动: 无 直播文档: 无 直播问答: 无
- 模版类型为2: 聊天互动: 有 直播文档: 无 直播问答: 有
- 模版类型为3: 聊天互动: 有 直播文档: 无 直播问答: 无
- 模版类型为4: 聊天互动: 有 直播文档: 有 直播问答: 无
- 模版类型为5: 聊天互动: 有 直播文档: 有 直播问答: 有
- 模版类型为6: 聊天互动: 无 直播文档: 无 直播问答: 有 */ -(void)roomInfo:(NSDictionary *)dic;
/**
- @brief 服务器端给自己设置的信息
- viewerId 服务器端给自己设置的UserId
- groupId 分组id
- name 用户名 / -(void)setMyViewerInfo:(NSDictionary ) infoDic; /
- @brief 房间设置信息
- dic{ "allow_chat" = true;//是否允许聊天 "allow_question" = true;//是否允许问答 "room_base_user_count" = 0;//房间基础在线人数 "source_type" = 0;//对应receivedSwitchSource方法的source_type } *ps:当房间类型没有聊天或者问答时,对应的字段默认为true / -(void)roomSettingInfo:(NSDictionary )dic; /
- @brief 服务器端给自己设置的UserId */ -(void)setMyViewerId:(NSString *)viewerId;
##3.5 聊天功能
代理方法(可选)
/**
- @brief 历史聊天数据
- @param chatLogArr [{ chatId //聊天ID content //聊天内容 groupId //聊天组ID time //时间 userAvatar //用户头像 userId //用户ID userName //用户名称 userRole //用户角色}] */
- (void)onChatLog:(NSArray )chatLogArr; /
- @brief 收到公聊消息 @param message { groupId //聊天组ID msg //消息内容 time //发布时间 useravatar //用户头像 userid //用户ID username //用户名称 userrole //用户角色} */
- (void)onPublicChatMessage:(NSDictionary )message; /*
- @brief 收到私聊信息
- @param dic {fromuserid //发送者用户ID
-
fromusername //发送者用户名
-
fromuserrole //发送者角色
-
msg //消息内容
-
time //发送时间
-
touserid //接受者用户ID
-
tousername //接受者用户名}
*/
- (void)OnPrivateChat:(NSDictionary )dic; /
- @brief 收到自己的禁言消息,如果你被禁言了,你发出的消息只有你自己能看到,其他人看不到 @param message { groupId //聊天组ID msg //消息内容 time //发布时间 useravatar //用户头像 userid //用户ID username //用户名称 userrole //用户角色} */
- (void)onSilenceUserChatMessage:(NSDictionary )message; /*
- @brief 当主讲全体禁言时,你再发消息,会出发此代理方法,information是禁言提示信息 */
- (void)information:(NSString )information; /*
- @brief 自定义消息 */
- (void)customMessage:(NSString )message; /*
- @brief 收到聊天禁言并删除聊天记录
- viewerId 禁言用户id,是自己的话别删除聊天历史,其他人需要删除该用户的聊天 / -(void)onBanDeleteChat:(NSDictionary ) viewerDic; /
- @brief 收到聊天禁言
- mode 禁言类型 1:个人禁言 2:全员禁言 / -(void)onBanChat:(NSDictionary ) modeDic; /
- @brief 收到解除禁言事件
- mode 禁言类型 1:个人禁言 2:全员禁言 / -(void)onUnBanChat:(NSDictionary ) modeDic; /
- @brief 聊天管理
- status 聊天消息的状态 0 显示 1 不显示
- chatIds 聊天消息的id列列表 */ -(void)chatLogManage:(NSDictionary *) manageDic;
主动方法(可选)
/**
- @brief 发送公聊信息
- @param message 发送的消息内容 */
- (void)chatMessage:(NSString )message; /*
- @brief 发送私聊信息 */
- (void)privateChatWithTouserid:(NSString )touserid msg:(NSString )msg; /
- @brief 发送公聊信息
- @param message 发送的消息内容
-
completion 发送回调 成功或者失败
*/
- (void)sendChatMessage:(NSString *)message completion:(void (^)(BOOL success))completion;
## 3.6 问答功能
代理方法(可选)
/**
- @brief 收到提问,用户观看时和主讲的互动问答信息
- @param questionDic { groupId //分组ID content //问答内容 userName //问答用户名 userId //问答用户ID time //问答时间 id //问答主键ID useravatar //用户化身 } */
- (void)onQuestionDic:(NSDictionary )questionDic; /*
- @brief 收到回答
- @param answerDic {content //回复内容 userName //用户名 questionUserId //问题用户ID time //回复时间 questionId //问题ID isPrivate //1 私聊回复 0 公聊回复 } */
- (void)onAnswerDic:(NSDictionary )answerDic; /*
- @brief 收到历史提问&回答
- @param questionArr [{content //问答内容 encryptId //加密ID groupId //分组ID isPublish //1 发布的问答 0 未发布的问答 questionUserId //问答用户ID questionUserName //问答用户名 time //问答时间 triggerTime //问答具体时间}]
- @param answerArr [{answerUserId //回复用户ID answerUserName //回复名 answerUserRole //回复角色(主讲、助教) content //回复内容 encryptId //加密ID groupId //分组ID isPrivate //1 私聊回复 0 公共回复 time = 135; //回复时间 triggerTime //回复具体时间}] */
- (void)onQuestionArr:(NSArray )questionArr onAnswerArr:(NSArray )answerArr; /
- @brief 发布问题的ID */
- (void)publish_question:(NSString *)publishId;
主动方法(可选)
/**
- @brief 提问
- @param message 提问内容 */
- (void)question:(NSString *)message;
## 3.7 连麦功能
代理方法(可选)
/**
- @brief 本房间为允许连麦的房间,会回调此方法,在此方法中主要设置UI的逻辑,
- 在断开推流,登录进入直播间和改变房间是否允许连麦状态的时候,都会回调此方法 */
- (void)allowSpeakInteraction:(BOOL)isAllow; /**
- @brief WebRTC连接成功,在此代理方法中主要做一些界面的更改 */
- (void)connectWebRTCSuccess; /**
- @brief 当前是否可以连麦 */
- (void)whetherOrNotConnectWebRTCNow:(BOOL)connect; /**
- @brief 主播端接受连麦请求,在此代理方法中,要调用DequestData对象的
-
- (void)saveUserInfo:(NSDictionary *)dict remoteView:(UIView *)remoteView;方法
- 把收到的字典参数和远程连麦页面的view传进来,这个view需要自己设置并发给SDK,SDK将要在这个view上进行渲染
- @param dict {type //audio 音频 audiovideo 音视频
-
videosize //视频尺寸
-
viewerId //申请连麦ID
-
viewerName //申请连麦名}
*/
- (void)acceptSpeak:(NSDictionary )dict; /*
- @brief 主播端发送断开连麦的消息,收到此消息后做断开连麦操作 */ -(void)speak_disconnect:(BOOL)isAllow;
主动方法(可选)
/**
- @brief 设置远程连麦窗口的大小,连麦成功后调用才生效,连麦不成功调用不生效 / -(void)setRemoteVideoFrameA:(CGRect)remoteVideoFrame; /*
- @brief 设置本地预览窗口的大小,连麦成功后调用才生效,连麦不成功调用不生效 / -(void)setLocalVideoFrameA:(CGRect)localVideoFrame; /*
- @brief 当观看端主动申请连麦时,需要调用这个接口,并把本地连麦预览窗口传给SDK,SDK会在这个view上
- 进行远程画面渲染
- param localView:本地预览窗口,传入本地view,连麦准备时间将会自动绘制预览画面在此view上
- param isAudioVideo:是否是音视频连麦,不是音视频即是纯音频连麦(YES表示音视频连麦,NO表示音频连麦) / -(void)requestAVMessageWithLocalView:(UIView )localView isAudioVideo:(BOOL)isAudioVideo; /
- @brief 当收到- (void)acceptSpeak:(NSDictionary *)dict;回调方法后,调用此方法
- dict 正是- (void)acceptSpeak:(NSDictionary *)dict;接收到的的参数
- remoteView 是远程连麦页面的view,需要自己设置并发给SDK,SDK将要在这个view上进行远程画面渲染 */
- (void)saveUserInfo:(NSDictionary )dict remoteView:(UIView )remoteView; /
- @brief 将要连接WebRTC / -(void)gotoConnectWebRTC; /*
- @brief 观看端主动断开连麦时候需要调用的接口 */
- (void)disConnectSpeak;
##3.8 切换线路和清晰度
代理方法(可选)
/**
- @brief 切换线路
- @param firRoadNum 线路
- @param secRoadKeyArray 清晰度[@"标清",@"高清"] */
- (void)firRoad:(NSInteger)firRoadNum secRoadKeyArray:(NSArray *)secRoadKeyArray;
主动方法(可选)
/**
- @brief 切换播放线路和清晰度
- firIndex表示第几个线路
- key表示该线路对应的secRoadKeyArray里面的元素 */
- (void)switchToPlayUrlWithFirIndex:(NSInteger)firIndex key:(NSString *)key;
## 3.9 答题卡功能
/**
- @brief 开始答题 */
- (void)start_vote:(NSInteger)count singleSelection:(BOOL)single; /**
- @brief 结束答题 */
- (void)stop_vote;
/**
- @brief 答题结果
- @param resultDic {answerCount //参与回答人数
correctOption //正确答案 (单选字符串,多选字符串数组)
statisics[{ //统计数组
count //选择当前选项人数
option //选项序号
percent //正确率 }]
voteCount //题目数量
voteId //题目ID
voteType //题目类型}
*/
- (void)vote_result:(NSDictionary )resultDic; /*
- @brief 收到打卡提交结果
- dic{ "success": true, "data": { "isRepeat": false//是否重复提交打卡 } } / -(void)hdReceivedPunchResultWithDict:(NSDictionary )dic; /
- @brief 收到开始打卡
- dic { "punchId": "punchId", "expireTime": "2019-10-26 10:00:00", "remainDuration": 124 }
- 当没有设置时长,即无过期时间时
- { "punchId": "asasdasdasdasd", "remainDuration": -1 //其中-1表示剩余无限时间。 } / -(void)hdReceivedStartPunchWithDict:(NSDictionary )dic; /
- @brief 收到结束打卡
- dic{ "punchId": "punchId" } */ -(void)hdReceivedEndPunchWithDict:(NSDictionary *)dic;
/**
- @brief 答单选题 / -(void)reply_vote_single:(NSInteger)index; /*
- @brief 答多选题 @param IndexArray [题目index,题目index] 例:[1,2] */ -(void)reply_vote_multiple:(NSMutableArray *)indexArray;
## 3.10 问卷功能
代理方法(可选)
/**
- @brief 发布问卷 */
- (void)questionnaire_publish; /**
- @brief 结束发布问卷 */
- (void)questionnaire_publish_stop; /**
- @brief 获取问卷详细内容
- @param detailDic { forcibly //1就是强制答卷,0为非强制答卷 id //问卷主键ID subjects //包含的项目 submitedAction //1提交后查看答案,0为提交后不查看答案 title //标题 } */
- (void)questionnaireDetailInformation:(NSDictionary )detailDic; /*
- @brief 获取问卷统计
- @param staticsDic { forcibly //1就是强制答卷,0为非强制答卷 id //问卷主键ID subjects //包含的项目 submitedAction //1提交后查看答案,0为提交后不查看答案 title //标题 } */
- (void)questionnaireStaticsInformation:(NSDictionary )staticsDic; /*
- @brief 提交问卷结果(成功,失败) */
- (void)commitQuestionnaireResult:(BOOL)success; /**
- @brief 问卷功能 */
- (void)questionnaireWithTitle:(NSString *)title url:(NSString *)url;
主动方法(可选)
/**
- @brief 提交问卷结果
- @param dic{subjectsAnswer[{selectedOptionId //选中选项ID subjectId //题目ID}]} / -(void)commitQuestionnaire:(NSDictionary )dic; /
- @brief 主动请求问卷 */ -(void)getPublishingQuestionnaire;
## 3.11 广播功能
代理方法(可选)
/**
- @brief 接收到发送的广播
- @param dic {content //广播内容 userid //发布者ID username //发布者名字 userrole //发布者角色 } */
- (void)broadcast_msg:(NSDictionary )dic; /*
- @brief 接收到最后一条广播(直播中途进入,会返回最后一条广播)
- @param array[{ content //广播内容 publisherId //发布者ID publisherName //发布者名字 publisherRole //发布者角色 time //发布时间 }] */
- (void)broadcastLast_msg:(NSArray *)array;
## 3.12 签到功能
代理方法(可选)
/**
- @brief 开始签到 */
- (void)start_rollcall:(NSInteger)duration;
主动方法(可选)
/**
- @brief 签到 / -(void)answer_rollcall; /* 提交打卡
@param punchId 打卡id */
- (void)hdCommitPunchWithPunchId:(NSString )punchId; /* 查询打卡信息 */
- (void)hdInquirePunchInformation;
## 3.13 抽奖功能
代理方法(可选)
/**
- @brief 开始抽奖 */
- (void)start_lottery; /**
- @brief 抽奖结果
- remainNum 剩余奖品数 */
- (void)lottery_resultWithCode:(NSString )code myself:(BOOL)myself winnerName:(NSString )winnerName remainNum:(NSInteger)remainNum; /
- @brief 退出抽奖 */
- (void)stop_lottery;
## 3.14 修改昵称
代理方法(可选)
/**
- @brief 修改昵称 */
- (void)onChangeNickname:(NSString *)nickNime;
主动方法(可选)
/**
- @brief 修改昵称
- @param nickName 修改后的昵称 */
- (void)changeNickName:(NSString *)nickName;
## 3.15 在线人数
代理方法(可选)
/**
- @brief 收到在线人数 */
- (void)onUserCount:(NSString )count; /* 收到老师列表 teachers = ( { id = "";//老师id ip = "";//IP地址 name = "";老师昵称 role = teacher;//角色 } ); */ -(void)onOnlineTeachers:(NSDictionary *)dic;
主动放法(可选)
/**
- @brief 获取在线房间人数,当登录成功后即可调用此接口,登录不成功或者退出登录后就不可以调用了,如果要求实时性比较强的话,可以写一个定时器,不断调用此接口,几秒钟发一次就可以,然后在代理回调函数中,处理返回的数据,15秒响应一次 */
- (void)roomUserCount; /** 获取老师列表 */
- (void)getOnlineTeachers;
## 3.16 随堂测功能
代理方法(可选)
/**
- @brief 接收到随堂测(The new method)
- rseultDic 随堂测内容 resultDic {isExist //1 随堂考存在 0随堂考不存在 practice {id //随堂考主键ID isAnswered //false 未回答过 true 回答过 options = ({ id //选项主键ID index //选项序号}) publishTime //发布时间 status //发布状态 1开启 0关闭 type //题目类型 0判断 1单选 2多选} serverTime //分发时间}
/ -(void)receivePracticeWithDic:(NSDictionary ) resultDic; /
- @brief 随堂测提交结果(The new method)
- rseultDic 提交结果,调用commitPracticeWithPracticeId:(NSString *)practiceId options:(NSArray *)options后执行
- resultDic {datas {practice //随堂测 { answerResult // id //随堂测主键ID isRepeatAnswered //是否重置答案 options ({ count //参与人数 id //选项主键ID index //选项序号 isCorrect //是否正确 percent //选项占比}) submitRecord ({ optionId //提交记录 提交选项ID optionIndex //提交选项序号}) type //题型 0 判断 1单选 2多选}}} / -(void)practiceSubmitResultsWithDic:(NSDictionary ) resultDic; /
- @brief 随堂测统计结果(The new method)
- rseultDic 统计结果,调用getPracticeStatisWithPracticeId:(NSString *)practiceId后执行 resultDic {practice { //随堂测 answerPersonNum //回答人数 correctPersonNum //回答正确人数 correctRate //正确率 id //随堂测主键ID options ({ //选项数组 count //选择人数 id //选项ID index //选项序号 isCorrect //是否正确 percent //选项选择率}) status //状态 type //题型 0判断 1单选 2多选}} / -(void)practiceStatisResultsWithDic:(NSDictionary ) resultDic; /
- @brief 随堂测排名结果
- rseultDic 排名结果,调用getPracticeRankWithPracticeId:(NSString *)practiceId后执行 ressult{practice { //随堂测 id //随堂测主键ID ranking ({ //排名 costTime //回答用时 viewerId //用户ID viewerName //用户名})}} / -(void)practiceRankResultsWithDic:(NSDictionary ) resultDic; /
- @brief 停止随堂测(The new method)
- rseultDic 结果
- resultDic {practiceId //随堂测主键ID} / -(void)practiceStopWithDic:(NSDictionary ) resultDic; /
- @brief 关闭随堂测(The new method)
- rseultDic 结果
- resultDic {practiceId //随堂测主键ID} / -(void)practiceCloseWithDic:(NSDictionary ) resultDic; /
- @brief 收到奖杯(The new method)
- dic 结果
- "type": 1 奖杯 2 其他
- "viewerName": 获奖用户名
- "viewerId": 获奖用户ID */ -(void)prize_sendWithDict:(NSDictionary *)dic;
主动方法(可选)
/**
-
@brief 提交随堂测
-
@param practiceId 随堂测ID
-
@param options 选项ID
*/
- (void)commitPracticeWithPracticeId:(NSString )practiceId options:(NSArray )options; /
-
@brief 获取随堂测统计信息(可多次调用)
-
@param practiceId 随堂测ID
/ -(void)getPracticeStatisWithPracticeId:(NSString )practiceId; /
-
@brief 获取随堂测排名(可多次调用)
-
@param practiceId 随堂测ID
/ -(void)getPracticeRankWithPracticeId:(NSString )practiceId; /
- @brief 获取随堂测
- @param practiceId 随堂测ID(没有传@"") */ -(void)getPracticeInformation:(NSString *)practiceId;
## 3.17 公告
代理方法(可选)
/**
- @brief 公告 */
- (void)announcement:(NSString )str; /*
- @brief 监听到有公告消息
- @dict {action //action 返回release 取出公告内容,action 返回remove 删除公告 announcement //公告内容} */
- (void)on_announcement:(NSDictionary *)dict;
## 3.18 跑马灯
代理方法(可选)
/**
- @brief 跑马灯
- @param dic action [{ //事件 duration //执行时间 end { //结束位置 alpha //透明度 xpos //x坐标 ypos //y坐标 }, start { //开始位置 alpha //透明度 xpos //x坐标 ypos //y坐标}] image { //包含图片 height //图片高度 image_url //地址 width //图片宽度} loop //循环次数 -1 无限循环 text { //文字信息 color //文字颜色 content //文字内容 font_size //字体大小} type //当前类型 text 文本 image 图片 */ -(void)receivedMarqueeInfo:(NSDictionary *)dic;
# 4.常见问题
## 4.1 旋转屏错误
常用的旋转屏方式
第一个方法决定是否支持多方向旋转屏,如果返回NO则后面的两个方法都不会再被调用,而且只会支持默认的UIInterfaceOrientationMaskPortrait方向;
第二个方法直接返回支持的旋转方向,该方法在iPad上的默认返回值是UIInterfaceOrientationMaskAll,iPhone上的默认返回值是UIInterfaceOrientationMaskAllButUpsideDown,官方文档有说明
第三个方法返回最优先显示的屏幕方向,比如同时支持Portrait和Landscape方向,但想优先显示Landscape方向,那软件启动的时候就会先显示Landscape,在手机切换旋转方向的时候仍然可以在Portrait和Landscape之间切换
HD云直播的页面跳转均是采用模态形式跳转
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^ __nullable)(void))completion NS_AVAILABLE_IOS(5_0);
在每个控制器或者基类控制器设置旋转选项
#pragma mark - 屏幕旋转
-
(BOOL)shouldAutorotate{ return NO;//该旋转的页面自己变量控制 }
-
(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return UIInterfaceOrientationPortrait; }
-
(UIInterfaceOrientationMask)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; }
## 4.2 Swift实现代理错误
//初始化
let parameter = PlayParameter.init()
/**
*配置各种参数
*/
//守护代理
guard let player = RequestData else {
return}
player.delegate = self
## 4.3 查看手机日志
首先: 在AppDelegate中写如下代码(仅限CCSDK);
[[SaveLogUtil sharedInstance]isNeedToSaveLog:YES];
第一步:选择Windows下面的Devices and Simulators
第二步:点击Devices and Simulators 会出现手机信息以及测试的INSTALLED APPS, 点击设置(齿轮图标) 会出现三个选项, 选择Download Container...
第三步: 点击Download Container... 下载并保存日志文件,打开文件找到XXLog文件里面就是相关的打印日志
第四步:这里可以看到相关的请求信息和打印日志, 也可以判断错误原因
## 4.4 编译失败和打包上架打包失败
错误大意为
Failed to verify bitcode in xxxxx error: Bundle only contains bitcode-marker /var/folders/s5/lnk362pd4cs0lmtn_43ppjzw0000gn/T/XcodeDistPipeline.2TS/Root/Payload/268YK.appxxxxxxxxxx (armv7)
解决办法:
第一步: xcode -> file -> Workspace Settings
第二步: Shared Workspace Settings:
第三步:Build System -> Legacy Build System
## 4.5 提交问卷的格式
主动提交问卷这个方法参数格式
-(void)commitQuestionnaire:(NSDictionary *)dic
{ subjectsAnswer = ( { //单选 selectedOptionId = 6DBB147BC4EF99A7; subjectId = 5DEEA9F9FD1DDFAD; }, { //多选 selectedOptionIds = "A2F4436135131236,1A8C59C6F3A774F5"; subjectId = 658A573395F3E00D; }, { //问答 answerContent = Qqq; subjectId = 10F9E9D82094F36C; } ); }