Channel
实现与原生通信
【1】MethodChannel
flutter MethodChannel官方文档
通过MethodChannel来传递数据,调用方法
案例
分别调用Android和Ios原生的获取电量的方法
Flutter端
实例一个MethodChannel, 唯一标识name,定义方法名称getBatteryLevel
methodchannel.invokeMethod(name)来调用方法
static const platform = MethodChannel('sample.flutter.dev/battery');static const method = 'getBatteryLevel';String _batteryLevel = 'Unknown battery level';Future<void> _getBatteryLevel() async {String batteryLevel;try {final result = await platform.invokeMethod<int>(method);batteryLevel = 'Battery level at $result';} on PlatformException catch (e) {batteryLevel = "Failed to get battery level: '${e.message}";}setState(() {_batteryLevel = batteryLevel;});}
界面操作
Widget build(BuildContext context) {return Material(child: Column(mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: [ElevatedButton(onPressed: _getBatteryLevel,child: const Text('Get Battery Level'),),Text(_batteryLevel),],),);}
Android端
private static final String CHANNEL = "sample.flutter.dev/battery";private MethodChannel methodChannel;private static final String METHOD = "getBatteryLevel";@Overridepublic void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {super.configureFlutterEngine(flutterEngine);BinaryMessenger binaryMessenger = flutterEngine.getDartExecutor().getBinaryMessenger();methodChannel = new MethodChannel(binaryMessenger, CHANNEL);methodChannel.setMethodCallHandler((call, result) -> {});}
if (call.method.equals(METHOD)) {int batteryLevel = getBatteryLevel();if (batteryLevel != -1) {result.success(batteryLevel);} else {result.error("UNAVAILABLE", "Battery level not avaiable", null);}} else {result.notImplemented();}
private int getBatteryLevel() {int batteryLevel = -1;if (VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {BatteryManager batteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE);batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);} else {IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);Intent intent = new ContextWrapper(getApplicationContext()).registerReceiver(null, intentFilter);batteryLevel = (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) /intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);}return batteryLevel;}
Ios端
实例FlutterMethodChannel
override func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {let method : String = "getBatteryLevel"let controller : FlutterViewController = window?.rootViewController as! FlutterViewControllerlet batteryChannel = FlutterMethodChannel(name: "sample.flutter.dev/battery", binaryMessenger: controller.binaryMessenger)batteryChannel.setMethodCallHandler({(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void inguard call.method == method else {result(FlutterMethodNotImplemented)return}self.receiveBatteryLevel(result: result)})GeneratedPluginRegistrant.register(with: self)return super.application(application, didFinishLaunchingWithOptions: launchOptions)}
定义获取电量的方法
func receiveBatteryLevel(result: FlutterResult) -> Void {let device = UIDevice.currentdevice.isBatteryMonitoringEnabled = trueif device.batteryState == UIDevice.BatteryState.unknown {result(FlutterError(code: "UNAVAILABLE", message: "Battery level not available.", details: nil))} else {result(Int(device.batteryLevel * 100))}}
运行测试
【2】EventChannel
墙外的参考文章
区别MethodChannel,它是continuously
采用event streams
案例
在原生端(Android&Ios)会有个计时器,不停的传时间给Flutter端,Flutter端显示出来
Flutter端
实例一个EventChannel,唯一标识name
late EventChannel eventChannel;void initState() {eventChannel = const EventChannel('timeHandlerEvent');super.initState();}
在Flutter注册监听
Stream<String> get streamTimeFromNative =>eventChannel.receiveBroadcastStream().map((event) => event.toString());Widget build(BuildContext context) {return Scaffold(body: Center(child: StreamBuilder<String>(stream: streamTimeFromNative,builder: (BuildContext context, AsyncSnapshot<String> snapshot) {if (snapshot.hasData) {return Text('${snapshot.data}',style: Theme.of(context).textTheme.headlineMedium,);} else {return const CircularProgressIndicator();}},),),);}
Ios端
实例一个FlutterEventChannel,加上唯一标识timeHandlerEvent
let controller : FlutterViewController = window?.rootViewController as! FlutterViewControllerlet eventChannel = FlutterEventChannel(name: "timeHandlerEvent", binaryMessenger: controller.binaryMessenger)
定义FlutterStreamHandler
class TimeHandler: NSObject, FlutterStreamHandler {func onCancel(withArguments arguments: Any?) -> FlutterError? {return nil}func onListen(withArguments arguments: Any?, eventSink: @escaping FlutterEventSink) -> FlutterError? {return nil}}
每间隔1秒发送一次当前时间
class TimeHandler: NSObject, FlutterStreamHandler {var timer = Timer()private var eventSink: FlutterEventSink?func onCancel(withArguments arguments: Any?) -> FlutterError? {eventSink = nilreturn nil}func onListen(withArguments arguments: Any?, eventSink: @escaping FlutterEventSink) -> FlutterError? {self.eventSink = eventSinkself.timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: {_ in let dateFormat = DateFormatter()dateFormat.dateFormat = "HH:mm:ss"let time = dateFormat.string(from: Date())eventSink(time)})return nil}}
注册监听
eventChannel.setStreamHandler(TimeHandler())
Android端
new 一个EventChannel对象
在channel注册一个stream Handler
EventChannel.StreamHandler streamHandler = new EventChannel.StreamHandler() {@Overridepublic void onListen(Object arguments, EventChannel.EventSink events) {}@Overridepublic void onCancel(Object arguments) {}};eventChannel.setStreamHandler(streamHandler);
不断将当前时间返回
EventChannel.StreamHandler streamHandler = new EventChannel.StreamHandler() {private final Handler handler = new Handler(Looper.getMainLooper());private EventChannel.EventSink eventSink = null;@Overridepublic void onListen(Object arguments, EventChannel.EventSink events) {eventSink = events;Runnable runnable = new Runnable() {@Overridepublic void run() {Locale locale = new Locale("zh", "CN");SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss", locale);String time = dateFormat.format(new Date());events.success(time);handler.postDelayed(this, 1000);}};handler.postDelayed(runnable, 1000);}@Overridepublic void onCancel(Object arguments) {eventSink = null;}};eventChannel.setStreamHandler(streamHandler);
运行测试
在建立好EventChannel之后,运行项目。
获取到当前的时间,并且不停的
【3】BasicMessageChannel
参考文章
约定一种数据格式,来互相传递数据
案例
传递Map数据到Android/Ios端,再解析并返回数据到Flutter端
Flutter端
构建BasicMessageChannel, 唯一标识name,约定数据格式StandardMessageCodec
static const messageChannel =BasicMessageChannel('basic_message_channel', StandardMessageCodec());
发送数据
Map<String, dynamic> message = {"name": "apple","time": "2024-04-09 12:30:00"};
messageChannel.send(arguments)
接收数据
Map reply = await messageChannel.send(arguments) as Map;
Android 端
接收数据
messageChannel.setMessageHandler((message, reply) -> {});
发送数据
reply.reply(resultMap);
package com.example.basic_message_channel_example;import android.os.Bundle;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.BasicMessageChannel;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.StandardMessageCodec;public class MainActivity extends FlutterActivity {@Overridepublic void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {super.configureFlutterEngine(flutterEngine);BinaryMessenger binaryMessenger = Objects.requireNonNull(getFlutterEngine()).getDartExecutor().getBinaryMessenger();BasicMessageChannel<Object> messageChannel = new BasicMessageChannel<Object>(binaryMessenger, "basic_message_channel", StandardMessageCodec.INSTANCE);messageChannel.setMessageHandler((message, reply) -> {Map<Object, Object> arguments = (Map<Object, Object>) message;assert message != null;String name = (String) arguments.get("name");assert name != null;if (name.equals("apple")) {Map<String, Object> resultMap = new HashMap<>();String timeStr = (String) arguments.get("time");Timestamp timestamp = Timestamp.valueOf(timeStr);resultMap.put("message", "i eat the " + name + " at " + timestamp.toString());resultMap.put("code", 200);reply.reply(resultMap);} else {Map<String, Object> resultMap = new HashMap<>();resultMap.put("message", "i dislike " + name);resultMap.put("code", 500);reply.reply(resultMap);}});}
}
Ios 端
构建通道
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let basicMessageChannel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: controller.binaryMessenger)
接收数据
basicMessageChannel.setMessageHandler { message, reply in}
返回数据
reply(result)
import UIKit
import Flutter@available(iOS 15.0, *)
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {override func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {let channelName : String = "basic_message_channel"let controller : FlutterViewController = window?.rootViewController as! FlutterViewControllerlet basicMessageChannel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: controller.binaryMessenger)basicMessageChannel.setMessageHandler { message, reply inif let data = message as? Dictionary<String, Any> {let name: String = data["name"] as? String ?? ""if name == "apple" {let timeStr: String = data["time"] as? String ?? ""var message: String = "I eat the "message.append(name)message.append(" at ")message.append(timeStr)let result = ["code": 200, "message": message]reply(result)} else {var message = "I dislike "message.append(name)let result = ["code": 500, "message": message]reply(result)}}}GeneratedPluginRegistrant.register(with: self)return super.application(application, didFinishLaunchingWithOptions: launchOptions)}
}
运行测试
总结
MethodChannel 定义方法名调用
EventChannel 持续监听数据传递
BasicMessageChannel 约定一种数据格式,传递数据