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 (and
Rendering (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 (and
Rendering (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 (and
Rendering (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, and
Rendering (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 ~