插件介绍

一个代码生成工具,让Flutter和宿主平台更安全、更简单、更快地通信。通过Dart入口,生成两端通用的模板代码,原生则只需重写模板内的接口,无需管理Meios应用商店thod Channel的实现。参数可以通过模板来同步生成。这样确实方便很多,关于系统的三种方式可以参考这篇文章(Flutter 与原生通信的三种方式)。

插件信息

插件地址:pub.flutter-io.cn/packages/pi…实体类图

插件版本:pigeon: 3.0.3

插件的使用

Flutter的准备工作

在Flutter项目的lSwiftib目录外创建一个pige初始化电脑的后果ons文件夹,在pigeons文件夹中创建schema.dart

因为目前是原生和Flutter混编,我需要从原生获取用户信息和获取l通信地址是写什么地址ocalHost,所以schema.dart的代码如下

/// Description : 定义与原生通信--通过自动生成减少手写代码量
/// 请求参数和返回结果都必需是类结构 否则无法生成文件
/// - Flutter 调用 Native 方法 ( @HostApi() )
/// - Native 调用 Flutter 方法 ( @FlutterApi() )
///Flutter 调用原生代码
@HostApi()
abstract class UserInfoApi {
  ///获取用户信息
  UserInfo getUserInfo();
  ///获取LocalHost用于抓包
  String getLocalHost();
}
///用户信息实体类
class UserInfo {
  String? userId;
  String? realName;
  String? phone;
  String? headImg;
}

使用到的命令

命令拆解:
①` flutter pub run pigeon`  
生成代码的命令
②` --input pigeons/schema.dart `
指定生成代码的输入`dart`文件
③ `--dart_out lib/schema.dart `
指定输出生成`dart`文件的目录文件
④ `--objc_header_out ios/Flutter/FlutterPluginRegistrant/Classes/schema.h  `
指定要生成的`iOS`的`.h`文件路径
⑤ `--objc_source_out ios/Flutter/FlutterPluginRegistrant/Classes/schema.m  `
指定要生成的`iOS`的`.m`文件路径
⑥ `--java_out android/Flutter/src/main/java/io/flutter/plugins/Schema.java `
指定要生成的`Android`的`.java`文件路径
⑦  `--java_package "io.flutter.plugins`
指定`Android`的包名,在`android/src/main/`下的`AndroidManifest.xml`里的`package`
⑧ `--objc_prefix Z`(可选)指定生成OC文件的前缀为Z,前缀自己定义为自己的。

在项目目录~/flutter_pigeon_plugin下,直接执行,命令太麻烦了,这通信地址是写什么地址里我就创建了一个脚本ios15,每次有更新的时候直接运行脚本就可以了。

创建脚本

这个脚本就是根据上面的命令写的,这个也是在pigeons文件夹创建的run pigeon.sh脚本。

flutter pub run pigeon 
  --input pigeons/schema.dart 
  --dart_out lib/schema.dart 
  --objc_header_out ios/Flutter/FlutterPluginRegistrant/Classes/schema.h 
  --objc_source_out ios/Flutter/FlutterPluginRegistrant/Classes/schema.m 
  --java_out android/Flutter/src/main/java/io/flutter/plugins/Schema.java 
  --java_package "io.flutter.plugins"
  # 点击绿色三角形按钮,或者选择文件右键选择运行此文件,开启运行以上脚本文件,
  # 然后会自动生产跨端通信的Android文件(Java文件)和iOS文件(Object_C)
 No newline at end of file

这个就是运行脚本后自动生成的文件

Flutter-官方推荐的Flutter与原生交互插件Pigeon

Flutter-官方推荐的Flutter与原生交互插件Pigeon

Flutter-官方推荐的Flutter与原生交互插件Pigeon

如何进行通信呢?

举个例子:上面我不是写了两个方法,那假如我想抓包,就需要设置成Mac的ip

Flutter端代码初始化电脑时出现问题

if (!kReleaseMode){
  UserInfoApi().getLocalHost().then((value) {
    if(value.isNotEmpty){
      (_dio!.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (HttpClient client) {
        client.findProxy = (uri) {
          return "PROXY $value:8888";
        };
      };
    }
  });
}

原生端代码

首先肯定要把Flswift翻译utter Modswift系统ule引入原生工程,这里就不做说明了。创建了一个类继承自FlutterViewController

- (void)viewDidLoad {
  [super viewDidLoad];
 
  [GeneratedPluginRegistrant registerWithRegistry:self.engine];
    //这里是需要传入一个对象的
  UserInfoApiSetup(self.binaryMessenger, [UserInfoAPI new]);
}
- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
  self.navigationController.navigationBarHidden = YES;
}
- (void)viewWillDisappear:(BOOL)animated {
  [super viewWillDisappear:animated];
  self.navigationController.navigationBarHidden = NO;
}

初始化电脑的后果需要创建一个遵循UserInfoApi协议的类,并且实现ios15协议方法

@interface UserInfoAPI : NSObject<UserInfoApi>
@end
@implementation UserInfoAPI
- (nullable UserInfo *)getUserInfoWithError:(FlutterError * _Nullable __autoreleasing * _Nonnull)error {
  UserInfo *userInfo = [[UserInfo alloc] init];
  return userInfo;
}
- (nullable NSString *)getLocalHostWithError:(FlutterError * _Nullable * _Nonnull)error {
  return @"10.210.3.16";
}
@end

FlutteiOSr页面返回原生页面

这样就实现了Flutter调用原生的方法,一般我们跳转到Flutter页面中,想返回原生页面也可以实现,通过调用原生的方法,原ios14.4.1更新了什么生处理返回,比如iOS端可以这ios模拟器样实现

if ([mthodStr isEqualToString:@"closeFlutterVC"]) {
   //调用popViewControllerAnimated
}

Flutter返回Android端则直接可以调用方法完成

SystemNavigator.pop();

原生进入Flutter页面

//这里可以传入要进入flutter页面的路由
TestViewController *flutterVC = [[IAskFlutterViewController alloc] initWithProject:nil initialRoute:@"" nibName:nil bundle:nil];[self.navigationController pushViewController:flutterVC animated:YES];

Android端其实也是同理,实现getInitialRouswift语言teios越狱ios应用商店法,返回要跳转页面的路由即可。

Flutter集成iOS原生遇swift翻译到的问题汇总:

下面列举一些最近在进行混编时遇到的一些问题:

Faios是苹果还是安卓iled to register observa初始化英文tory port with mDNS with error -65555.

官方描述

On iOS 14 and higher, enable the Dart multicast DNS service in the Debug version of your app to add debugging functionalities s实体类的定义uch as hot-swift是什么意思啊reload and Devios14.4.1更新了什么Tooswift国际结算系统ls via fl实体类图utter attac通信达h.

解决方法

  • 将应用程序的Info.plist重命名为Info-Debug.plist。复制一个名为Info-Release.plist的副本,并将其添ios应用商店加到Xcode项目中

Flutter-官方推荐的Flutter与原生交互插件Pigeon

  • 在Info-Debug.plist中初始化是什么意思,添加键 Bonjour services 并将值设置为_dartobservatory._tcp

可选的设置Privacy - Local Network Usage Dios下载escription,并将值设置为Allow Flutter tools on your computer to connect and debug your application.This prompt will not apios14.4.1更新了什么pear on rele实体类型ase builds通信行程卡.

Flutter-官方推荐的Flutter与原生交互插件Pigeon

  • 在TA初始化磁盘RGETS中, build settings 修改Info.plist File路径 path/to/Info.plist 为 path/to/Info-$(CONFIGURATIONswift系统).plist.

Flutter-官方推荐的Flutter与原生交互插件Pigeon

In iOS 14+,debug mode Flutter apps can only be launched from Flutter tooling,IDEs with Flutter pl…

Flutter-官方推荐的Flutter与原生交互插件Pigeon

分析原因

在 iOS14 的真机上安装了 debug模式 编通信行程卡下载app译出来的 flutter 应用,那么在断开编译安装连接后,将无法从桌面上打开该应用程序

解决方案

  1. 使用flutter的release模式,终端输入
flutter run --release
  1. 修改main.dart的配置

Flutter-官方推荐的Flutter与原生交互插件Pigeon

Flutter-官方推荐的Flutter与原生交互插件Pigeon

Reason: tried: ‘/usr/lib/swift/App.framework/App’ (no such file), ‘/usr/lib/swift/App.framework/App’ (no such file),

分析原因

FlutterApp.framework没有导入

解决办法

打开Pods-xx-frameworks.sh,然后添加以下代码

install_framework "${PODS_ROOT}/../flutter/.ios/Flutter/App实体类是什么.framework"

但是这样只能一时解决问题,下次poios是苹果还是安卓d install后又没有这个配置了,终极解决办法是:

重装Cocoapods和ruby-通信人家园macho:

卸载ruby-macho和Cocoapods
sudo gem uninstall ruby-macho
sudo gem uninstall cocoapods
重新安装ruby-macho和Cocoapods
sudo gem install ruby-macho
sudo gem install cocoapods

No podspec foun初始化游戏启动器失败d for Flutter in ../flutteios14.4.1更新了什么r/.初始化英文i初始化os/Flut通信ter/engiiOSne

分析原因

这个是在这个路径下缺少这个文件

解决办法

可以看下其他Flutter项目下,是否有这个文件直接拷贝过来,这个就是和Flut初始化sdk什么意思ter引擎相关的ios模拟器文件。假如有ios文件夹,看下这个文件下有没有那个文件

Undefined symbol: OBJC_CLASS$_TestViewController

Flutter-官方推荐的Flutter与原生交互插件Pigeon

iOS析原因

这个是我创建一个继承自FlutterViewController的类,没有发现

解决办法

在这个里面添加这个类的.m文件即可

Flutter-官方推荐的Flutter与原生交互插件Pigeon

底部Wios15idget不跟随键盘弹起而弹起

分析原因

默认resizeToAvoidBottomInset:true,Scaffold 内部会将 mediaQuery.viewInsets.bottom 参与到 B实体类型oxConstraints 的大小计算,也就是键盘弹起时调整了内部的 bottom 位置来迎合ios下载键盘。

解决办法

设置 resizeToAvoidBottomInset: false

MissingPluginException(No implementat通信工程ion found for method resetPlugin on channel com.dooboolab.初始化英文flutter_sound_player)

9.2.13版本以前,假如是iOS和Flutter混编项目,如果首次进入Flutte初始化失败是怎么解决r模块,这个插件使用是没有问题的,但是当离开这个模块第二次进入就会出现注册插件出错、初始化失败的情况。报错如下:

ERROR during registerWithRegistrar: flutterSoundPlayerManager != nil
MissingPluginException(No implementation found for method resetPlugin on channel com.dooboolab.flutter_sound_player)

分析原因

这是第二次进入,注册失败,其他插件都能初始化电脑时出现问题未进行更改正常注swift是什么组织缩写册,后来提了问题给开发人员

解决办法

这是插件确实存在的b初始化电脑时出现问题未进行更改ug,目前作者已通信人家园经在最新版本9.2.13上做了修复。swifter

后续再遇到新的问题,swifter会继续更新的~

总结

由于以前都是使用原生的通信方式,那种确实麻烦实体类的定义一些,使用这个插件的方式确实比较简单。但是这样有点增加了代码阅读的难度,没有直接原生通信的可读性高,凡事都有两面性就看自己去衡量了。