一、配置
1. 导入第三方
rongcloud_im_plugin: ^5.1.3
2. 初始化融云
token为融云唯一识别标志,用shared_preferences存到本地
initRongIM() async {RongIMClient.init(rongIMKey);SharedPreferences prefs = await SharedPreferences.getInstance();///融云初登录-""传tokenRongIMClient.connect(prefs.getString("token")!, (int? code, String? userId) {if (code == 0) {print("融云登录ID" + userId!);// 连接成功后打开数据库// _initUserInfoCache();} else if(code == 31004) {toastShow("需要重新从 APP 服务获取新 token 并连接,请联系管理员");}});
}
3. 消息回调
这里使用eventBus(存放在全局变量中)进行广播,状态管理框架为GETx
根据当前是否是聊天页面来判断是否需要刷新聊天页面
/// 初始化融云消息回调
initRongIMReceive() async {SharedPreferences prefs = await SharedPreferences.getInstance();if(prefs.getString("token") != null){initRongIM();}/// 融云接收到消息时操作RongIMClient.onMessageReceived = (Message? msg,int? left) {if(Get.currentRoute == "/() => BalloonChatPage"){ /// BalloonChatPage为聊天页面路由Get.find<GlobalConfigService>().eventBus.fire(UpdateNowChat(msg!.targetId!));} else {Get.find<GlobalConfigService>().eventBus.fire(UpdateChatList(1));}};
}/// 融云接收消息通知后刷新聊天列表
class UpdateChatList{int status;UpdateChatList(this.status);
}/// 融云接收消息通知后刷新聊天页面
class UpdateNowChat{String targetId;UpdateNowChat(this.targetId);
}
有个坑:如果没有初始化融云就监听消息回调,会失败。我的处理方式是将消息回调写在main文件中,当程序运行时执行一次,当用户登录时,也执行一次。
二、使用
1. 发送消息
支持文本消息+表情消息
onRongSendMessage(content, memberId) async{RongIMClient.onConnectionStatusChange = (int? connectionStatus) {if(RCConnectionStatus.KickedByOtherClient == connectionStatus ||RCConnectionStatus.TokenIncorrect == connectionStatus ||RCConnectionStatus.UserBlocked == connectionStatus){print("失效了");initRongIM();}};TextMessage txtMessage = new TextMessage();txtMessage.content = content;await RongIMClient.sendMessage(RCConversationType.Private, memberId, txtMessage);
}
- RCConversationType.Private:单聊时固定
- memberId:发送者ID
- txtMessage:TextMessage格式文本
2. 获取本地历史消息
暂时只处理TextMessage格式消息,有时候能正确解析,有时候不能正确解析,所以我处理的返回值,只返回我需要的参数
Future<List<Map<dynamic, dynamic>>> onGetHistoryMessages(memberId, {count}) async {RongIMClient.onConnectionStatusChange = (int? connectionStatus) {if(RCConnectionStatus.KickedByOtherClient == connectionStatus ||RCConnectionStatus.TokenIncorrect == connectionStatus ||RCConnectionStatus.UserBlocked == connectionStatus){initRongIM();}};List msgs = (await RongIMClient.getHistoryMessage(RCConversationType.Private, memberId, -1, count ?? 10))!;List<Map<dynamic, dynamic>> messages = [];if(msgs.length > 0){msgs.asMap().forEach((index, m){var content = (msgs[index].content != null && msgs[index].content is TextMessage) ? msgs[index].content.content : "❕此版本暂不支持该类型消息";if(msgs[index].originContentMap?['content'] != null){content = msgs[index].originContentMap?['content'];}messages.add({"messageDirection": (msgs[index] as Message).messageDirection,"sentTime": (msgs[index] as Message).sentTime, "content": content});});}return messages;
}
(1)Param
- memberId:对方的ID
- count:单次获取的数量
(2)Response
消息实体 Message 对象列表
-
int? conversationType; //会话类型 参见 RCConversationType
-
int? conversationType; //会话类型 参见 RCConversationType
-
String? targetId; //会话 id
-
int? messageId; //messageId ,本地数据库的自增 id
-
int? messageDirection; //消息方向 参见 RCMessageDirection
-
String? senderUserId; //发送者 id
-
int? receivedStatus; //消息接收状态 参见 RCReceivedStatus
-
int? sentStatus; //消息发送状态 参见 RCSentStatus
-
int? sentTime; //发送时间,unix 时间戳,单位毫秒
-
String? objectName; //消息 objName
-
MessageContent? content; //消息内容
-
String? messageUId; //消息 UID,全网唯一 Id
-
String? extra; // 扩展信息
-
bool? canIncludeExpansion; // 消息是否可以包含扩展信息
-
Map? expansionDic; // 消息扩展信息列表
-
ReadReceiptInfo? readReceiptInfo; //阅读回执状态
-
MessageConfig? messageConfig; // 消息配置
-
MessagePushConfig? messagePushConfig; // 推送配置
-
Map? originContentMap;//如果 content 为 null ,说明消息内容本身未被 flutter 层正确解析,则消息内容会保存到该 map 中
3. 获取单个聊天未读数量
这里有个巨坑,融云方获取未读数量有个延迟,所以有时候获取的值为0,所以修改源码即可,不过有个问题就是每次换电脑拉取都要修改
Future<int> onGetUnSeeMessages(memberId) async {RongIMClient.onConnectionStatusChange = (int? connectionStatus) {if(RCConnectionStatus.KickedByOtherClient == connectionStatus ||RCConnectionStatus.TokenIncorrect == connectionStatus ||RCConnectionStatus.UserBlocked == connectionStatus){initRongIM();}};var countNow = 0;await RongIMClient.getUnreadCount(RCConversationType.Private, memberId, (int? count,int? code) {if(0 == code) {countNow = count!;return count;}});return countNow;
}
(1)Param
- memberId:对方ID
(2)Response
- count:总数
解决未读消息获取延迟BUG
/// 原来代码
static void getUnreadCount(int conversationType, String targetId,Function(int? count, int? code)? finished) async {Map map = {"conversationType": conversationType, "targetId": targetId};Map? unreadMap =await _channel.invokeMethod(RCMethodKey.GetUnreadCountTargetId, map);if (finished != null) {finished(unreadMap!["count"], unreadMap["code"]);}
}/// 修改后
static Future<int> getUnreadCount(int conversationType, String targetId,Function(int? count, int? code)? finished) async {Map map = {"conversationType": conversationType, "targetId": targetId};Map? unreadMap =await _channel.invokeMethod(RCMethodKey.GetUnreadCountTargetId, map);if (finished != null) {finished(unreadMap!["count"], unreadMap["code"]);}return 1;
}