Flutter development practice-MethodChannel realizes two-way communication between flutter and iOS
In the recent development, iOS and flutter need to communicate. The MethodChannel used here
If you need two-way communication between flutter and Android, please see
https://blog.csdn.net/gloryFlow/article/details/132218837
This part is consistent with https://blog.csdn.net/gloryFlow/article/details/132218837 . Here we implement the MethodChannel settings on the iOS side.
1. MethodChannel
MethodChannel: used to pass method calls (method invocation).
The client and host ends of a channel are connected via the channel name passed to the channel constructor
All channel names used in an application must be unique
Prefix channel names with a unique domain prefix, for example: samples.flutter.dev/battery
Official website https://flutter.cn/docs/development/platform-integration/platform-channels
2. Implement MethodChannel on the flutter side
We need to create a channel named "samples.flutter.dev/test".
Realized by invokeNativeMethod and setMethodCallHandler
invokeNativeMethod: Call the code on the Android side
setMethodCallHandler: Set the method callback to receive the parameters on the Android side
code show as below
import 'package:flutter/services.dart';
//MethodChannel
const methodChannel = const MethodChannel('samples.flutter.dev/test');
class FlutterMethodChannel {
/*
* MethodChannel
* 在方法通道上调用方法invokeMethod
* methodName 方法名称
* params 发送给原生的参数
* return数据 原生发给Flutter的参数
*/
static Future<Map> invokeNativeMethod(String methodName,
[Map? params]) async {
var res;
try {
if (params == null) {
res = await methodChannel.invokeMethod('$methodName');
} else {
res = await methodChannel.invokeMethod('$methodName', params);
}
} catch (e) {
res = {
'Failed': e.toString()};
}
return res;
}
/*
* MethodChannel
* 接收methodHandler
* methodName 方法名称
* params 发送给原生的参数
* return数据 原生发给Flutter的参数
*/
static void methodHandlerListener(Future<dynamic> Function(MethodCall call)? handler) {
methodChannel.setMethodCallHandler(handler);
}
}
To use the MethodChannel, we need to use the MethodChannel
code as follows
void initState() {
// TODO: implement initState
super.initState();
setMethodHandle();
}
void setMethodHandle() {
FlutterMethodChannel.methodHandlerListener((call) {
print("methodHandlerListener call:${
call.toString()}");
if ("methodToFlutter" == call.method) {
print("methodToFlutter arg:${
call.arguments}");
}
return Future.value("message from flutter");
});
}
Future<void> invokeNativeMethod() async {
var result = await FlutterMethodChannel.invokeNativeMethod("methodTest", {
"param":"params from flutter"});
print("invokeNativeMethod result:${
result.toString()}");
}
void testButtonTouched() {
invokeNativeMethod();
}
void dispose() {
// TODO: implement dispose
super.dispose();
}
Here we have processed the method methodToFlutter to receive the parameter passing call from the iOS side, and after processing, we will return the result "message from flutter" to the iOS side.
We call the method methodTest on the iOS side, and pass parameters to get the result returned by the iOS side.
3. Implement MethodChannel on the iOS side
In iOS, we also implemented MethodChannel.
To implement MethodChannel on iOS, you need to implement FlutterPlugin and implement registerWithRegistrar.
Here I name a SDFlutterMethodChannelPlugin that inherits NSObject and implements the registerWithRegistrar method.
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FlutterMethodChannel *methodChannel = [FlutterMethodChannel methodChannelWithName:kFlutterMethodChannelName binaryMessenger:[registrar messenger] codec:[FlutterStandardMethodCodec sharedInstance]];
SDFlutterMethodChannelPlugin *instance = [[SDFlutterMethodChannelPlugin alloc] initWithMethodChannel:methodChannel];
// 将插件注册为来自Dart端的传入方法调用的接收者 在指定的“ FlutterMethodChannel”上。
[registrar addMethodCallDelegate:instance channel:methodChannel];
}
Also set setMethodCallHandler and call Flutter method in the plug-in SDFlutterMethodChannelPlugin
For example
__weak typeof(self) weakSelf = self;
[self.methodChannel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) {
[weakSelf handleMethodCall:call result:result];
}];
The method methodTest can be processed through handleMethodCall to process and receive parameters from flutter, and return the result to flutter after processing.
The overall code is as follows
SDFlutterMethodChannelPlugin.h
#import <Foundation/Foundation.h>
#import <Flutter/Flutter.h>
@class SDFlutterMethodChannelPlugin;
typedef void (^SDFlutterMethodChannelPluginCompletionBlock)(SDFlutterMethodChannelPlugin *plugin);
@interface SDFlutterMethodChannelPlugin : NSObject<FlutterPlugin>
- (instancetype)initWithMethodChannel:(FlutterMethodChannel *)methodChannel;
@end
SDFlutterMethodChannelPlugin.m
#define kFlutterMethodChannelName @"samples.flutter.dev/test"
@interface SDFlutterMethodChannelPlugin ()<FlutterStreamHandler>
@property (nonatomic, strong) FlutterMethodChannel *methodChannel;
@property (nonatomic, strong) NSTimer *sendMessageTimer;
@end
@implementation SDFlutterMethodChannelPlugin
- (instancetype)initWithMethodChannel:(FlutterMethodChannel *)methodChannel {
self = [super init];
if (self) {
self.flutterBridgeConfig = [[DFFlutterBridgeConfig alloc] init];
self.methodChannel = methodChannel;
__weak typeof(self) weakSelf = self;
[self.methodChannel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) {
[weakSelf handleMethodCall:call result:result];
}];
[self startSendMessageTimer];
}
return self;
}
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FlutterMethodChannel *methodChannel = [FlutterMethodChannel methodChannelWithName:kFlutterMethodChannelName binaryMessenger:[registrar messenger] codec:[FlutterStandardMethodCodec sharedInstance]];
SDFlutterMethodChannelPlugin *instance = [[SDFlutterMethodChannelPlugin alloc] initWithMethodChannel:methodChannel];
// 将插件注册为来自Dart端的传入方法调用的接收者 在指定的“ FlutterMethodChannel”上。
[registrar addMethodCallDelegate:instance channel:methodChannel];
}
#pragma mark - FlutterPlugin协议方法
- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
NSLog(@"config handleMethodChannel callmethod:%@,params:%@,result:%@", call.method, call.arguments, result);
// 没有处理,需要单独处理
NSString *method=call.method;
if ([method isEqualToString:@"methodTest"]) {
NSLog(@"flutter 调用到了 ios test");
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setObject:@"result.success 返回给flutter的数据" forKey:@"message"];
[dic setObject: [NSNumber numberWithInt:200] forKey:@"code"];
result(dic);
} else if ([method isEqualToString:@"test2"]) {
NSLog(@"flutter 调用到了 ios test2");
result(@YES);
} else {
result(FlutterMethodNotImplemented);
}
}
#pragma mark - 开启定时器
- (void)sendMessageTimerAction {
// 开启
[self.methodChannel invokeMethod:@"methodToFlutter" arguments:@"Params from Android"];
}
/**
开启定时器
*/
- (void)startSendMessageTimer {
if (_sendMessageTimer) {
return;
}
//开始其实就是开始定时器
_sendMessageTimer = [NSTimer timerWithTimeInterval:6 target:self selector:@selector(sendMessageTimerAction) userInfo:nil repeats:YES];
//加到runloop
[[NSRunLoop currentRunLoop] addTimer:_sendMessageTimer forMode:NSRunLoopCommonModes];
}
/**
结束定时器
*/
- (void)stopSendMessageTimer {
//暂停其实就是销毁计时器
[_sendMessageTimer invalidate];
_sendMessageTimer = nil;
}
@end
In iOS, it needs to be set in AppDelegate, implemented in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[SDFlutterMethodChannelPlugin registerWithRegistrar:[(id)[SDWeakProxy proxyWithTarget:self] registrarForPlugin:@"SDFlutterMethodChannelPlugin"]];
return YES;
}
We implement MethodChanel in the iOS code, and regularly call the method methodToFlutter through the timer NSTimer to pass the parameters to the Flutter side. SetMethodCallHandler on the iOS side processes and receives parameters from flutter according to the method methodTest, and returns the result to flutter after processing.
Four. Summary
Flutter development practice-MethodChannel realizes two-way communication between flutter and iOS. Implement MethodChannel to realize mutual communication between flutter and iOS.
https://blog.csdn.net/gloryFlow/article/details/132240415
Learning records, keep improving every day.