当前Flutter内的请求数据都无法直接利用抓包工具直接抓取,对测试造成了十分严重的困扰。下面说说如何解决Flutter模块无法抓包这个问题。
解决思路是这样的:基于Flutter自带的网络框架与原生的网络框架不通,设置网络代理时只能检测到原生的网络,那么我们可以主动为Flutter网络框架设置对应的代理地址以获取网络请求数据。
那么我们需要Native主动为Flutter端提供代理的地址。为此我们采用EventChannel的方式来传递两端数据。
Native端
以iOS端为例:我们构建一个UIAlertController用以输入代理地址:
在Appdelegate里设置延迟2s执行,保证flutter引擎已经初始化。
#ifdef DEBUG
//延时处理,立即处理的话,引擎还没有初始化完成
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2*NSEC_PER_SEC),dispatch_get_main_queue(), ^{
[self showFlutterDelegateAlertController];
});
#else
#endif
弹框代码:
//设置Flutter代理弹框
- (void)showFlutterDelegateAlertController {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:@"输入代理" preferredStyle:UIAlertControllerStyleAlert];
//增加取消按钮;
[alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}]];
//增加确定按钮;
[alertController addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//获取第1个输入框;
UITextField *delegateField = alertController.textFields.firstObject;
if (delegateField.text.length>0){
//一下代码为调取flutter端代码
[PlatformRouterImp sharedRouter].nativeCallFlutterEventSink(delegateField.text);
}
}]];
//定义第一个输入框;
[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
textField.placeholder = @"(测试抓包专用,不用输端口)";
}];
[self.window.rootViewController presentViewController:alertController animated:true completion:nil];
}
PlatformRouterImp为自己封装的一个两端通信的类。只需设置FlutterViewController时先为其设置Eventchannel通道
- (void)setupNativeCallFlutter {
if (!self.flutterViewController) return;
// 用于Native调用Flutter
FlutterEventChannel *nativeCallFlutterChannel = [FlutterEventChannel eventChannelWithName:NativeCallFlutter binaryMessenger:self.flutterViewController];
[nativeCallFlutterChannel setStreamHandler:self];
}
设置完通道后设置数据监听函数
- (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)events
{
self.nativeCallFlutterEventSink = events;
return nil;
}
- (FlutterError*)onCancelWithArguments:(id)arguments {
//[[NSNotificationCenter defaultCenter] removeObserver:self];
NSLog(@"停止发送数据");
return nil;
}
Flutter端
在main函数里监听EventChannel数据流
static const EventChannel eventChannel =
EventChannel('samples.flutter.dev/nativeCallFlutter');
@override
void initState() {
super.initState();
eventChannel.receiveBroadcastStream().listen(_onEnvent, onError: _onError);
}
为网络框架设置代理地址,这里以dio为例
void _onEnvent(Object obj) {
setState(() {
print('接收到eventChannel:$obj');
//TODO:设置dio代理
Http2Client _client = Http2Client.getInstance();
(_client.getDio().httpClientAdapter as DefaultHttpClientAdapter)
.onHttpClientCreate = (HttpClient client) {
client.findProxy = (uri) {
//proxy all request to localhost:8888
print('设置了代理:PROXY $obj:8888');
return "PROXY $obj:8888";
};
client.badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
};
});
}
void _onError(Object obj) {
print('失败:$obj');
}
至此,可在原生界面为Flutter端设置网络代理里。
网友评论