功能描述
通过 addSimpleMsgListener
监听接收文本、自定义消息,相关回调在 V2TIMSimpleMsgListener
协议中定义。
通过 addAdvancedMsgListener
监听接收所有类型消息(文本、自定义、富媒体消息),相关回调在 V2TIMAdvancedMsgListener
协议中定义。
设置消息监听器
SDK 提供了 2 种消息监听器,简单消息监听器 V2TIMSimpleMsgListener
和高级消息监听器 V2TIMAdvancedMsgListener
。
两者的区别在于:
1. 简单消息监听器只能接收文本、自定义消息。如果您的业务只需要这两种消息,可以仅使用简单消息监听器。
2. 高级消息监听器可以接收所有类型的消息。如果您的业务还需要支持富媒体、合并消息等其他类型,请使用高级消息监听器。
注意
1. addSimpleMsgListener
和 addAdvancedMsgListener
请使用其中之一,切勿混用,以免产生不可预知的逻辑 bug。
2. 如果想要正常接收下面各种类型的消息,必须先添加消息监听器,否则无法正常接收。
简单消息监听器
添加监听器
接收方调用 addSimpleMsgListener
(Java / Swift / Objective-C / C++) 添加简单消息监听器。一般建议在比较靠前的时间点调用,例如聊天消息界面初始化后,确保 App 能及时收到消息。 示例代码如下:
V2TIMManager.getInstance().addSimpleMsgListener(simpleMsgListener);
V2TIMManager.shared.addSimpleMsgListener(listener: self)
[[V2TIMManager sharedInstance] addSimpleMsgListener:self];
class SimpleMsgListener final : public V2TIMSimpleMsgListener {
};
SimpleMsgListener simpleMsgListener;
V2TIMManager::GetInstance()->AddSimpleMsgListener(&simpleMsgListener);
监听器回调事件
public abstract class V2TIMSimpleMsgListener {
public void onRecvC2CTextMessage(String msgID, V2TIMUserInfo sender, String text) {}
public void onRecvC2CCustomMessage(String msgID, V2TIMUserInfo sender, byte[] customData) {}
public void onRecvGroupTextMessage(String msgID, String groupID, V2TIMGroupMemberInfo sender, String text) {}
public void onRecvGroupCustomMessage(String msgID, String groupID, V2TIMGroupMemberInfo sender, byte[] customData) {}
}
public protocol V2TIMSimpleMsgListener : AnyObject {
func onRecvC2CTextMessage(msgID: String, sender: V2TIMUserInfo, text: String?)
func onRecvC2CCustomMessage(msgID: String, sender: V2TIMUserInfo, customData: Data?)
func onRecvGroupTextMessage(msgID: String, groupID: String, sender: V2TIMGroupMemberInfo, text: String?)
func onRecvGroupCustomMessage(msgID: String, groupID: String, sender: V2TIMGroupMemberInfo, customData: Data?)
}
@protocol V2TIMSimpleMsgListener <NSObject>
@optional
- (void)onRecvC2CTextMessage:(NSString *)msgID sender:(V2TIMUserInfo *)info text:(NSString *)text;
- (void)onRecvC2CCustomMessage:(NSString *)msgID sender:(V2TIMUserInfo *)info customData:(NSData *)data;
- (void)onRecvGroupTextMessage:(NSString *)msgID groupID:(NSString *)groupID sender:(V2TIMGroupMemberInfo *)info text:(NSString *)text;
- (void)onRecvGroupCustomMessage:(NSString *)msgID groupID:(NSString *)groupID sender:(V2TIMGroupMemberInfo *)info customData:(NSData *)data;
@end
class SimpleMsgListener final : public V2TIMSimpleMsgListener {
public:
SimpleMsgListener() = default;
~SimpleMsgListener() override = default;
void OnRecvC2CTextMessage(const V2TIMString& msgID, const V2TIMUserFullInfo& sender,
const V2TIMString& text) override {}
void OnRecvC2CCustomMessage(const V2TIMString& msgID, const V2TIMUserFullInfo& sender,
const V2TIMBuffer& customData) override {}
void OnRecvGroupTextMessage(const V2TIMString& msgID, const V2TIMString& groupID,
const V2TIMGroupMemberFullInfo& sender, const V2TIMString& text) override {}
void OnRecvGroupCustomMessage(const V2TIMString& msgID, const V2TIMString& groupID,
const V2TIMGroupMemberFullInfo& sender,
const V2TIMBuffer& customData) override {}
};
移除监听器
示例代码如下:
V2TIMManager.getInstance().removeSimpleMsgListener(simpleMsgListener);
V2TIMManager.shared.removeSimpleMsgListener(listener: self)
[[V2TIMManager sharedInstance] removeSimpleMsgListener:self];
class SimpleMsgListener final : public V2TIMSimpleMsgListener {
};
V2TIMManager::GetInstance()->RemoveSimpleMsgListener(&simpleMsgListener);
高级消息监听器
添加监听器
接收方调用 addAdvancedMsgListener
(Java / Swift / Objective-C / C++) 添加高级消息监听器。一般建议在比较靠前的时间点调用,例如例如聊天消息界面初始化后,确保 App 能及时收到消息。 示例代码如下:
V2TIMManager.getMessageManager().addAdvancedMsgListener(advancedMsgListener);
V2TIMManager.shared.addAdvancedMsgListener(listener: self)
[[V2TIMManager sharedInstance] addAdvancedMsgListener:self];
class AdvancedMsgListener final : public V2TIMAdvancedMsgListener {
};
AdvancedMsgListener advancedMsgListener;
V2TIMManager::GetInstance()->GetMessageManager()->AddAdvancedMsgListener(&advancedMsgListener);
监听器回调事件
public abstract class V2TIMAdvancedMsgListener {
public void onRecvNewMessage(V2TIMMessage msg) {}
public void onRecvC2CReadReceipt(List<V2TIMMessageReceipt> receiptList) {}
public void onRecvMessageReadReceipts(List<V2TIMMessageReceipt> receiptList) {}
public void onRecvMessageRevoked(String msgID) {}
public void onRecvMessageModified(V2TIMMessage msg) {}
}
public protocol V2TIMAdvancedMsgListener: AnyObject {
func onRecvNewMessage(msg: V2TIMMessage)
func onRecvMessageReadReceipts(receiptList: Array<V2TIMMessageReceipt>)
func onRecvC2CReadReceipt(receiptList: Array<V2TIMMessageReceipt>)
func onRecvMessageRevoked(msgID: String, operateUser: V2TIMUserInfo, reason: String?)
func onRecvMessageModified(msg: V2TIMMessage)
}
@protocol V2TIMAdvancedMsgListener <NSObject>
@optional
- (void)onRecvNewMessage:(V2TIMMessage *)msg;
- (void)onRecvMessageReadReceipts:(NSArray<V2TIMMessageReceipt *> *)receiptList;
- (void)onRecvC2CReadReceipt:(NSArray<V2TIMMessageReceipt *> *)receiptList;
- (void)onRecvMessageRevoked:(NSString *)msgID;
- (void)onRecvMessageModified:(V2TIMMessage *)msg;
@end
class AdvancedMsgListener final : public V2TIMAdvancedMsgListener {
public:
AdvancedMsgListener() = default;
~AdvancedMsgListener() override = default;
void OnRecvNewMessage(const V2TIMMessage& message) override {}
void OnRecvC2CReadReceipt(const V2TIMMessageReceiptVector& receiptList) override {}
void OnRecvMessageReadReceipts(const V2TIMMessageReceiptVector& receiptList) override {}
void OnRecvMessageRevoked(const V2TIMString& messageID) override {}
void OnRecvMessageModified(const V2TIMMessage& message) override {}
};
移除监听器
示例代码如下:
V2TIMManager.getMessageManager().removeAdvancedMsgListener(advancedMsgListener);
V2TIMManager.shared.removeAdvancedMsgListener(listener: self)
[[V2TIMManager sharedInstance] removeAdvancedMsgListener:self];
class AdvancedMsgListener final : public V2TIMAdvancedMsgListener {
};
V2TIMManager::GetInstance()->GetMessageManager()->RemoveAdvancedMsgListener(&advancedMsgListener);
接收文本消息
使用简单消息监听器接收
单聊文本消息
接收方使用简单消息监听器接收单聊文本消息,需要以下几步:
1. 调用 addSimpleMsgListener
设置事件监听器。
3. 希望停止接收消息,调用 removeSimpleMsgListener
移除监听。该步骤不是必须的,客户可以按照业务需求调用。
代码示例如下:
V2TIMManager.getInstance().addSimpleMsgListener(simpleMsgListener);
public void onRecvC2CTextMessage(String msgID, V2TIMUserInfo sender, String text) {
}
V2TIMManager.shared.addSimpleMsgListener(listener: self)
func onRecvC2CTextMessage(msgID: String, sender: V2TIMUserInfo, text: String?) {
}
[[V2TIMManager sharedInstance] addSimpleMsgListener:self];
- (void)onRecvC2CTextMessage:(NSString *)msgID sender:(V2TIMUserInfo *)info text:(NSString *)text {
}
class SimpleMsgListener final : public V2TIMSimpleMsgListener {
public:
void OnRecvC2CTextMessage(const V2TIMString& msgID, const V2TIMUserFullInfo& sender,
const V2TIMString& text) override {
std::cout << "text:" << std::string{text.CString(), text.Size()} << std::endl;
}
};
SimpleMsgListener simpleMsgListener;
V2TIMManager::GetInstance()->AddSimpleMsgListener(&simpleMsgListener);
群聊文本消息
接收方使用简单消息监听器接收群聊文本消息,需要以下几步:
1. 调用 addSimpleMsgListener
设置事件监听器。
3. 希望停止接收消息,调用 removeSimpleMsgListener
移除监听。该步骤不是必须的,客户可以按照业务需求调用。
代码示例如下:
V2TIMManager.getInstance().addSimpleMsgListener(simpleMsgListener);
public void onRecvGroupTextMessage(String msgID, String groupID, V2TIMGroupMemberInfo sender, String text) {
}
V2TIMManager.shared.addSimpleMsgListener(listener: self)
func onRecvGroupTextMessage(msgID: String, groupID: String, sender: V2TIMGroupMemberInfo, text:String?
{
}
[[V2TIMManager sharedInstance] addSimpleMsgListener:self];
- (void)onRecvGroupTextMessage:(NSString *)msgID groupID:(NSString *)groupID sender:(V2TIMGroupMemberInfo *)info text:(NSString *)text {
}
class SimpleMsgListener final : public V2TIMSimpleMsgListener {
public:
void OnRecvGroupTextMessage(const V2TIMString& msgID, const V2TIMString& groupID,
const V2TIMGroupMemberFullInfo& sender, const V2TIMString& text) override {
std::cout << "text:" << std::string{text.CString(), text.Size()} << std::endl;
}
};
SimpleMsgListener simpleMsgListener;
V2TIMManager::GetInstance()->AddSimpleMsgListener(&simpleMsgListener);
使用高级消息监听器接收
接收方使用高级消息监听器接收单聊、群聊文本消息,需要以下几步:
1. 调用 addAdvancedMsgListener
设置事件监听器。
3. 希望停止接收消息,调用 removeAdvancedMsgListener
移除监听。该步骤不是必须的,客户可以按照业务需求调用。
代码示例如下:
V2TIMManager.getMessageManager().addAdvancedMsgListener(advancedMsgListener);
public void onRecvNewMessage(V2TIMMessage msg) {
String groupID = msg.getGroupID();
String userID = msg.getUserID();
if (msg.getElemType() == V2TIMMessage.V2TIM_ELEM_TYPE_TEXT) {
V2TIMTextElem textElem = msg.getTextElem();
String text = textElem.getText();
Log.i("onRecvNewMessage", "text:" + text);
}
}
V2TIMManager.shared.addAdvancedMsgListener(listener: self)
func onRecvNewMessage(_ msg: V2TIMMessage) {
let groupID = msg.groupID
let userID = msg.userID
if !groupID.isEmpty {
print("Received a group message in group: \\(groupID)")
} else if !userID.isEmpty {
print("Received a one-on-one message from user: \\(userID)")
} else {
print("Received a message with no identifiable sender.")
}
if msg.elemType == .V2TIM_ELEM_TYPE_TEXT {
if let textElem = msg.textElem {
let text = textElem.text
print("onRecvNewMessage, text: \\(text)")
}
} else {
print("Received a non-text message.")
}
}
[[V2TIMManager sharedInstance] addAdvancedMsgListener:self];
- (void)onRecvNewMessage:(V2TIMMessage *)msg {
NSString *groupID = msg.groupID;
NSString *userID = msg.userID;
if (msg.elemType == V2TIM_ELEM_TYPE_TEXT) {
V2TIMTextElem *textElem = msg.textElem;
NSString *text = textElem.text;
NSLog(@"onRecvNewMessage, text: %@", text);
}
}
class AdvancedMsgListener final : public V2TIMAdvancedMsgListener {
public:
void OnRecvNewMessage(const V2TIMMessage& message) override {
V2TIMString groupID = message.groupID;
V2TIMString userID = message.userID;
if (message.elemList.Size() == 1) {
V2TIMElem* elem = message.elemList[0];
if (elem->elemType == V2TIMElemType::V2TIM_ELEM_TYPE_TEXT) {
auto textElem = static_cast<V2TIMTextElem*>(elem);
V2TIMString text = textElem->text;
std::cout << "text:" << std::string{text.CString(), text.Size()} << std::endl;
}
}
}
};
AdvancedMsgListener advancedMsgListener;
V2TIMManager::GetInstance()->GetMessageManager()->AddAdvancedMsgListener(&advancedMsgListener);
接收自定义消息
使用简单消息监听器接收
单聊自定义消息
接收方使用简单消息监听器接收单聊自定义消息,需要以下几步:
1. 调用 addSimpleMsgListener
设置事件监听器。
3. 希望停止接收消息,调用 removeSimpleMsgListener
移除监听。该步骤不是必须的,客户可以按照业务需求调用。
代码示例如下:
public void onRecvC2CCustomMessage(String msgID, V2TIMUserInfo sender, byte[] customData) {
Log.i("onRecvC2CCustomMessage", "msgID:" + msgID + ", from:" + sender.getNickName() + ", content:" + new String(customData));
}
func onRecvC2CCustomMessage(msgID: String, sender: V2TIMUserInfo, customData: Data?) {
}
- (void)onRecvC2CCustomMessage:(NSString *)msgID sender:(V2TIMUserInfo *)info customData:(NSData *)data {
NSLog(@"onRecvC2CCustomMessage, msgID: %@, sender: %@, customData: %@", msgID, info, data);
}
class SimpleMsgListener final : public V2TIMSimpleMsgListener {
public:
void OnRecvC2CCustomMessage(const V2TIMString& msgID, const V2TIMUserFullInfo& sender,
const V2TIMBuffer& customData) override {
std::cout << "customData:"
<< std::string{reinterpret_cast<const char*>(customData.Data()), customData.Size()}
<< std::endl;
}
};
SimpleMsgListener simpleMsgListener;
V2TIMManager::GetInstance()->AddSimpleMsgListener(&simpleMsgListener);
群聊自定义消息
接收方使用简单消息监听器接收群聊自定义消息,需要以下几步:
1. 调用 addSimpleMsgListener
设置事件监听器。
3. 希望停止接收消息,调用 removeSimpleMsgListener
移除监听。该步骤不是必须的,客户可以按照业务需求调用。
public void onRecvGroupCustomMessage(String msgID, String groupID, V2TIMGroupMemberInfo sender, byte[] customData) {
Log.i("onRecvGroupCustomMessage", "msgID:" + msgID + ", groupID:" + groupID + ", from:" + sender.getNickName() + ", content:" + new String(customData));
}
func onRecvGroupCustomMessage(msgID: String, groupID: String, sender: V2TIMGroupMemberInfo, customData: Data?) {
}
- (void)onRecvGroupCustomMessage:(NSString *)msgID groupID:(NSString *)groupID sender:(V2TIMGroupMemberInfo *)info customData:(NSData *)data {
NSLog(@"onRecvGroupCustomMessage, msgID: %@, groupID: %@, sender: %@, customData: %@", msgID, groupID, info, data);
}
class SimpleMsgListener final : public V2TIMSimpleMsgListener {
public:
void OnRecvGroupCustomMessage(const V2TIMString& msgID, const V2TIMString& groupID,
const V2TIMGroupMemberFullInfo& sender,
const V2TIMBuffer& customData) override {
std::cout << "customData:"
<< std::string{reinterpret_cast<const char*>(customData.Data()), customData.Size()}
<< std::endl;
}
};
SimpleMsgListener simpleMsgListener;
V2TIMManager::GetInstance()->AddSimpleMsgListener(&simpleMsgListener);
使用高级消息监听器接收
接收方使用高级消息监听器接收单聊、群聊自定义消息,需要以下几步:
1. 调用 addAdvancedMsgListener
设置事件监听器。
3. 希望停止接收消息,调用 removeAdvancedMsgListener
移除监听。该步骤不是必须的,客户可以按照业务需求调用。
代码示例如下:
V2TIMManager.getMessageManager().addAdvancedMsgListener(v2TIMAdvancedMsgListener);
public void onRecvNewMessage(V2TIMMessage msg) {
String groupID = msg.getGroupID();
String userID = msg.getUserID();
if (msg.getElemType() == V2TIMMessage.V2TIM_ELEM_TYPE_CUSTOM) {
V2TIMCustomElem customElem = msg.getCustomElem();
String data = new String(customElem.getData());
Log.i("onRecvNewMessage", "customData:" + data);
}
}
V2TIMManager.shared.addAdvancedMsgListener(listener: self)
func onRecvNewMessage(_ msg: V2TIMMessage) {
let groupID = msg.groupID
let userID = msg.userID
if !groupID.isEmpty {
print("Received a group message in group: \\(groupID)")
} else if !userID.isEmpty {
print("Received a one-on-one message from user: \\(userID)")
} else {
print("Received a message with no identifiable sender.")
}
if msg.elemType == .V2TIM_ELEM_TYPE_TEXT {
if let textElem = msg.textElem {
let text = textElem.text
print("onRecvNewMessage, text: \\(text)")
}
} else {
print("Received a non-text message.")
}
}
[[V2TIMManager sharedInstance] addAdvancedMsgListener:self];
- (void)onRecvNewMessage:(V2TIMMessage *)msg {
NSString *groupID = msg.groupID;
NSString *userID = msg.userID;
if (msg.elemType == V2TIM_ELEM_TYPE_CUSTOM) {
V2TIMCustomElem *customElem = msg.customElem;
NSData *customData = customElem.data;
NSLog(@"onRecvNewMessage, customData: %@", customData);
}
}
class AdvancedMsgListener final : public V2TIMAdvancedMsgListener {
public:
void OnRecvNewMessage(const V2TIMMessage& message) override {
V2TIMString groupID = message.groupID;
V2TIMString userID = message.userID;
if (message.elemList.Size() == 1) {
V2TIMElem* elem = message.elemList[0];
if (elem->elemType == V2TIMElemType::V2TIM_ELEM_TYPE_CUSTOM) {
auto customElem = static_cast<V2TIMCustomElem*>(elem);
V2TIMBuffer data = customElem->data;
std::cout << "data:"
<< std::string{reinterpret_cast<const char*>(data.Data()), data.Size()}
<< std::endl;
}
}
}
};
AdvancedMsgListener advancedMsgListener;
V2TIMManager::GetInstance()->GetMessageManager()->AddAdvancedMsgListener(&advancedMsgListener);
接收富媒体消息
接收富媒体消息只能使用高级消息监听器,需要以下几步:
1. 接收方调用 addAdvancedMsgListener
接口设置高级消息监听。
3. 接收方解析 V2TIMMessage
消息中的 elemType
属性,并根据其类型进行二次解析,获取消息内部 Elem 中的具体内容。
4. 希望停止接收消息,调用 removeAdvancedMsgListener
移除监听。该步骤不是必须的,客户可以按照业务需求调用。
图片消息
一个图片消息会包含三种格式大小的图片,分别为原图、大图、微缩图(SDK 会在发送图片消息的时候自动生成微缩图、大图,客户不需要关心):
大图:将原图等比压缩。压缩后宽、高中较小的一个等于 720 像素。
缩略图:将原图等比压缩。压缩后宽、高中较小的一个等于 198 像素。
为了避免重复下载,节省资源,我们推荐您将 V2TIMImage
对象的 uuid
属性值设置到图片的下载路径中,作为图片的标识。
示例代码向您演示如何从 V2TIMMessage
中解析出图片消息内容:
public void onRecvNewMessage(V2TIMMessage msg) {
if (msg.getElemType() == V2TIMMessage.V2TIM_ELEM_TYPE_IMAGE) {
V2TIMImageElem v2TIMImageElem = msg.getImageElem();
List<V2TIMImageElem.V2TIMImage> imageList = v2TIMImageElem.getImageList();
for (V2TIMImageElem.V2TIMImage v2TIMImage : imageList) {
String uuid = v2TIMImage.getUUID();
int imageType = v2TIMImage.getType();
int size = v2TIMImage.getSize();
int width = v2TIMImage.getWidth();
int height = v2TIMImage.getHeight();
String url = v2TIMImage.getUrl();
String imagePath = "/sdcard/im/image/" + "myUserID" + uuid;
File imageFile = new File(imagePath);
if (!imageFile.exists()) {
v2TIMImage.downloadImage(imagePath, new V2TIMDownloadCallback() {
@Override
public void onProgress(V2TIMElem.V2ProgressInfo progressInfo) {
}
@Override
public void onError(int code, String desc) {
}
@Override
public void onSuccess() {
}
});
} else {
}
}
}
}
func onRecvNewMessage(_ msg: V2TIMMessage) {
if msg.elemType == .V2TIM_ELEM_TYPE_IMAGE {
guard let imageElem = msg.imageElem else { return }
let imageList = imageElem.imageList
for timImage in imageList {
let uuid = timImage.uuid
let type = timImage.type
let size = timImage.size
let width = timImage.width
let height = timImage.height
let url = timImage.url
let imagePath = NSTemporaryDirectory().appending("testImage\\(timImage.uuid)")
if !FileManager.default.fileExists(atPath: imagePath) {
timImage.downloadImage(path: imagePath, progress: { curSize, totalSize in
print("下载图片进度:curSize:\\(curSize), totalSize: \\(totalSize)")
}, succ: {
print("下载图片完成")
}, fail: { code, msg in
print("下载图片失败:code:\\(code), msg: \\(msg)")
})
} else {
print("图片已存在:\\(imagePath)")
}
print("图片信息:uuid: \\(uuid), type: \\(type.rawValue), size: \\(size), width: \\(width), height: \\(height)")
}
}
}
- (void)onRecvNewMessage:(V2TIMMessage *)msg {
if (msg.elemType == V2TIM_ELEM_TYPE_IMAGE) {
V2TIMImageElem *imageElem = msg.imageElem;
NSArray<V2TIMImage *> *imageList = imageElem.imageList;
for (V2TIMImage *timImage in imageList) {
NSString *uuid = timImage.uuid;
V2TIMImageType type = timImage.type;
int size = timImage.size;
int width = timImage.width;
int height = timImage.height;
NSString * url = timImage.url;
NSString *imagePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat: @"testImage%@", timImage.uuid]];
if (![[NSFileManager defaultManager] fileExistsAtPath:imagePath]) {
[timImage downloadImage:imagePath progress:^(NSInteger curSize, NSInteger totalSize) {
NSLog(@"下载图片进度:curSize:%lu,totalSize:%lu",curSize,totalSize);
} succ:^{
NSLog(@"下载图片完成");
} fail:^(int code, NSString *msg) {
NSLog(@"下载图片失败:code:%d,msg:%@",code,msg);
}];
} else {
}
NSLog(@"图片信息:uuid:%@, type:%ld, size:%d, width:%d, height:%d", uuid, (long)type, size, width, height);
}
}
}
class DownloadCallback final : public V2TIMDownloadCallback {
public:
using SuccessCallback = std::function<void()>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;
using DownLoadProgressCallback = std::function<void(uint64_t, uint64_t)>;
DownloadCallback