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…