有奖捉虫:办公协同&微信生态&物联网文档专题 HOT
本文主要介绍使用 TIM 作为同步通道。

平台支持

iOS
Android
Windows
Mac OS
Web
小程序

注意事项

因为实时录制会以 TIMSDK 作为信令通道,同时是以自定义消息的 extension:'TXWhiteBoardExt' 为标识,所以在同步信令的时候需要注意以下四点:
1. 使用 TIMSDK 作为信令通道。
2. 关闭互动白板内置的信令通道(一定需要关闭,否则会收不到 onTEBSyncData 回调)。
3. 同步信令的时候发送的消息类型为自定义消息类型。
4. 自定义消息的 extension 字段必须为 TXWhiteBoardExt。

同步原理




监听 onTEBSyncData 事件(事件名以各端实际为准),将事件中回调的数据通过信令通道进行广播。
收到白板信令后,调用互动白板 addSyncData 接口(接口名以各端实际为准)进行同步。

代码集成

Mac/iOS
说明
以下示例为 TIM V2 版本代码,IM 的版本请尽量用新版本,具体请查阅 IM 的 更新日志
// 1. 将 TEduBoardInitParam 的 timSync 参数初始为 NO (关闭互动白板内置的信令通道)
TEduBoardInitParam *initParam = [[TEduBoardInitParam alloc] init];
initParam.timSync = NO; // 关闭互动白板内置的信令通道(一定需要关闭,否则会收不到onTEBSyncData回调)
_boardController = [[TEduBoardController alloc] initWithAuthParam:authParam roomId:_classId initParam:initParam];

// 2. 监听白板信令数据回调 onTEBSyncData,将数据发送给其他白板用户
- (void)onTEBSyncData:(NSString *)data {
V2TIMMessage *message = [[V2TIMManager sharedInstance] createCustomMessage:data desc:nil extension:@"TXWhiteBoardExt"];
if (message.customElem) {
message.customElem.extension = @"TXWhiteBoardExt";
}
[[V2TIMManager sharedInstance] getConversation:@"groupid" succ:^(V2TIMConversation *conv) {
if ([conv type] == V2TIM_GROUP) {
BOOL onlineUserOnly = ![[conv.groupType lowercaseString] isEqualToString:@"avchatroom"];
[[V2TIMManager sharedInstance] sendMessage: message
receiver: nil
groupID: conv.groupID
priority: V2TIM_PRIORITY_HIGH
onlineUserOnly:onlineUserOnly
offlinePushInfo:nil
progress:nil succ:^{
// 发送 IM 消息成功
} fail:^(int code, NSString *desc) {
// 发送 IM 消息失败,建议进行重试
}];
}

} fail:^(int code, NSString *desc) {
// 获取回话失败
}];

}

// 3. 监听IM的消息回调,在收到其他用户的白板信令时,将消息传递给白板
// 注意: 自己操作触发的信令,不需要再同步给本人
[_boardController addSyncData:data];
Android
说明
以下示例为 TIM V2 版本代码,IM 的版本请尽量用新版本,具体请查阅 IM 的 更新日志
// 1. 将 TEduBoardInitParam 的 timSync 参数初始为 NO (关闭互动白板内置的信令通道)
TEduBoardController.TEduBoardInitParam initParam = new TEduBoardController.TEduBoardInitParam();
initParam.timSync = false; // 关闭互动白板内置的信令通道(一定需要关闭,否则会收不到onTEBSyncData回调)

// 2. 监听白板信令回调 onTEBSyncData,将信令发送给其他白板用户
@Override
public void onTEBSyncData(String data) {
final V2TIMMessage message = V2TIMManager.getMessageManager().createCustomMessage(data.getBytes(), "", "TXWhiteBoardExt".getBytes());
if (message.getCustomElem() != null) {
message.getCustomElem().setExtension("TXWhiteBoardExt".getBytes());
}
V2TIMManager.getConversationManager().getConversation("groupid", new V2TIMValueCallback<V2TIMConversation>() {
@Override
public void onSuccess(V2TIMConversation v2TIMConversation) {
if (v2TIMConversation.getType() == V2TIMConversation.V2TIM_GROUP) {
boolean onlineUserOnly = !(v2TIMConversation.getGroupType().toLowerCase().equals("avchatroom"));
V2TIMManager.getMessageManager().sendMessage(message, null, "groupid", 1, onlineUserOnly, null, new V2TIMSendCallback<V2TIMMessage>() {
@Override
public void onSuccess(V2TIMMessage v2TIMMessage) {
// 发送 IM 消息成功
}

@Override
public void onError(int i, String s) {
// 发送 IM 消息失败,建议进行重试
}

@Override
public void onProgress(int i) {

}
});
}
}

@Override
public void onError(int i, String s) {
// 获取回话失败
}
});
}

// 3. 在收到其他用户的白板信令时,将信令透传给白板
// 注意: 自己操作触发的信令,不需要再同步给本人
mBoard.addSyncData(data);
Windows
以下代码为演示代码,最新 TIM 相关接口请参考 TIM V2 创建自定义消息TIM V2 消息发送TIM V2 消息回调,按以下步骤进行接入。
// 引入IM SDK头文件
#include "TIMCloud.h"

// 这里为了演示方便,使用ostringstream来构造JSON串,生产环境建议使用第三方JSON库来生成JSON串
#include <iostream>
#include <sstream>
#include <string>


// 1. 将 TEduBoardInitParam 的 timSync 参数初始为 NO (关闭互动白板内置的信令通道)
TEduBoardInitParam initParam;
initParam.timSync = false; // 关闭互动白板内置的信令通道(一定需要关闭,否则会收不到onTEBSyncData回调)
boardCtrl->Init(authParam, ROOM_ID, initParam); // 使用上面构造的初始化参数

// 2. 监听白板信令回调 onTEBSyncData,将信令发送给其他白板用户
virtual void onTEBSyncData(const char * data) override {
//使用自定义信令通道,发送 data 给其他白板用户
std::string message = data;
std::ostringstream json;
json << "{";
json << "\\"" << kTIMMsgElemArray << "\\":";
json << "[{";
json << "\\"" << kTIMMsgPriority << "\\": " << kTIMMsgPriority_High << ","; // 设置消息优先级为高
json << "\\"" << kTIMElemType << "\\": " << kTIMElem_Custom << ","; // 消息类型为自定义消息
json << "\\"" << kTIMCustomElemExt << "\\": \\"TXWhiteBoardExt\\","; // 扩展字段信息
json << "\\"" << kTIMCustomElemData << "\\": \\"" << message << "\\","; // 消息内容为白板数据
json << "}]";
json << "}";
int ret = TIMMsgSendNewMsg("课堂id", kTIMConv_Group, json.str().c_str(), [](int32_t code, const char *desc, const char *json_param, const void *user_data) {
if (ERR_SUCC == code) { // 消息发送成功
//信令发送成功后调用 addAckData(data),确认数据发送状态
} else { // 消息发送失败,建议进行重试
}
}, nullptr);
if (ERR_SUCC != ret) { // 消息发送失败,建议进行重试

}
}

// 3. 在收到其他用户的白板信令时,将信令透传给白板
// 注意: 自己操作触发的信令,不需要再同步给本人
boardCtrl->AddSyncData(data);
Web
以下代码为演示代码,最新 TIM 相关接口请参考 TIM 创建自定义消息TIM 消息发送TIM 消息回调,按以下步骤进行接入。
// Web没有内置TIM通道,不需要额外关闭内置TIM通道。
// 1. 在 onTEBSyncData 回调里,将数据发送给其他白板用户
teduBoard.on(TEduBoard.EVENT.TEB_SYNCDATA, data => {
const message = tim.createCustomMessage({
to: '课堂ID',
conversationType: TIM.TYPES.CONV_GROUP,
priority: TIM.TYPES.MSG_PRIORITY_HIGH, // 因为im消息有限频,白板消息的优先级调整为最高
payload: {
data: JSON.stringify(data),
description: '',
extension: 'TXWhiteBoardExt',
},
});
// 发送消息
tim.sendMessage(message).then(() => {
// 发送成功
//信令发送成功后调用 addAckData(data),确认数据发送状态
}, (error) => {
// 发送失败,建议进行重试
});
});
// 2. 监听im的消息接收事件,在收到其他用户的白板信令时,将信令透传给白板(addSyncData)
// 注意: 自己操作触发的信令,不需要再同步给本人;以下代码this.im,this.userId,teduBoard请以实际的业务变量为准
this.tim.on(TIM.EVENT.MESSAGE_RECEIVED, (event) => {
  const messages = event.data;
  const groupId = String(this.classInfo.classId);
  messages.forEach((message) => {
    // 群组消息
    if (message.conversationType === TIM.TYPES.CONV_GROUP) {
      if (message.to === groupId) { // 如果是当前群组
        const elements = message.getElements();
        if (elements.length) {
          elements.forEach(async (element) => {
            if (element.type === 'TIMCustomElem') { // 自定义消息
              if (element.content.extension === 'TXWhiteBoardExt') { // 是白板的自定义消息
                if (message.from != this.userId) { // 并且发消息的人不是自己
// 将白板信令设置给白板
                  teduBoard.addSyncData(data);
                }
              }
            }
          });
        }
      } else {
        // 其他群组消息自行处理,在互动白板的场景中可以忽略其他群组的消息
      }
    } else if (message.conversationType === TIM.TYPES.CONV_C2C) { // C2C消息
      // c2c消息在互动白板的场景中可以直接忽略
    }
  });
});