Flutter IM SDK 从 5.2.4 版本开始,需要替换升级为新版 SDK(rongcloud_im_wrapper_plugin)。已集成旧版 SDK 的客户应遵照开发者文档 SDK 变更说明尽快迁移到新版 SDK。
针对旧版 SDK 无法直接替换的部分功能,在本知识库中进行了说明。
如何支持旧版本自定义消息
新版 SDK(rongcloud_im_wrapper_plugin)重新设计了自定义消息类型的实现方式。
如果您已经升级为 rongcloud_im_wrapper_plugin
,但需要兼容旧版自定义消息,您需要在项目的 Dart 层、Android 层、iOS 层分别进行处理。
注意:需要编写原生层代码, 仅处理 Dart 层是无法支持自定义消息的!
详细代码可参考 example
Dart 层处理
-
首先需要开发者根据自己的自定义消息定义 Dart 层消息内容,代码参考
example/lib/custom_message/poke_message.dart
导入头文件
import 'package:rongcloud_im_wrapper_plugin/rongcloud_im_wrapper_plugin.dart'; import 'dart:convert' as json_lib show json;
定义消息类
-
开发者的自定义消息类需要继承
RCIMIWUserCustomMessage
-
开发者需要定义 fromJson 的构造函数,并调用 super.fromJson
RCIMDPokeMessage.fromJson(Map<String, dynamic> json) : super.fromJson(json);
-
开发者定义自己的构造方法, 需要调用父类的 RCIMIWUserCustomMessage(RCIMIWConversationType type, String targetId)
RCIMDPokeMessage(RCIMIWConversationType type, String targetId, this.pokeMessage) : super(type, targetId);
-
开发者需要实现父类的 decode/encode 方法
@override void decode(String jsonStr) { Map map = json_lib.json.decode(jsonStr.toString()); // 获取的 key 值要与原生传递的 key 值一样 pokeMessage = map['content']; } @override String encode() { Map map = {}; // 传递的 key 值要与原生传递的 key 值一样 map['content'] = pokeMessage; return json_lib.json.encode(map); }
-
开发者需要实现父类的 messageObjectName 来返回 objectName。注意:objectName 值要与原生完全一致
@override String messageObjectName() { return "ST:PokeMsg"; }
-
开发者需要实现父类的 toJson 方法,创建一个 Map 对象,并给设置 ‘content’ 的 value 值为 encode 方法的返回值。
final Map<String, dynamic> json = super.toJson(); // 此处 'content' 不可修改 json['content'] = encode(); return json;
-
-
注册自定义消息
调用引擎的 registerCustomMessage 方法进行注册,注册参考下面代码,只需要修改 objectName 和自定义消息类即可。
e.registerCustomMessage('ST:PokeMsg', (json){ RCIMDPokeMessage pokeMsg = RCIMDPokeMessage.fromJson(json); // 此处 'content' 不可修改 pokeMsg.decode(json['content']); return pokeMsg; });
Android 层处理
-
开发者需要在项目工程中引入融云原生 SDK,且 SDK 版本需要和Flutter SDK中引入的版本号一致。具体版本号可以在 android/build.gradle 中进行查看。
-
将原生的自定义消息文件放入工程中,并在
MainActivity
进行注册,确保注册放在 dart 层 init 之前。import cn.rongcloud.im.wrapper.flutter.RCIMWrapperEngine;
List<Class<? extends MessageContent>> list = new ArrayList<>(); list.add(PokeMessage.class); RCIMWrapperEngine.getInstance().messageContentClassList = list;
iOS 层处理
-
引入头文件
#import <rongcloud_im_wrapper_plugin/RCIMWrapperEngine.h>
-
将原生的自定义消息导入到 iOS 工程中,并在
AppDelegate
中进行注册,确保注册放在 dart 层 init 之前。NSMutableArray *marr = [NSMutableArray arrayWithObject:[RCDPokeMessage class]]; [RCIMWrapperEngine sharedInstance].messageContentClassList = marr.copy;
如何实现旧版的 conversationDigest 功能
因为新版本自定义消息优化后,不再需要开发者在原生层进行处理,为避免开发者在自定义消息上更好的进行扩展功能,所以 conversationDigest 功能需要开发者自己来进行定义处理。 逻辑参考如下:
开发者封装一个 conversationDigest 的方法,根据传入的message来返回不同情况下的摘要内容
示例代码如下
String conversationDigest(RCIMIWMessage message) {
switch (message.messageType) {
case RCIMIWMessageType.text:
return "text";
case RCIMIWMessageType.voice:
return "[语音]";
case RCIMIWMessageType.userCustom:
return "[自定义消息]";
case RCIMIWMessageType.command:
return "[系统消息]";
break;
}
}
如何实现旧版的 onDataReceived
因为 onDataReceived 不属于 SDK 标准功能,所以新版本 SDK 不再提供此功能,开发者如需要使用可以参考旧版本 SDK 实现, 步骤如下:
-
在 Dart 插件层定义 onDataReceived 方法
///收到原生数据的回调 /// ///[data] 传递的数据内容 /// /// 如果传送的是push内容 建议在 main.dart 使用 static Function(Map? data)? onDataReceived;
-
在 setMethodCallHandler 中处理channel回调
static void _addNativeMethodCallHandler() { _channel.setMethodCallHandler(_methodCallHandler); } static Future<dynamic> _methodCallHandler(MethodCall call) async { switch (call.method) { case "SendDataToFlutterCallBack": if (onDataReceived != null) { Map? map = call.arguments; onDataReceived!(map); } break; } }
-
ios/android 层调用方法。
// 可通过该接口向Flutter传递数据 public void sendDataToFlutter(final Map map) { if (map == null) { return; } RCLog.i("sendDataToFlutter start param:" + map.toString()); mMainHandler.post(new Runnable() { @Override public void run() { mChannel.invokeMethod("SendDataToFlutterCallBack", map); } }); }
- (void)sendDataToFlutter:(NSDictionary *)userInfo { NSString *LOG_TAG = @"sendDataToFlutter"; [RCLog i:[NSString stringWithFormat:@"%@,start param:%@",LOG_TAG,userInfo]]; [self.channel invokeMethod:@"SendDataToFlutterCallBack" arguments:userInfo]; }