This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

Project Address: GitHub: github.com/baiyuliang/…

Melting cloud IM – Flutter document address: docs. Rongcloud. Cn/v4/5 x/views…

Integration steps:

Note: you need to register an account on rongyun official website, create an application, and obtain the appID and AppKey of the application!

  • The introduction of the SDK:
Rongcloud_im_plugin: ^ 5.1.3Copy the code
  • Initialization:
 RongIMClient.init(Url.RONG_IM_KEY);
Copy the code
  • Connect to server:
RongIMClient.connect(token, (int code, String userId) {
  if (code == 0) {}});Copy the code
  • Set listening:
 RongIMClient.onConnectionStatusChange = (intConnectionStatus) {}; RongIMClient.onMessageReceived = (Message msg,intLeft) {};Copy the code
  • Get session list:
RongIMClient.getConversationListByPage([
      RCConversationType.Private,
      RCConversationType.Group,
      RCConversationType.System
    ], 999.0);
Copy the code
  • Send a message:
 TextMessage txtMessage = new TextMessage();
    txtMessage.content = "";
    txtMessage.extra = "";
    Message msg = await RongIMClient.sendMessage(RCConversationType.Private, targetId, txtMessage);
Copy the code

There are many types of messages, refer to the documentation for details!

Since rongyun login relies on tokens generated by the server, it is necessary to write the background for normal use, which may be impossible for developers of mobile terminal or front-end. Therefore, it is important to introduce server side Java Server DK in this project and put it into the Android project liBS. To simulate server registration and other related requests!

Here is a trick we can use to open the Flutter project and the Android part of the Flutter project, respectively, while developing both the Flutter and native ends:

Flutter:

Android:

At this point, we can complete server-side functions in the Android project, such as registration methods:

       val map = HashMap<String, Any>()
       val id = call.argument<String>("id")!!!!! .toString() val name = call.argument<String>("name")!!!!! .toString() val avatar = call.argument<String>("avatar")!!!!! .toString() val user: User = rongCloud.user val userModel = UserModel() .setId(id) .setName(name) .setPortrait(avatar) Thread {try {
               val tokenResult = user.register(userModel)
               if(! TextUtils.isEmpty(tokenResult.token)) { map["code"] = 200
                   map["token"] = tokenResult.token
                   map["error"] = "Registration successful"
                   Log.e("RongIMRegPlugin"."Registration successful: $tokenResult")}else {
                   map["code"] = -1
                   map["error"] = "Registration failed"}}catch (e: Exception) {
               e.printStackTrace()
               map["code"] = -1
               map["error"] = e.message.toString()
           }
           activity.runOnUiThread {
               result.success(map)
           }
       }.start()
Copy the code

How can FLUTTER communicate locally?

The easiest way to do this is www.baidu.com…… Ten thousand words omitted here!

Just kidding! Actually very simple, want to discover, than a gourd ladle, believe that we are in the process of development, the introduction of more or less the other third-party libraries, we can open to have a closer look at their Plugin. Java, implementation process, open a casually, thoughtSharedPreferencesEx. :

/** SharedPreferencesPlugin */
public class SharedPreferencesPlugin implements FlutterPlugin {
  private static final String CHANNEL_NAME = "plugins.flutter.io/shared_preferences";
  private MethodChannel channel;
  private MethodCallHandlerImpl handler;

  @SuppressWarnings("deprecation")
  public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registrar registrar) {
    final SharedPreferencesPlugin plugin = new SharedPreferencesPlugin();
    plugin.setupChannel(registrar.messenger(), registrar.context());
  }

  @Override
  public void onAttachedToEngine(FlutterPlugin.FlutterPluginBinding binding) {
    setupChannel(binding.getBinaryMessenger(), binding.getApplicationContext());
  }

  @Override
  public void onDetachedFromEngine(FlutterPlugin.FlutterPluginBinding binding) {
    teardownChannel();
  }

  private void setupChannel(BinaryMessenger messenger, Context context) {
    channel = new MethodChannel(messenger, CHANNEL_NAME);
    handler = new MethodCallHandlerImpl(context);
    channel.setMethodCallHandler(handler);
  }

  private void teardownChannel(a) {
    handler.teardown();
    handler = null;
    channel.setMethodCallHandler(null);
    channel = null; }}Copy the code

Obviously, the class inherits FlutterPlugin and rewrites two methods: onAttachedToEngine and onDetachedFromEngine, after getting an instance of MethodChannel:

channel = new MethodChannel(messenger, CHANNEL_NAME);
Copy the code

Implements the MethodCallHandler interface,

handler = new MethodCallHandlerImpl(context);
channel.setMethodCallHandler(handler)
Copy the code

MethodCallHandlerImpl

class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler {
  @Override
  public void onMethodCall(MethodCall call, MethodChannel.Result result) {
    String key = call.argument("key");
    try {
      switch (call.method) {
        case "setBool":
          commitAsync(preferences.edit().putBoolean(key, (boolean) call.argument("value")), result);
          break; . }Copy the code

Only part of the code has been pasted above, and the process is already clear.

  • Step 1: Create RongIMServerPlugin and inherit FlutterPlugin:
class RongIMServerPlugin() : FlutterPlugin{

    override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {}override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {}}Copy the code
  • Step 2: Get a MethodChannel instance:
private var channel: MethodChannel? = null

override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
     channel = MethodChannel(binding.binaryMessenger, "rongim/server")}Copy the code

Note that the name of a channel can be customized. I defined it as **”rongim/server”**. The flutter should be invoked the same way!

  • Step 3: implement MethodChannel. MethodCallHandler interface:
class RongIMServerPlugin() : FlutterPlugin.MethodChannel.MethodCallHandler {

    private var channel: MethodChannel? = null

    override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        channel = MethodChannel(binding.binaryMessenger, "rongim/server") channel!! .setMethodCallHandler(this)}override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { channel!! .setMethodCallHandler(null)
        channel = null
    }

    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {}}Copy the code

You don’t have to write a separate MethodCallHandlerImpl class like you do in SharedPreferences, We can implement setMethodCallHandler(this) directly in the main class just like we did with View.onClickListener!

  • OnMethodCall (); call. Method ();
    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
        when (call.method) {
            "register" -> {
              
            }
            "user"-> {}}}Copy the code

If the context context is needed in the method, we can introduce it in the constructor:

class RongIMServerPlugin(activity: Activity) : FlutterPlugin{
      private var activity: Activity = activity
}
Copy the code

After the Plugin is written, register in MainActivity:

class MainActivity: FlutterActivity(a){
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState) flutterEngine!! .plugins.add(RongIMServerPlugin(this))}}Copy the code

If you don’t understand why, can be opened:Flutter end calls:

  static Future<Map> register(String id, String name, String avatar) async {
    var methodChannel = const MethodChannel("rongim/server");
    Map<String, dynamic> params = <String, dynamic>{
      "id": id,
      "name": name,
      "avatar": avatar
    };
    var result = await methodChannel.invokeMethod("register", params);
    return result;
  }
Copy the code

The onMethodCall method on the Android side receives the parameters as a map:

 val id = call.argument<String>("id")!!!!! .toString() val name = call.argument<String>("name")!!!!! .toString() val avatar = call.argument<String>("avatar")!!!!! .toString()Copy the code

For detailed code, please refer to the project: github.com/baiyuliang/…