Communication between Flutter and android

Introduction to Platform Channel

Flutter introduces the Platform Channel mechanism to support API calls on different platforms. In Flutter, three Platform Channels are provided to support the transfer of data between platforms:

  • BasicMessageChannel: Supports string and semi-structured data transmission. You can obtain icons and other resources of Native projects through BasicMessageChannel.
  • MethodChannel: Supports passing method calls. Flutter actively calls Native methods and obtains the corresponding return value. You can initiate method calls from the Flutter platform, or you can initiate calls to Flutter from the platform code.
  • EventChannel: supports data stream communication and delivers events. After receiving the message, you cannot reply to this message. It is usually used for communication from Native to Dart.

Instructions

BasicMessageChannel

Android side:

BasicMessageChannel mBasicMessageChannel = new BasicMessageChannel(getFlutterView(), "basic_channel", StringCodec.INSTANCE);
mBasicMessageChannel.setMessageHandler(new BasicMessageChannel.MessageHandler() {
    //接受消息
    @Override
    public void onMessage(Object o, BasicMessageChannel.Reply reply) {
        Log.e("basic_channel", "接收到来自flutter的消息:"+o.toString());
        reply.reply("回馈消息");
    }
});
//发送消息
mBasicMessageChannel.send("向flutter发送消息");
//发送消息并接受flutter的回馈
mBasicMessageChannel.send("向flutter发送消息", new BasicMessageChannel.Reply() {
            @Override
            public void reply(Object o) {
                
            }
});

Flutter side:

const basicMessageChannel = const BasicMessageChannel('basic_channel', StringCodec());
//接受并回复消息
basicMessageChannel.setMessageHandler(
      (String message) => Future<String>(() {
            setState(() {
              this.message = message;
            });
            return "回复native消息";
      }),
);
//发送消息
basicMessageChannel.send("来自flutter的message");
//flutter并没有发送并接受回复消息的`send(T message, BasicMessageChannel.Reply<T> callback)`方法

MethodChannel

Android side:

MethodChannel mMethodChannel = new MethodChannel(getFlutterView(), "method_channel");
mMethodChannel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
    //响应flutter端的调用
    @Override
    public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
        if (methodCall.method.equals("noticeNative")) {
            todo()
            result.success("接受成功");
        }
    }
});
//原生调用flutter
mMethodChannel.invokeMethod("noticeFlutter", "argument", new MethodChannel.Result() {
            @Override
            public void success(Object o) {
                //回调成功
            }
            @Override
            public void error(String s,String s1, Object o) {
                //回调失败
            }
            @Override
            public void notImplemented() {

            }
});

Flutter side:

const methodChannel = const MethodChannel('method_channel');
Future<Null> getMessageFromNative() async {
    //flutter调原生方法
    try {
      //回调成功
      final String result = await methodChannel.invokeMethod('noticeNative');
      setState(() {
        method = result;
      });
    } on PlatformException catch (e) {
      //回调失败
    }
  }
methodChannel.setMethodCallHandler(
      (MethodCall methodCall) => Future<String>(() {
            //响应原生的调用
          if(methodCall.method == "noticeFlutter"){
            setState(() {
              
            });
          }
      }),
); 

EventChannel

Android side:

EventChannel eventChannel = new EventChannel(getFlutterView(),"event_channel");
eventChannel.setStreamHandler(new EventChannel.StreamHandler() {
    @Override
    public void onListen(Object o, EventChannel.EventSink eventSink) {
        eventSink.success("成功");
        //eventSink.error("失败","失败","失败");
    }
    @Override
    public void onCancel(Object o) {
        //取消监听时调用
    }
});

Flutter side:

const eventChannel = const EventChannel('event_channel');
eventChannel.receiveBroadcastStream().listen(_onEvent,onError:_onError);
void _onEvent(Object event) {
    //返回的内容
}
void _onError(Object error) {
    //返回的回调
}

Among them: Object args is the passed parameters, EventChannel.EventSink eventSink is the callback function when Native calls back Dart. eventSink provides three callback methods: success, error and endOfStream, which correspond to different states of the event.

A preliminary exploration of the source code

Platform Channel basic structure

First, let’s understand the codes of these three Channels:

BasicMessageChannel
class BasicMessageChannel<T> {
  const BasicMessageChannel(this.name, this.codec);
  final String name;
  final MessageCodec<T> codec;
  Future<T> send(T message) async {
    return codec.decodeMessage(await BinaryMessages.send(name, codec.encodeMessage(message)));
  }
  void setMessageHandler(Future<T> handler(T message)) {
    if (handler == null) {
      BinaryMessages.setMessageHandler(name, null);
    } else {
      BinaryMessages.setMessageHandler(name, (ByteData message) async {
        return codec.encodeMessage(await handler(codec.decodeMessage(message)));
      });
    }
  }
  void setMockMessageHandler(Future<T> handler(T message)) {
    if (handler == null) {
      BinaryMessages.setMockMessageHandler(name, null);
    } else {
      BinaryMessages.setMockMessageHandler(name, (ByteData message) async {
        return codec.encodeMessage(await handler(codec.decodeMessage(message)));
      });
    }
  }
}
MethodChannel
class MethodChannel {
  const MethodChannel(this.name, [this.codec = const StandardMethodCodec()]);
  final String name;
  final MethodCodec codec;
  void setMethodCallHandler(Future<dynamic> handler(MethodCall call)) {
    BinaryMessages.setMessageHandler(
      name,
      handler == null ? null : (ByteData message) => _handleAsMethodCall(message, handler),
    );
  }
  void setMockMethodCallHandler(Future<dynamic> handler(MethodCall call)) {
    BinaryMessages.setMockMessageHandler(
      name,
      handler == null ? null : (ByteData message) => _handleAsMethodCall(message, handler),
    );
  }
  Future<ByteData> _handleAsMethodCall(ByteData message, Future<dynamic> handler(MethodCall call)) async {
    final MethodCall call = codec.decodeMethodCall(message);
    try {
      return codec.encodeSuccessEnvelope(await handler(call));
    } on PlatformException catch (e) {
      returun ...
    } on MissingPluginException {
      return null;
    } catch (e) {
      return ...
    }
  }
  Future<T> invokeMethod<T>(String method, [dynamic arguments]) async {
    assert(method != null);
    final ByteData result = await BinaryMessages.send(
      name,
      codec.encodeMethodCall(MethodCall(method, arguments)),
    );
    if (result == null) {
      throw MissingPluginException('No implementation found for method $method on channel $name');
    }
    final T typedResult = codec.decodeEnvelope(result);
    return typedResult;
  }
}
EventChannel
class EventChannel {
  const EventChannel(this.name, [this.codec = const StandardMethodCodec()]);
  final String name;
  final MethodCodec codec;
  Stream<dynamic> receiveBroadcastStream([dynamic arguments]) {
    final MethodChannel methodChannel = MethodChannel(name, codec);
    StreamController<dynamic> controller;
    controller = StreamController<dynamic>.broadcast(onListen: () async {
      BinaryMessages.setMessageHandler(name, (ByteData reply) async {
        ...
      });
      try {
        await methodChannel.invokeMethod<void>('listen', arguments);
      } catch (exception, stack) {
        ...
      }
    }, onCancel: () async {
      BinaryMessages.setMessageHandler(name, null);
      try {
        await methodChannel.invokeMethod<void>('cancel', arguments);
      } catch (exception, stack) {
        ...
      }
    });
    return controller.stream;
  }
}

These three types of Channels have two member variables:

  • name: Indicates the name of the Channel, which is a unique identifier used to distinguish different Platform Channels. Each Channel uses a unique name as its unique identifier.
  • codec: Represents the codec of the message. Flutter uses a binary byte stream as the data transmission protocol: the sender needs to encode the data into binary data, and the receiver decodes the data into original data. The codec is responsible for the encoding and decoding operations.
    It is used in every Channel BinaryMessages. It acts as a messenger, responsible for carrying information across platforms, and is a tool for sending and receiving messages.
setMessageHandler

After it is created BasicMessageChannel, let it accept messages from another platform, BinaryMessengercall its setMessageHandlermethod to set up a message processor for it, and cooperate BinaryMessengerto complete message processing and reply;

send

After it is created BasicMessageChannel, its send method can be called to transfer data to another platform.

setMethodCallHandler

Sets MethodChannela callback for receiving method calls on this

receiveBroadcastStream

Set up a broadcast stream to receive EventChannelevents on this

Handler

Flutter uses Handler to process messages decoded by Codec. Three types of Platform Channels correspond to each other, and three types of Handlers are also defined in Flutter:

  • MessageHandler: used to process string or semi-structured messages, defined in BasicMessageChannel.
  • MethodCallHandler: used to handle method calls, defined in MethodChannel.
  • StreamHandler: used for event stream communication, defined in EventChannel

When using Platform Channel, you need to register a corresponding BinaryMessageHandler for it and set the corresponding Handler for it. Binary data will be processed by BinaryMessageHanler, first use Codec for decoding operation, and then distribute to specific Handler for processing.

Guess you like

Origin blog.csdn.net/qq_27981847/article/details/132760010