Flutter hybrid development BasicMessageChannel communicates with native android

  • Three ways to mix communication
  • Analysis of the
  • The Android end
  • The Flutter end

Said a thousand times I love you finally also arrived but a break up bar. This is love. Once how the imprint is engraved on my heart. once loved how dead and alive, finally still will be light, but everyone’s time transition is not the same.

Three ways to mix communication

  • BasicMessageChannel: two-way communication with a return value and continuous communication
  • MethodChannel: Two-way communication, with return values, one-time communication
  • EventChannel: one-way communication. No return value is returned. The communication continues

Let’s take a look at today’s results:



As usual, first analyze the function:

Analysis of the

The Android side:

  • Click a button with data to jump to the Flutter page,
  • An EditText text box to enter text content
  • Complete transfer of Flutter data

The Flutter end

  • A TextField() component can complete the data return and Toast
  • A RaisedButton() button that can be clicked to complete the Toast presentation and the data returned successfully
  • The text at the bottom shows the data returned by Android

The Android end

The first step; Create BasicMessageChannel ()

(Don’t be so quick to copy, I’ll write tools below! Very good)

 private final BasicMessageChannel<String> messageChannel;
 
messageChannel = new BasicMessageChannel(messenger, "BasicMessageChannelPlugin", StringCodec.INSTANCE);
Copy the code

BasicMessageChannel parameters:

  • BinaryMessenger messenger – a tool for sending and receiving messages;
  • String name– The name and unique identifier of a Channel corresponding to the Flutter end (andRendering (1.1)Corresponding)
  • MessageCodec

    codec – the MessageCodec, which has the following table types
MessageCodec codec type introduce
BinaryCodec Codec is the simplest, because its return value type is the same as the input parameter type, both in binary format (ByteBuffer in Android). In fact, BinaryCodec does nothing in the codec process, just returns the binary data message as it is, right
JSONMessageCodec Codecs between basic data and binary data. It supports basic data types, lists, dictionaries, and uses its custom JSONUtil and StringCodec serialization tools on Android
StringCodec It is used for encoding and decoding between string and binary data in UTF-8 format
StandardMessageCodec Is the default codec for BasicMessageChannel, which supports basic data types, binary data, lists, dictionaries, and how it works;

Rendering (1.1)

Step 2: Set up the message handler to process messages from Dart

 // Set up the message handler to process messages from Dart
        messageChannel.setMessageHandler(new BasicMessageChannel.MessageHandler<String>() {
            @Override
            public void onMessage(@Nullable String message, @NonNull BasicMessageChannel.Reply<String> reply) {
            // You can reply via reply
			 reply.reply("BasicMessageChannel received:"+ message); }});Copy the code

OnMessage parameters:

  • Parameter one,String message, is the received parameter
  • Argument 2: BasicMessageChannel. Reply < String > Reply, when received Flutter news, can Reply. Reply immediately () returns a data (andRendering (1.2)Corresponding)

Rendering (1.2)

Step three, send a message

 messageChannel.send(message, callback);
Copy the code

Parameter Description:

  • Parameter one: The message content to be sent (andRendering (1.3)Corresponding)
  • Parameter 2: Feedback from Dart (I don’t think it’s going to help… )

Rendering (1.3)

BasicMessageChannel

import android.app.Activity;
import android.widget.Toast;

import io.flutter.Log;
import io.flutter.plugin.common.BasicMessageChannel;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.StringCodec;

/ * * SZJ 2020/11/26 CSDN blog: https://blog.csdn.net/weixin_44819566/ WeChat public number: getting rich * / code
public class BasicMessageChannelPlugin implements BasicMessageChannel.MessageHandler<String> {
    private final Activity activity;
    private final BasicMessageChannel<String> messageChannel;

    public static BasicMessageChannelPlugin registerWith(BinaryMessenger messenger, Activity activity) {
        return new BasicMessageChannelPlugin(messenger, activity);
    }

    private BasicMessageChannelPlugin(BinaryMessenger messenger, Activity activity) {
        this.activity = activity;
        this.messageChannel = new BasicMessageChannel(messenger, "BasicMessageChannelPlugin", StringCodec.INSTANCE);
        // Set up the message handler to process messages from Dart
        messageChannel.setMessageHandler(this);

    }

    @Override// Process the Dart message
    public void onMessage(String s, BasicMessageChannel.Reply<String> reply) {
        reply.reply("BasicMessageChannel received:" + s);// You can reply via reply
        if (activity instanceofIShowMessage) { ((IShowMessage) activity).onShowMessage(s); Toast.makeText(activity, s, Toast.LENGTH_SHORT).show(); }}/** * Send a message to Dart and accept Dart's feedback **@paramMessage Indicates the content of the message to be sent to Dart@paramCallback from Dart feedback */
   public void send(String message, BasicMessageChannel.Reply<String> callback) { messageChannel.send(message, callback); }}Copy the code

The code is very simple, if you don’t understand, please leave a message in the comment section

Step 4: Write an interface that defines the data to fetch and send:

public interface IShowMessage {
    / * * * *@param message Flutter -> Android
     */
    void onShowMessage(String message);

    / * * * *@param message Android --> flutter
     */
    void sendMessage(String message);
}
Copy the code

Step 5: Create click events to jump to the page and upload values

 EditText edit = findViewById(R.id.edit);

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FlutterAppActivity.start(BasicMsgChannelActivity.this,edit.getText().toString(),1); }});Copy the code

For those who are confused, please refer to the previous chapter :Flutter hybrid development transferring initialization data to Android(4.2)

Java code (FlutterAppActivity class);

public class FlutterAppActivity extends FlutterActivity  implements IShowMessage{
    private BasicMessageChannelPlugin basicMessageChannelPlugin;

    public final static String INIT_PARAMS = "initParams";
    /** * 0 passes initialization data to Flutter * 1 passes data to Flutter using BasicMsgChannel */
    private static int mtype ;

    public static void start(Context context, String initParams, int type) {
        mtype = type;
        Intent intent = new Intent(context, FlutterAppActivity.class);
        intent.putExtra(INIT_PARAMS, initParams);
        context.startActivity(intent);
    }

    String mInitParam;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("szjonCreate",mtype+"");
        if (mtype == 0) {
           // Pass initialization data to Flutter
            mInitParam = getIntent().getStringExtra(INIT_PARAMS);

        }else if(mtype == 1) {// Use BasicMsgChannel to pass data
            basicMessageChannelPlugin = BasicMessageChannelPlugin.registerWith(getFlutterEngine().getDartExecutor(), this); }}@Override
    protected void onStart(a) {
        super.onStart();
        if (mtype == 1) {
            String initParam = getIntent().getStringExtra(INIT_PARAMS);
            this.sendMessage(initParam); }}/** * Pass initialization parameters to Flutter *@return* /
    @NonNull
    @Override
    public String getInitialRoute(a) {
        return mInitParam == null ? super.getInitialRoute() : mInitParam;
    }

// Use the Flutter engine pre-initialized in MyApplication to increase the Flutter page opening speed.
// Note: in this mode, getInitialRoute will not be called so initialization parameters cannot be set
// @Override
// public String getCachedEngineId() {
// return App.ENG_INED;
/ /}


    @Override
    public void onShowMessage(String message) {
        Log.i("szjonShowMessage",message);
    }

    @Override
    public void sendMessage(String message) {
        Log.i("szjsendMessage",message);
        if (basicMessageChannelPlugin == null) {
            return;
        }
        basicMessageChannelPlugin.send(getIntent().getStringExtra(INIT_PARAMS),this::onShowMessage); }}Copy the code

My sendMessage() method is written in onStart()

 @Override
    protected void onStart(a) {
        super.onStart();
        if (mtype == 1) {
            String initParam = getIntent().getStringExtra(INIT_PARAMS);
            this.sendMessage(initParam); }}Copy the code

The mType in the code is a variable used to distinguish the Flutter from the variable used in the previous chapter :Flutter hybrid development to pass initialization data to Android(4.2)!

The initialization of the Android terminal is complete, in a simple analysis:

  • The BasicMsgChannelActivity page has a button and a text box. Clicking the button invoks the method to jump to the FlutterAppActivity page FlutterAppActivity is a Flutter page because FlutterAppActivity inherits from FlutterActivity. In the onCreate method of FlutterAppActivity then use tools BasicMessageChannelPlugin, this utility class is initialized BasicMessageChannel (). The send method is called in the onStart() method to pass the dart value.

The Flutter end

Here is the code for Flutter:

Step 1: Initialize BasicMessageChannel()

BasicMessageChannel()
BasicMessageChannel<String> _basicMessageChannel =
      BasicMessageChannel('BasicMessageChannelPlugin', StringCodec());
Copy the code
  • Parameter 1: Corresponds to BasicMessageChannel() in the Android code, andRendering (1.4)The corresponding

Rendering (1.4)

  • Parameter 2: Encoding mode. The encoding mode of Android and Flutter is the same

Step 2: Use BasicMessageChannel to accept messages from Native and reply back to Native


  String showMessage;

  @override
  void initState(a) {
    // Use BasicMessageChannel to receive messages from Native and reply to Native
    _basicMessageChannel
        .setMessageHandler((String message) => Future<String>(() {
              setState(() {
                showMessage = 'BasicMessageChannel:' + message;
              });
              return "BasicMessageChannel receives message from Android:" + message;
            }));
    super.initState();
  }
Copy the code
 RaisedButton(
      onPressed: () {
      _basicMessageChannel.send("I am data of Flutter!!");
      },
      child: Text("Send a message to native"),
      ),
     TextField(
        onChanged: _onTextChange,
        decoration: InputDecoration(
        hintText: "Please enter a message to native send",
          ),
    ),
    Text(BasicMessageChannel receives android native data as: ${showMessage}),
Copy the code

It is recommended to use asynchronous operation to send messages.

  void _onTextChange(value) async {
    String response;
    /** * on Android the equivalent is reply.reply() */
    response = await _basicMessageChannel.send(value);
    setState(() {
      showMessage =  response ;
    });
  }
Copy the code

Walk here to complete, you must see a little confused, I speak not very good, but also take words to express, the expression is not very perfect, or in the summary:

Android is used to send messages to Flutter

BasicMessageChannel messageChannel = BasicMessageChannel(parameter 1, parameter 2, parameter 3); messageChannel.send(message, callback);Copy the code

Android gets messages sent by Flutter using:

 @Override// Process the Dart message
  messageChannel.setMessageHandler(new BasicMessageChannel.MessageHandler<String>() {
            @Override
            public void onMessage(@Nullable String message, @NonNull BasicMessageChannel.Reply<String> reply) {
             reply.reply("I'm android code reply:" + s);// You can reply via replyToast.makeText(activity, message, Toast.LENGTH_SHORT).show(); }});Copy the code
  • Message here is the message that a Flutter sends to Android. I have displayed it as Toast
  • Reply.reply () is used to retrieve data from a Flutter

Note on Android that the send() method must come after the BasicMessageChannel() method is initialized; if it comes before it, send() will be null

Flutter retrieves data sent by Android using:

// Initialize BasicMessageChannel
 BasicMessageChannel<String> _basicMessageChannel =
      BasicMessageChannel('BasicMessageChannelPlugin', StringCodec());

_basicMessageChannel
        .setMessageHandler((String message) => Future<String>(() {
              setState(() {
                //Android --> Flutter
                showMessage = 'BasicMessageChannel:' + message;
              });
              return "BasicMessageChannel receives message from Android:" + message;
            }));
Copy the code

The message here is the data that Android sends to Flutter

Android returns the data that Flutter sends to Android:

String response = _basicMessageChannel.send(value);
Copy the code

After sending the data, the return value of send() is the data returned by Android

Take a look at the effect:

You think this is the end of it?

Definitely not, don’t you want to know why there is a black screen when jumping??

How to solve it? For a guy like me, try to be perfect

The previous chapter on Flutter hybrid development passed initialization data to Android(4.2), just in The FlutterAppActivity

  @Override
        public String getCachedEngineId(a) {
            return App.ENG_INED;
        }
Copy the code

GetCachedEngineId () causes getInitialRoute() not to be called and therefore cannot be initialized, but BasicMessageChannel() does not

Come to kangkang’s final results:



I worked on this communication for several days, made many mistakes, finally finished this one, in the next few articles I will introduce the other two communication methods ~

The complete code

What do you like?

Android jump page, FLutter engine, etc. (4.1)

Pass initialization data to Android for Flutter hybrid development (4.2)

Flutter hybrid development EventChannel one-way data transfer (4.4)

MethodChannel of Flutter hybrid development one-way message passing (4.5)

How to convert a Flutter project into a Module into an Android project (4.6)

Original is not easy, your thumbs up is my biggest support, leave your thumbs up ~