Flutter and Android native mixed development-the use of EventChannel and MethodChannel

When using Flutter to develop apps, you will encounter the interaction with the Android native system API.
You can usually use Flutter to write pages and reuse existing Android logic (such as your own or third-party SDK) to speed up development schedule.
You can use plug-ins to solve, the official website about the development of plug-ins:
writing dual-end platform code (plug-in writing implementation)

A complete demo is listed in the article:
Note: The complete runnable code for this example can be obtained in / examples / platform_channel / for Android using Java and iOS using Objective-C For iOS code implemented in Swift, see / examples / platform_channel_swift / .


Channel

Flutter defines three different types of Channel, they are

  • BasicMessageChannel: Used to pass string and semi-structured information, and can request data in both directions.
  • MethodChannel: Used to pass method invocation (method invocation, that is, the Flutter side can call the method on the Platform side and call back the result data through the Result interface.
  • EventChannel: Used for communication of event streams, that is, the Flutter side monitors real-time messages on the Platform side, and once the Platform side generates data, it immediately calls back to the Flutter side.

⚠️ Note: On Android and iOS platforms, Platform Task Runner runs on the main thread. Therefore, time-consuming operations should not be handled in the Handler on the Platform side.

First look at the main.dart
file of MethodChannel and EventChannel as follows:

class PlatformChannel extends StatefulWidget {
  @override
  _PlatformChannelState createState() => _PlatformChannelState();
}

class _PlatformChannelState extends State<PlatformChannel> {
  static const MethodChannel methodChannel =
      MethodChannel('samples.flutter.io/battery');
  static const EventChannel eventChannel =
      EventChannel('samples.flutter.io/charging');

  String _batteryLevel = 'Battery level: unknown.';
  String _chargingStatus = 'Battery status: unknown.';

  Future<void> _getBatteryLevel() async {
    String batteryLevel;
    try {
      final int result = await methodChannel.invokeMethod('getBatteryLevel');
      batteryLevel = 'Battery level: $result%.';
    } on PlatformException {
      batteryLevel = 'Failed to get battery level.';
    }
    setState(() {
      _batteryLevel = batteryLevel;
    });
  }

  @override
  void initState() {
    super.initState();
    eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);
  }

  void _onEvent(Object event) {
    setState(() {
      _chargingStatus =
          "Battery status: ${event == 'charging' ? '' : 'dis'}charging.";
    });
  }

  void _onError(Object error) {
    setState(() {
      _chargingStatus = 'Battery status: unknown.';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(_batteryLevel, key: const Key('Battery level label')),
              Padding(
                padding: const EdgeInsets.all(16.0),
                child: RaisedButton(
                  child: const Text('Refresh'),
                  onPressed: _getBatteryLevel,
                ),
              ),
            ],
          ),
          Text(_chargingStatus),
        ],
      ),
    );
  }
}

void main() {
  runApp(MaterialApp(home: PlatformChannel()));
}

1. Use MethodChannel steps

  • It defines an MethodChannelobject, and methodChannelthe invokeMethod('getBatteryLevel')method used can be called to the Android native method,
  • Define the MethodChannel object in Android and call its setMethodCallHandler method, implement the onMethodCall method in the callback interface MethodCallHandler, and return the value to the Flutter end through the Result object.
  private static final String BATTERY_CHANNEL = "samples.flutter.io/battery";



    new MethodChannel(getFlutterView(), BATTERY_CHANNEL).setMethodCallHandler(
        new MethodCallHandler() {
          @Override
          public void onMethodCall(MethodCall call, Result result) {
            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();
            }
          }
        }
    );

In this MethodCallHandlercallback, the method call request sent by the Flutter part is processed, and the result.success(batteryLevel)data is passed back.

This is the case where the value returned directly from the Android side can be obtained directly, but usually the Android side operates asynchronously and returns the value in the interface callback, then how to pass the value to the Flutter side at this time? Then it can be used EventChannel.

2. Use EventChannel steps

  • Define the EventChannel object on the Android side and call the setStreamHandler () method, implement the onListen and onCancel methods in the anonymous inner class StreamHandler, and pass the data back to the Flutter side through the EventSink object
  • Flutter by side eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);to define _onEventthe function and the _onErrorfunction processing return value.
  new EventChannel(getFlutterView(), CHARGING_CHANNEL).setStreamHandler(
        new StreamHandler() {
          private BroadcastReceiver chargingStateChangeReceiver;
          @Override
          public void onListen(Object arguments, EventSink events) {
            chargingStateChangeReceiver = createChargingStateChangeReceiver(events);
            registerReceiver(
                chargingStateChangeReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
          }

          @Override
          public void onCancel(Object arguments) {
            unregisterReceiver(chargingStateChangeReceiver);
            chargingStateChangeReceiver = null;
          }
        }
    );

3. Steps to use BasicMessageChannel

Android side:
Insert picture description here
dart side:

Insert picture description here

Reference:
Flutter Platform channel
in-depth understanding of Flutter Platform Channel

Published 82 original articles · Like 86 · Visit 110,000+

Guess you like

Origin blog.csdn.net/unicorn97/article/details/102463153