PlatformChannel features introduction

PlatformChannel is divided into BasicMessageChannel, MethodChannel and EventChannel. Their main uses are as follows:

  • BasicMessageChannel: Used to transfer data. Flutter does not share resources with Native projects. Resources such as ICONS of Native projects can be obtained via BasicMessageChannel.
  • MethodChannel: Passes method calls. Flutter actively calls Native methods and gets the corresponding return value. For example, to obtain the system power, initiate Toast and call the system API, this can be done.
  • EventChannel: Transmits an event. Here is the Native notifying the Flutter of events. For example, Flutter needs to listen on the network, and MethodChannel is not up to the task. EventChannel can deliver a monitor of Flutter to Native, and Native can monitor the network broadcast. After receiving the broadcast, EventChannel calls the monitor registered with Flutter to complete the event notification of Flutter.

In fact, it can be seen that both the pass method and the pass event are essentially the data pass, but some logic of the upper package is different.

The specific implementation

BasicMessageChannel

The initial message is sent directly to the Native endpoint, but the flutter cannot receive the message, because the receiver listening method has not been implemented, so the message is sent to the Native endpoint, and we need to pay attention to the timing of the flutter

 static const messageChannel = const BasicMessageChannel('samples.flutter.io/message', StandardMessageCodec());

 static const messageChannel2 = const BasicMessageChannel('samples.flutter.io/message2', StandardMessageCodec());

 Future<String> sendMessage() async {
    String reply = await messageChannel.send('Data sent to Native');
    print('reply: $reply');
    return reply;
  }

  void receiveMessage() {
    messageChannel2.setMessageHandler((message) async {
      print('message: $message');
      return 'Return data at Native';
    });
  }
  
   @override
  void initState() {
    // TODO: implement initState
    super.initState();
    receiveMessage();
    sendMessage();

  }
Copy the code

ios

/ / initialize the definition FlutterBasicMessageChannel * messageChannel = [FlutterBasicMessageChannel messageChannelWithName: @"samples.flutter.io/message"binaryMessenger:controller]; // Receive message listener [messageChannelsetMessageHandler:^(id message, FlutterReply callback) {
    NSLog(message);
    callback(@"Return data at the flutter end."); }]; / / triggers execute FlutterViewController * controller = (FlutterViewController *) self. Window. The rootViewController; FlutterBasicMessageChannel* messageChannel2 = [FlutterBasicMessageChannel messageChannelWithName:@"samples.flutter.io/message2"binaryMessenger:controller]; // send a message [messageChannel2 sendMessage:(@)"Data sent to flutter") reply:^(id reply) {
    NSLog(reply);
}];
Copy the code

android

BasicMessageChannel<Object> messageChannel = new BasicMessageChannel<Object>(getFlutterView(), "samples.flutter.io/message", StandardMessageCodec.INSTANCE); / / receive messages to monitor messageChannel. SetMessageHandler (new BasicMessageChannel. The MessageHandler < Object > () {@ Override public void onMessage(Object o, BasicMessageChannel.Reply<Object> reply) { System.out.println("onMessage: " + o);
        reply.reply("Data returned to flutter"); }}); BasicMessageChannel<Object> messageChannel2 = new BasicMessageChannel<Object>(getFlutterView(),"samples.flutter.io/message2", StandardMessageCodec.INSTANCE); Messagechannel2. send("Data sent to flutter", new BasicMessageChannel.Reply<Object>() {
    @Override
    public void reply(Object o) {

        System.out.println("onReply: "+ o); }});Copy the code

MethodChannel

flutter

 static const platform = const MethodChannel('samples.flutter.io/battery');
 
 Future<Null> _getBatteryLevel() async {
    String batteryLevel;
    try {
      final int result = await platform.invokeMethod('getBatteryLevel');
      batteryLevel = 'Battery level at $result % .';
    } on PlatformException catch (e) {
      batteryLevel = "Failed to get battery level: '${e.message}'.";
    }

    setState(() { _batteryLevel = batteryLevel; }); } // Execute the _getBatteryLevel methodCopy the code

ios

FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;
    
FlutterMethodChannel* batteryChannel = [FlutterMethodChannel
                                        methodChannelWithName:@"samples.flutter.io/battery"
                                        binaryMessenger:controller];



[batteryChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
    // TODO
    if ([@"getBatteryLevel" isEqualToString:call.method]) {
        int batteryLevel = [self getBatteryLevel];
        
        if (batteryLevel == -1) {

            result([FlutterError errorWithCode:@"UNAVAILABLE"
                                       message:@"Battery info unavailable"
                                       details:nil]);
        } else{ result(@(batteryLevel)); }}else{ result(FlutterMethodNotImplemented); }}]; - (int)getBatteryLevel { UIDevice* device = UIDevice.currentDevice; device.batteryMonitoringEnabled = YES;if (device.batteryState == UIDeviceBatteryStateUnknown) {
        return- 1; }else {
        return(int)(device.batteryLevel * 100); }}Copy the code

android

new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
    new MethodCallHandler() {
        @Override
        public void onMethodCall(MethodCall call, Result result) {
            // TODO
            if (call.method.equals("getBatteryLevel")) {
                int batteryLevel = getBatteryLevel();

                if(batteryLevel ! = -1) { result.success(batteryLevel); }else {
                    result.error("UNAVAILABLE"."Battery level not available.", null); }}else{ result.notImplemented(); }}}); private intgetBatteryLevel() {
    int batteryLevel = -1;
    if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
        BatteryManager batteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE);
        batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
    } else {
        Intent intent = new ContextWrapper(getApplicationContext()).
                registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
        batteryLevel = (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) /
                intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
    }

    return batteryLevel;
}
Copy the code

FlutterEventChannel

flutter

static const EventChannel _eventChannel =
      const EventChannel('samples.flutter.io/test');

 void _onEvent(Object event) {
    print('Return: $event');
  }

  void _onError(Object error) {
    print('Error returned');
  }
  
  @override
  void initState() { // TODO: implement initState super.initState(); / / listen to start _eventChannel. ReceiveBroadcastStream () listen (_onEvent, onError: _onError); }Copy the code

ios

FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;
    
FlutterEventChannel* eventChannel = [FlutterEventChannel eventChannelWithName:@"samples.flutter.io/test" binaryMessenger:controller];
[eventChannel setStreamHandler:self]; FlutterEventSink eventSink; // // The onListen is the callback when the Flutter end starts listening to the channel. The second parameter, EventSink, is the carrier used to transmit data. - (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments eventSink:(FlutterEventSink)events { eventSink = events; // Arguments arguments to the native of the flutter // callback to the flutter. It is recommended to use the instance to point to since the block can be used multiple timesif (events) {
        events(@"Actively send notifications to flutter"); } // Listen for battery status [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onBatteryStateDidChange:) name:UIDeviceBatteryStateDidChangeNotification object:nil];returnnil; } // flutter no longer receives - (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments {// arguments [[NSNotificationCenter defaultCenter] removeObserver:self]; eventSink = nil;return nil;
}

- (void)onBatteryStateDidChange:(NSNotification*)notification {
    if (eventSink == nil) return;
    UIDeviceBatteryState state = [[UIDevice currentDevice] batteryState];
    switch (state) {
            case UIDeviceBatteryStateFull:
            case UIDeviceBatteryStateCharging:
            eventSink(@"charging");
            break;
            case UIDeviceBatteryStateUnplugged:
            eventSink(@"discharging");
            break;
        default:
            eventSink([FlutterError errorWithCode:@"UNAVAILABLE"
                                           message:@"Charging status unavailable"
                                           details:nil]);
            break; }}Copy the code

android

new EventChannel(getFlutterView(), CHANNEL2).setStreamHandler(
    new EventChannel.StreamHandler() {
        @Override
        public void onListen(Object o, EventChannel.EventSink eventSink) {
            this.eventSink = eventSink;

            handler.sendEmptyMessageDelayed(1, 1000);
        }

        @Override
        public void onCancel(Object o) {

        }

        private EventChannel.EventSink eventSink;
        private int count = 0;
        private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                eventSink.success((count++) + "Actively send messages to Flutter"); / / handler. SendEmptyMessageDelayed (1100); }}; });Copy the code

The source code

Making: github.com/shimuhui/fl…