How to send command and command notification messages in Flutter SDK (RCIMIWMessageType.command and RCIMIWMessageType.commandNotification)

Description

Starting with Flutter 5.4.0, you can’t create or send RCIMIWCommandMessage (command message) and RCIMIWCommandNotificationMessage (command notification message) types.

Analysis

The Flutter SDK doesn’t currently provide a create method for command messages (RCIMIWCommandMessage) and command notification messages (RCIMIWCommandNotificationMessage). To send these messages from the client, you’ll need to define a wrapper class in the Flutter layer. This approach is supported only in version 5.4.0 and above.

Follow the steps below for implementation.

Solution

Create a command message
  1. Define the message in the Flutter layer by creating wrapper_command_message.dart.

    import 'package:rongcloud_im_wrapper_plugin/rongcloud_im_wrapper_plugin.dart';
    import 'dart:convert' as json_lib show json;
    
    // Custom messages must extend RCIMIWUserCustomMessage
    class RCIMDCommandMessage extends RCIMIWUserCustomMessage {
      String? name;
      String? data;
      // 1. Define your constructor, calling the parent class RCIMIWUserCustomMessage(RCIMIWConversationType type, String targetId)
      RCIMDCommandMessage(RCIMIWConversationType type, String targetId, this.name, this.data) : super(type, targetId);
    
      // 2. Inherit the parent class constructor
      RCIMDCommandMessage.fromJson(Map<String, dynamic> json) : super.fromJson(json);
    
      // 3. Implement the parent class's decode/encode/messageObjectName
      @override
      void decode(String jsonStr) {
        Map map = json_lib.json.decode(jsonStr.toString());
        // The key must match the one passed from the native layer
        name = map['name'];
        name = map['data'];
      }
    
      @override
      String encode() {
        Map map = {};
        // The key must match the one passed to the native layer
        map['name'] = name;
        map['data'] = data;
        return json_lib.json.encode(map);
      }
    
      @override
      String messageObjectName() {
        return "RC:CmdMsg";
      }
    
      // 4. Implement the parent class's toJson
      @override
      Map<String, dynamic> toJson() {
        final Map<String, dynamic> json = super.toJson();
        // 'content' must not be modified
        json['content'] = encode();
        return json;
      }
    }
    
  2. Register the message in the native layer.

    iOS: xxxx/ios/Runner/AppDelegate.m

    - (BOOL)application:(UIApplication *)application
        didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        [GeneratedPluginRegistrant registerWithRegistry:self];
        NSMutableArray *marr = [NSMutableArray arrayWithObjects:[RCDPokeMessage class], [RCCommandMessage class], nil];
        [RCIMWrapperEngine sharedInstance].messageContentClassList = marr.copy;
        ...
    }
    

    Android: example/android/app/src/main/java/cn/rongcloud/im/wrapper/flutter/example/MainActivity.java

    public class MainActivity extends FlutterActivity {
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            List<Class<? extends MessageContent>> list = new ArrayList<>();
            list.add(PokeMessage.class);
            list.add(CommandMessage.class);
            RCIMWrapperEngine.getInstance().messageContentClassList = list;
    
        }
    }
    
Send a command message
  RCIMDCommandMessage msg = RCIMDCommandMessage(type, targetId, "name", "data");
  _sendMessage(msg, useCallback);

Both received and successfully sent messages will be processed as RCIMIWCommandMessage. For other use cases like receiving messages, simply handle RCIMIWCommandMessage.

If you have any questions, feel free to submit a ticket.