美文网首页Flutter圈子Flutter中文社区Flutter
Flutter无法抓包?教你如何利用Eventchannel设置

Flutter无法抓包?教你如何利用Eventchannel设置

作者: _Raymon_ | 来源:发表于2020-06-12 09:56 被阅读0次

    当前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端设置网络代理里。

    相关文章

      网友评论

        本文标题:Flutter无法抓包?教你如何利用Eventchannel设置

        本文链接:https://www.haomeiwen.com/subject/vgmbtktx.html