flutter与原生交互的具体实现
2019-02-28 本文已影响565人
沐沐小火柴
PlatformChannel功能简介
PlatformChannel分为BasicMessageChannel、MethodChannel以及EventChannel三种。其各自的主要用途如下:
- BasicMessageChannel: 用于传递数据。Flutter与原生项目的资源是不共享的,可以通过BasicMessageChannel来获取Native项目的图标等资源。
- MethodChannel: 传递方法调用。Flutter主动调用Native的方法,并获取相应的返回值。比如获取系统电量,发起Toast等调用系统API,可以通过这个来完成。
- EventChannel: 传递事件。这里是Native将事件通知到Flutter。比如Flutter需要监听网络情况,这时候MethodChannel就无法胜任这个需求了。EventChannel可以将Flutter的一个监听交给Native,Native去做网络广播的监听,当收到广播后借助EventChannel调用Flutter注册的监听,完成对Flutter的事件通知。
其实可以看到,无论传方法还是传事件,其本质上都是数据的传递,不过上层包的一些逻辑不同而已。
具体实现
BasicMessageChannel
初始直接在Native端发送消息, flutter是收不到的, 因为还没有执行接收监听方法, 所以在Native端发送消息, 需要注意一下时机
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('发送给Native端的数据');
print('reply: $reply');
return reply;
}
void receiveMessage() {
messageChannel2.setMessageHandler((message) async {
print('message: $message');
return '返回Native端的数据';
});
}
@override
void initState() {
// TODO: implement initState
super.initState();
receiveMessage();
sendMessage();
}
ios
// 初始化定义
FlutterBasicMessageChannel* messageChannel = [FlutterBasicMessageChannel messageChannelWithName:@"samples.flutter.io/message" binaryMessenger:controller];
// 接收消息监听
[messageChannel setMessageHandler:^(id message, FlutterReply callback) {
NSLog(message);
callback(@"返回flutter端的数据");
}];
// 触发事件执行
FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;
FlutterBasicMessageChannel* messageChannel2 = [FlutterBasicMessageChannel messageChannelWithName:@"samples.flutter.io/message2" binaryMessenger:controller];
// 发送消息
[messageChannel2 sendMessage:(@"发送给flutter的数据") reply:^(id reply) {
NSLog(reply);
}];
android
BasicMessageChannel<Object> messageChannel = new BasicMessageChannel<Object>(getFlutterView(), "samples.flutter.io/message", StandardMessageCodec.INSTANCE);
// 接收消息监听
messageChannel.setMessageHandler(new BasicMessageChannel.MessageHandler<Object>() {
@Override
public void onMessage(Object o, BasicMessageChannel.Reply<Object> reply) {
System.out.println("onMessage: " + o);
reply.reply("返回给flutter的数据");
}
});
// 触发事件执行
BasicMessageChannel<Object> messageChannel2 = new BasicMessageChannel<Object>(getFlutterView(), "samples.flutter.io/message2", StandardMessageCodec.INSTANCE);
// 发送消息
messageChannel2.send("发送给flutter的数据", new BasicMessageChannel.Reply<Object>() {
@Override
public void reply(Object o) {
System.out.println("onReply: " + o);
}
});
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;
});
}
// 执行_getBatteryLevel方法
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);
}
}
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 int getBatteryLevel() {
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;
}
FlutterEventChannel
flutter
static const EventChannel _eventChannel =
const EventChannel('samples.flutter.io/test');
void _onEvent(Object event) {
print('返回的内容: $event');
}
void _onError(Object error) {
print('返回的错误');
}
@override
void initState() {
// TODO: implement initState
super.initState();
// 监听开始
_eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);
}
ios
FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;
FlutterEventChannel* eventChannel = [FlutterEventChannel eventChannelWithName:@"samples.flutter.io/test" binaryMessenger:controller];
[eventChannel setStreamHandler:self];
FlutterEventSink eventSink;
// // 这个onListen是Flutter端开始监听这个channel时的回调,第二个参数 EventSink是用来传数据的载体。
- (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments
eventSink:(FlutterEventSink)events {
eventSink = events;
// arguments flutter给native的参数
// 回调给flutter, 建议使用实例指向,因为该block可以使用多次
if (events) {
events(@"主动发送通知到flutter");
}
// 监听电池状态
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onBatteryStateDidChange:)
name:UIDeviceBatteryStateDidChangeNotification
object:nil];
return nil;
}
/// flutter不再接收
- (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments {
// arguments flutter给native的参数
[[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;
}
}
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++) + "主动发送消息给flutter");
// handler.sendEmptyMessageDelayed(1,1000);
}
};
}
);