实现基础功能
更新时间: 2023/04/14 07:19:01
本文为您介绍如何通过 NEMeetingKit 提供的一套简单易用的接口,快速地将音视频会议基础功能集成至现有应用中。
- 初始化
- 登录鉴权
- 创建会议
- 加入会议
- 匿名入会
- 预约会议
- 编辑预约会议
- 取消预约会议
- 查询预约会议信息
- 查询指定状态下的预约会议列表
- 监听预约会议状态
- 监听会议状态
- 监听登录状态
- 监听全局事件
- 获取当前会议信息
- 注销登录
- 使用会议设置服务
会议状态流程图
预约会议或即时会议的状态流转图如下所示。
API 时序图
NEMeetingKit 实现在线会议的主要流程如下图所示。
初始化
在调用 SDK 其他接口之前,您首先需要完成初始化操作。
- 请在初始化接口的回调返回后再执行其他操作,否则会失败。
- 请不要重复初始化,否则 SDK 会报错。
- 配置初始化相关参数。
示例代码如下:
NEMeetingKitConfig *config = [[NEMeetingKitConfig alloc] init]; config.appKey = [DemoConfig shareConfig].appKey; //应用 App Key
- 调用
initialize
方法完成初始化操作。该接口无额外回调结果数据。 示例代码如下:[[NEMeetingKit getInstance] initialize:config callback:^(NSInteger resultCode, NSString *resultMsg, id result) { if (resultCode == ERROR_CODE_SUCCESS) { //初始化成功 } else { //初始化失败 } }];
登录鉴权
请求 SDK 进行登录鉴权,您只有完成 SDK 登录鉴权才可以创建会议。
NEMeetingKit 提供了多种登录方式供您选择,调用不同的登录接口需要传入不同的参数,具体说明如下表。
登录方式 | 说明 | 接口 | 参数 | 其他 |
---|---|---|---|---|
Token 登录 | - | NEMeetingKit#login | accountId、accountToken | 账号信息需要从网易会议服务端获取,由您自行实现相关业务逻辑。 |
自动登录 | SDK 尝试使用最近一次成功登录过的账号信息进行登录。 | NEMeetingKit#tryAutoLogin | - | - |
以下就 Token 登录方式说明 NEMeetingKit 的登录鉴权逻辑,其他登录方式同理。
SDK 不提供账号注册机制。您在自己的应用中集成 SDK 时,需要将用户帐号与网易会议系统中的帐号(accountId)进行绑定。
-
请在登录前先获取账号 ID 和 Token。账号信息由网易会议的应用服务器下发,但 SDK 不提供对应接口获取该信息,需要您自行实现相关业务逻辑。
示例代码如下:
NSString *accountId = @"your_accountId"; NSString *accountToken = @"your_accountToken";
-
调用
login
方法登录并进行回调处理,该接口无额外回调结果数据。示例代码如下:
[[NEMeetingKit getInstance] login:accountId token:accountToken callback:^(NSInteger resultCode, NSString *resultMsg, id result) { if (resultCode == ERROR_CODE_SUCCESS) { //登录成功 } else { //登录失败 } }];
创建会议
在已经完成 SDK 登录鉴权的状态下,创建并开始一个新的会议。
- 该接口仅支持在登录鉴权成功后调用,其他情况下会调用失败。
- 若您入会前配置了允许最小化会议界面,则在会中进行此操作时,SDK 会返回会议状态
NEMeetingStatus#MEETING_STATUS_INMEETING_MINIMIZED
的回调通知。若您需要返回会议界面,请调用[[NEMeetingKit getInstance].getMeetingService returnToMeeting]
方法。
-
配置创建会议相关参数。
示例代码如下:
NEStartMeetingParams *params = [[NEStartMeetingParams alloc] init]; //会议参数 params.meetingNum = @"123456789"; //会议号。若创建个人会议,则此处应传调用服务端创建会议接口时返回的 meetingNum(10 位数字的个人会议码);若创建随机会议,则置空,SDK 会使用 9 位数字的随机会议码 params.displayName = @"我的会议昵称; //会议昵称 params.displayName = "我的会议昵称"; //会议昵称 params.roleBinds = @{@"userUuid": @(枚举值)}; //指定用户角色类型,可以设置为 host,cohost,member NEStartMeetingOptions *options = [[NEStartMeetingOptions alloc] init]; //会议选项,可自定义会中的 UI 显示、菜单、行为等 options.noVideo = YES; //入会时关闭视频,默认为 YES options.noAudio = YES; //入会时关闭音频,默认为 YES options.noInvite = NO; //入会隐藏"邀请"按钮,默认为 NO options.noChat = NO; //入会隐藏"聊天"按钮,默认为 NO options.noWhiteBoard = NO; //入会隐藏白板入口,默认为 NO options.noGallery = NO; //入会隐藏设置"画廊模式"入口,默认为 NO options.noSwitchCamera = NO; //入会隐藏"切换摄像头"功能入口,默认为 NO options.noSwitchAudioMode = NO; //入会隐藏"切换音频模式"功能入口,默认为 NO options.noRename = NO; //入会隐藏"改名"功能入口,默认为 NO options.showMeetingTime = NO; //设置入会后是否显示会议持续时间,默认为 NO options.noCloudRecord = YES; //入会隐藏"录制中"显示,默认为 YES options.noMinimize = YES; //入会是否允许最小化会议页面,默认为 YES options.defaultWindowMode = NEWindowMode.normal; //入会默认会议视图模式 options.meetingIdDisplayOption = DISPLAY_ALL; //设置会议中会议 ID 的显示规则,默认为全部显示 options.noSip = NO; //会议是否支持 SIP 用户入会,默认为 NO options.showMeetingRemainingTip = NO; //会议中是否开启剩余时间(秒)提醒,默认为 NO NEMeetingChatroomConfig *chatroomConfig = [[NEMeetingChatroomConfig alloc] init]; //配置聊天室 chatroomConfig.enableFileMessage = YES //是否允许发送/接收文件消息,默认为 YES chatroomConfig.enableImageMessage = YES; //是否允许发送/接收图片消息,默认为 YES //options.fullToolbarMenuItems = configToolbarMenuItems(); //自定义【Toolbar】菜单 //options.fullToolbarMenuItems = configMoreMenuItems(); //自定义【更多】菜单
具体如何自定义 Toolbar 和更多菜单请参考自定义菜单。
-
调用
startMeeting
方法创建会议并进行回调处理。该接口无额外回调结果数据,您可根据错误码判断接口是否调用成功。示例代码如下:
NEMeetingService *meetingServce = [NEMeetingKit getInstance].getMeetingService; [meetingServce startMeeting:params opts:options callback:^(NSInteger resultCode, NSString *resultMsg, id result) { if (resultCode == ERROR_CODE_SUCCESS) { //创建会议成功 } else { //创建会议失败 } }];
-
会议成功创建后,SDK 会拉起会议界面并接管会议逻辑:创建会议的用户会自动成为该会议的主持人,可以进行相关的会议控制操作;其他用户可以通过该会议号入会。
加入会议
在已经完成 SDK 登录鉴权的状态下,加入一个当前正在进行中的会议。
-
配置加入会议相关参数。
- 会议号不能为空,需要配置为正在进行中的会议的真实 ID。
- 具体如何自定义 Toolbar 和更多菜单请参考自定义菜单。
- 若您入会前配置了允许最小化会议界面,则在会中进行此操作时,SDK 会返回会议状态
NEMeetingStatus#MEETING_STATUS_INMEETING_MINIMIZED
的回调通知。若您需要返回会议界面,请调用[[NEMeetingKit getInstance].getMeetingService returnToMeeting]
方法。
示例代码如下:
NEJoinMeetingParams *params = [[NEJoinMeetingParams alloc] init]; //会议参数 params.meetingNum = @"123456789"; //会议号,此处应传调用服务端创建会议接口时返回的 meetingNum params.displayName = @"我的会议昵称; //会议昵称 NEJoinMeetingOptions *options = [[NEJoinMeetingOptions alloc] init]; //会议选项,可自定义会中的 UI 显示、菜单、行为等 options.noVideo = YES; //入会时关闭视频,默认为 YES options.noAudio = YES; //入会时关闭音频,默认为 YES options.noInvite = NO; //入会隐藏"邀请"按钮,默认为 NO options.noChat = NO; //入会隐藏"聊天"按钮,默认为 NO options.noWhiteBoard = NO; //入会隐藏白板入口,默认为 NO options.noGallery = NO; //入会隐藏设置"画廊模式"入口,默认为 NO options.noSwitchCamera = NO; //入会隐藏"切换摄像头"功能入口,默认为 NO options.noSwitchAudioMode = NO; //入会隐藏"切换音频模式"功能入口,默认为 NO options.noRename = NO; //入会隐藏"改名"功能入口,默认为 NO options.showMeetingTime = NO; //设置入会后是否显示会议持续时间,默认为 NO options.noCloudRecord = YES; //入会隐藏"录制中"显示,默认为 YES options.noMinimize = YES; //入会是否允许最小化会议页面,默认为 YES options.defaultWindowMode = NEWindowMode.normal; //入会默认会议视图模式 options.meetingIdDisplayOption = DISPLAY_ALL; //设置会议中会议 ID 的显示规则,默认为全部显示 options.noSip = NO; //会议是否支持 SIP 用户入会,默认为 NO options.showMeetingRemainingTip = NO; //会议中是否开启剩余时间(秒)提醒,默认为 NO NEMeetingChatroomConfig *chatroomConfig = [[NEMeetingChatroomConfig alloc] init]; //配置聊天室 chatroomConfig.enableFileMessage = YES //是否允许发送/接收文件消息,默认为 YES chatroomConfig.enableImageMessage = YES; //是否允许发送/接收图片消息,默认为 YES //options.fullToolbarMenuItems = configToolbarMenuItems(); //自定义【Toolbar】菜单 //options.fullToolbarMenuItems = configMoreMenuItems(); //自定义【更多】菜单
-
调用
joinMeeting
方法加入会议并进行回调处理。该接口无额外回调结果数据,您可根据错误码判断接口是否调用成功。该接口仅支持在登录鉴权成功后调用,其他情况下会调用失败。
示例代码如下:
NEMeetingService *meetingServce = [NEMeetingKit getInstance].getMeetingService; [meetingServce joinMeeting:params opts:options callback:^(NSInteger resultCode, NSString *resultMsg, id result) { if (resultCode == ERROR_CODE_SUCCESS) { //加入会议成功 } else { //加入会议失败 } }];
匿名入会
在已完成初始化的状态下,匿名加入一个当前正在进行中的会议。
-
配置加入会议相关参数。
- 会议号不能为空,需要配置为正在进行中的会议的真实 ID。
- 具体如何自定义 Toolbar 和更多菜单请参考自定义菜单。
- 若您入会前配置了允许最小化会议界面,则在会中进行此操作时,SDK 会返回会议状态
NEMeetingStatus#MEETING_STATUS_INMEETING_MINIMIZED
的回调通知。若您需要返回会议界面,请调用[[NEMeetingKit getInstance].getMeetingService returnToMeeting]
方法。
示例代码如下:
NEJoinMeetingParams *params = [[NEJoinMeetingParams alloc] init]; //会议参数 params.meetingNum = @"123456789"; //会议号 params.displayName = @"我的会议昵称; //会议昵称 NEJoinMeetingOptions *options = [[NEJoinMeetingOptions alloc] init]; //会议选项,可自定义会中的 UI 显示、菜单、行为等 options.noVideo = YES; //入会时关闭视频,默认为 YES options.noAudio = YES; //入会时关闭音频,默认为 YES options.noInvite = NO; //入会隐藏"邀请"按钮,默认为 NO options.noChat = NO; //入会隐藏"聊天"按钮,默认为 NO options.noWhiteBoard = NO; //入会隐藏白板入口,默认为 NO options.noGallery = NO; //入会隐藏设置"画廊模式"入口,默认为 NO options.noSwitchCamera = NO; //入会隐藏"切换摄像头"功能入口,默认为 NO options.noSwitchAudioMode = NO; //入会隐藏"切换音频模式"功能入口,默认为 NO options.noRename = NO; //入会隐藏"改名"功能入口,默认为 NO options.showMeetingTime = NO; //设置入会后是否显示会议持续时间,默认为 NO options.noCloudRecord = YES; //入会隐藏"录制中"显示,默认为 YES options.noMinimize = YES; //入会是否允许最小化会议页面,默认为 YES options.defaultWindowMode = NEWindowMode.normal; //入会默认会议视图模式 options.meetingIdDisplayOption = NEMeetingIdDisplayOption.DISPLAY_ALL; //设置会议中会议 ID 的显示规则,默认为全部显示 //options.fullToolbarMenuItems = configToolbarMenuItems(); //自定义【Toolbar】菜单 //options.fullToolbarMenuItems = configMoreMenuItems(); //自定义【更多】菜单
-
调用
anonymousJoinMeeting
方法加入会议并进行回调处理。该接口无额外回调结果数据,您可根据错误码判断接口是否调用成功。该接口在完成登录鉴权前后均可调用。
示例代码如下:
NEMeetingService *meetingServce = [NEMeetingKit getInstance].getMeetingService; [meetingServce anonymousJoinMeeting:params opts:options callback:^(NSInteger resultCode, NSString *resultMsg, id result) { if (resultCode == ERROR_CODE_SUCCESS) { //加入会议成功 } else { //加入会议失败 } }];
预约会议
在已经完成 SDK 登录鉴权的状态下,预约一个新的会议。
调用 scheduleMeeting
方法预会议并进行回调处理,您可根据错误码判断接口是否调用成功。
示例代码如下:
//获取会议预约服务
NEPreMeetingService *premeetingService = [NEMeetingSDK getInstance].getPreMeetingService;
//预约会议的 Item
NEMeetingItem *item = [premeetingService createScheduleMeetingItem];
uint64_t startTimeS = [[NSDate date] timeIntervalSince1970];
item.subject = @"xxx预定的会议"; //会议主题
item.startTime = startTimeS * 1000; //会议开始时间,单位ms
item.endTime = (startTimeS + 30*60) * 1000; //会议结束时间,单位ms
item.password = @"123456"; //入会密码,也可以不填
item.live.enable = NO; //是否开启直播
item.live.liveWebAccessControlLevel = NEMeetingLiveAuthLevelToken;//设置直播安全模式
item.roleBinds = @{@"userUuid": @(枚举值)}; //指定用户角色类型,可以设置为 host,cohost,member
item.noSip = false; //会议是否支持 SIP 用户入会,默认为 false
NEMeetingItemSetting *setting = [[NEMeetingItemSetting alloc] init];
setting.attendeeAudioOff = NO; //入会时打开音频开关
setting.cloudRecordOn = YES; //是否开启云端录制
//预约会议
[premeetingService scheduleMeeting:item
callback:^(NSInteger resultCode, NSString * _Nonnull resultMsg, NEMeetingItem * _Nonnull item) {
if (resultCode == ERROR_CODE_SUCCESS) {
//预约成功
//返回的 item 里面会更新服务端下发的只读属性(meetingId, meetingNum, updateTime)
//请以返回的 item 为准,替换掉之前申请的 item
} else {
//预约失败, resultCode 参考 NEMeetingErrorCode
}
}];
编辑预约会议
在已经完成 SDK 登录鉴权的状态下,编辑一个已经预约的会议。
调用 editMeeting
方法编辑会议并进行回调处理,您可根据错误码判断接口是否调用成功。
- 该接口仅支持在登录鉴权成功后调用,其他情况下会调用失败。
- 预约会议时,
scheduleMeeting
接口中的参数NEMeetingItem
,必须是createScheduleMeetingItem
返回的createScheduleMeetingItem
对象。
示例代码如下:
[[[NEMeetingKit getInstance] getPreMeetingService] editMeeting:self.item
callback:^(NSInteger resultCode, NSString * _Nonnull resultMsg, NEMeetingItem * _Nonnull item) {
if (resultCode == ERROR_CODE_SUCCESS) {
// 编辑成功
} else {
// 编辑失败
}
}];
取消预约会议
在已经完成 SDK 登录鉴权的状态下,取消一个已经预约的会议。
调用 cancelMeeting
方法取消预约会议并进行回调处理,您可根据错误码判断接口是否调用成功。
- 该接口仅支持在登录鉴权成功后调用,其他情况下会调用失败。
- 取消预约会议时,
cancelMeeting
接口中的参数meetingId
是服务端返回的唯一码,请从NEMeetingItem#meetingId
处获取。 - 您无法取消正在进行中的、处于回收状态的或已经结束的会议。
示例代码如下:
[[NEMeetingKit getInstance].getPreMeetingService cancelMeeting:meetingId callback:^(NSInteger resultCode, NSString *resultMsg) {
if (resultCode == ERROR_CODE_SUCCESS) {
// 取消成功
} else {
// 取消失败
}
}];
查询预约会议信息
在已经完成 SDK 登录鉴权的状态下,查询一个已经预约的会议的信息。
调用 getMeetingItemById
方法查询预约会议信息并进行回调处理,您可根据错误码判断接口是否调用成功。
- 该接口仅支持在登录鉴权成功后调用,其他情况下会调用失败。
- 查询预约会议的信息时,
getMeetingItemById
接口中的参数meetingNum
是会议号,请从NEMeetingItem#meetingNum
处获取。
示例代码如下:
//获取会议预约服务
NEPreMeetingService *premeetingService = [NEMeetingKit getInstance].getPreMeetingService;
//查询操作
[premeetingService getMeetingItemById:_item.meetingNum
callback:^(NSInteger resultCode,
NSString * _Nonnull resultMsg,
NEMeetingItem * _Nonnull item) {
if (resultCode == ERROR_CODE_SUCCESS) {
//查询成功
} else {
//查询失败
}
}];
查询指定状态下的预约会议列表
在已经完成 SDK 登录鉴权的状态下,根据指定的一种或多种会议状态在已预约的所有会议基础上筛选出会议列表。
调用 getMeetingList
方法查询指定状态下的预约会议列表并进行回调处理,您可根据错误码判断接口是否调用成功。
- 该接口仅支持在登录鉴权成功后调用,其他情况下会调用失败。
- 调用此接口时,默认返回最近一周的指定会议列表。
示例代码如下:
//获取会议预约服务
NEPreMeetingService *premeetingService = [NEMeetingKit getInstance].getPreMeetingService;
//待查询状态
NSArray *meetingStatus = @[@(NEMeetingItemStatusInit),
@(NEMeetingItemStatusStarted),
@(NEMeetingItemStatusEnded)];
//查询列表
[premeetingService getMeetingList:meetingStatus
callback:^(NSInteger resultCode, NSString * _Nonnull resultMsg,
NSArray<NEMeetingItem *> * _Nonnull items) {
if (resultCode == ERROR_CODE_SUCCESS) {
//查询成功
} else {
//查询失败
}
}];
监听预约会议状态
通过注册预约会议状态回调接口,获取预约会议状态变更的通知。
- 该接口在初始化 SDK 成功后即可调用。
- 一次预约会议状态变更回调可能包含多个预约会议信息的变更。
-
注册回调接口
addListener:self
开始监听,并在回调方法中根据您的需求处理相应事件。- 当回调参数
incremental
为 NO 时,预约会议的状态为全量变更。 - 当回调参数
incremental
为 YES 时,预约会议的状态为增量变更。
示例代码如下:
//注册事件回调 [[NEMeetingKit getInstance].getPreMeetingService addListener:self]; //实现回调方法 - (void)onScheduleMeetingStatusChange:(NSArray<NEMeetingItem *> *)changedMeetingItemList incremental:(BOOL)incremental { if (incremental) { //进行全量更新 } else { //进行增量更新 } }
- 当回调参数
-
反注册回调接口
removeListener:self
停止监听。示例代码如下:
//反注册事件回调(在不需要的时候移除,例如在 dealloc 方法中) [[NEMeetingKit getInstance].getPreMeetingService removeListener:self];
监听会议状态
通过注册会议状态回调接口,获取会议状态变更的通知。
-
注册回调接口
addListener:self
开始监听,并在回调方法中根据您的需求处理相应事件。该接口在初始化 SDK 成功后即可调用。
**示例代码*如下:
//会议添加监听 [[NEMeetingKit getInstance].addGlobalEventListener:self]; #pragma mark - NEGlobalEventListener - (void)beforeRtcEngineReleaseWithRoomUuid:(NSString *)roomUuid rtcWrapper:(NERtcWrapper *)rtcWrapper { NSLog(@"Rtc销毁前操作. RoomUuid: %@", roomUuid); } - (void)beforeRtcEngineInitializeWithRoomUuid:(NSString *)roomUuid rtcWrapper:(NERtcWrapper *)rtcWrapper { NSLog(@"Rtc初始化之前操作"); } - (void)afterRtcEngineInitializeWithRoomUuid:(NSString *)roomUuid rtcWrapper:(NERtcWrapper *)rtcWrapper { NSLog(@"Rtc初始化之后操作"); }
-
反注册回调接口
removeListener:self
停止监听。示例代码如下:
[[NEMeetingKit getInstance].getMeetingService removeListener:self];
监听全局事件
通过注册全局事件回调接口,获取相应事件通知,目前支持监听 RTC 初始化和销毁相关的事件。
-
注册回调接口
addGlobalEventListener:self
开始监听,并在回调方法中根据您的需求处理相应事件。该接口在初始化 SDK 成功后即可调用。
示例代码如下:
//会议添加监听 [[NEMeetingKit getInstance].addGlobalEventListener:self]; //MeetingServiceListener 协议实现 - (void)beforeRtcEngineInitialize:(NEMeetingEvent *)event { //引擎初始化前回调 } - (void)afterRtcEngineInitialize:(NEMeetingEvent *)event { //引擎初始化后回调 } - (void)beforeRtcEngineRelease:(NEMeetingEvent *)event { //引擎销毁前回调 }
-
反注册回调接口
removeGlobalEventListener:self
停止监听。示例代码如下:
[[NEMeetingKit getInstance].removeGlobalEventListener:self];
获取当前会议信息
在已经完成 SDK 登录鉴权的状态下,获取当前会议信息。
调用 getCurrentMeetingInfo
方法获取当前会议信息并进行回调处理。该接口的回调结果的数据类型为 NEMeetingInfo 对象类型。
- 请确认已经通过一种入会方式(加入会议/创建会议/匿名入会)加入到会议内,否则回调数据对象为空。
- 该接口仅支持在登录鉴权成功后调用,其他情况下会调用失败。
示例代码如下:
[[NEMeetingSDK getInstance].getMeetingService getCurrentMeetingInfo:^(NSInteger resultCode, NSString * _Nonnull resultMsg, NEMeetingInfo * _Nonnull info) {
if (resultCode != ERROR_CODE_SUCCESS) {
//查询失败
} else {
//查询成功
}
}];
监听登录状态
通过注册登录状态回调接口,获取登录状态变更的通知。
-
注册回调接口
addAuthListener
开始监听,并在回调方法中根据您的需求处理相应事件。示例代码如下:
[[NEMeetingKit getInstance] addAuthListener:self]; /// 当前账号已在其他设备上登录 - (void)onKickOut {} /// 账号信息过期通知,原因为用户修改了密码,应用层随后应该重新登录 - (void)onAuthInfoExpired {}
-
反注册回调接口
removeAuthListener
停止监听。示例代码如下:
[[NEMeetingKit getInstance] removeAuthListener:self];//移除监听
注销登录
注销当前已登录的账号,返回未登录状态。
调用 logout
方法注销当前账号并进行回调处理。该接口无额外回调结果数据,您可根据错误码判断接口是否调用成功。
账号注销后,登录状态会被清空,且无法再使用该账号创建会议。
示例代码如下:
[[NEMeetingKit getInstance] logout:^(NSInteger resultCode, NSString *resultMsg, id result) {
if (resultCode == ERROR_CODE_SUCCESS) {
//注销登录成功
} else {
//注销登录失败
}
}];
使用会议设置服务
通过会议设置服务,设置和查询用户的当前会议设置,例如如入会时的音视频开关状态、会议持续时间的显示等。
- 每个已登录的用户有自己独立的一份会议设置项;其他所有未登录用户、匿名用户共享一份会议设置项。
- 会议设置项仅在当前设备上保存,不会漫游。
- 调用创建/加入会议方法时,若您设置
NEMeetingOptions
参数为 null,SDK 会使用会议设置服务中已保存的相关配置进行创会/入会。
-
调用
getSettingService
方法获取会议设置服务。示例代码如下:
NESettingsService *settingsService = [NEMeetingKit getInstance].getSettingsService;
-
调用不同方法设置或查询会议设置项。
示例代码如下:
// 设置并保存会议设置 [settingsService enableShowMyMeetingElapseTime:YES]; [settingsService setTurnOnMyAudioWhenJoinMeeting:YES]; [settingsService setTurnOnMyVideoWhenJoinMeeting:YES]; //查询会议设置 BOOL showMeetingElapseTimeEnabled = [settingsService isShowMyMeetingElapseTimeEnabled]; BOOL audioEnabled = [settingsService isTurnOnMyAudioWhenJoinMeetingEnabled]; BOOL videoEnabled = [settingsService isTurnOnMyVideoWhenJoinMeetingEnabled];