开发 flutter原生ios插件
安装 flutter
-
下载 flutter SDK,地址:
https://flutter.dev/docs/get-started/install/macos
-
解压缩:
unzip ~/Downloads/flutter_macos_v1.7.8+hotfix.4-stable.zip
-
添加路径到 path 变量:
open -e .bash_profile
在 .bash_profile 中编辑:
export PATH=${PATH}:下载的文件夹路径/flutter/bin:$PATH
刷新 .bash_profile:
source .bash_profile
-
检查:
flutter doctor
结果如下:
[✓] Xcode - develop for iOS and macOS (Xcode 10.3)
[✗] iOS tools - develop for iOS devices
✗ libimobiledevice and ideviceinstaller are not installed. To install with
Brew, run:
brew update
brew install --HEAD usbmuxd
brew link usbmuxd
brew install --HEAD libimobiledevice
brew install ideviceinstaller
✗ ios-deploy not installed. To install:
brew install ios-deploy
[!] Android Studio (version 3.4)
✗ Flutter plugin not installed; this adds Flutter specific functionality.
✗ Dart plugin not installed; this adds Dart specific functionality.
[!] IntelliJ IDEA Ultimate Edition (version 2018.2.7)
✗ Flutter plugin not installed; this adds Flutter specific functionality.
✗ Dart plugin not installed; this adds Dart specific functionality.
[!] VS Code (version 1.32.3)
✗ Flutter extension not installed; install from
https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[✓] Connected device (1 available)
```
这些错误中,我们只需要关心 Android Studio 插件的问题。接下来安装 Androi Studio 插件。
安装 Android Studio 插件
安装后需重启 Android Studio。
创建插件工程并引入第三方依赖
-
创建插件工程 zhgd_native_plugin。
-
默认插件工程使用项目名称 zhgd_native_plugin 作为通道名,我们需要修改通道名为你和 flutter 端约定的通道名,比如 origin_channel:
- 搜索 MethodChannel(,将通道名称从 zhgd_native_plugin 修改为你和 flutter 端约定的通道名称 origin_channel。
- 搜索 @“zhgd_native_plugin”,将 o-c 代码中的通道名称修改为 @“origin_channel”。
-
默认插件工程调用的方法名为 getPlatformVersion,我们需要修改方法名为你和 flutter 端约定的方法名,比如 hello:
-
搜索 getPlatformVersion,将 zhgd_native_plugin.dart 中的
final String version = await _channel.invokeMethod('getPlatformVersion');
一句修改为:await _channel.invokeMethod(
‘hello’,
{
“code”: “1000001”,
“codeType”: 1,
“port”: 36357,
“createTime”: “2019-08-22 19:02:43”,
“ip”: “26o0e91123.wicp.vip”,
“effect”: 1,
“channel”: 0,
“updateTime”: “2019-08-22 19:02:43”,
“id”: 1,
“username”: “admin”,
“name”: “1号摄像头”,
“describe”: “1号门位置”
}
);
return “hello”;
```hello 方法需要一个 map 参数。
-
-
拷贝 include 目录和 lib 目录到 ios/Classes 目录下
-
将 .h/.m 文件拷贝到 ios/Classes 目录下
-
打开插件的 .podspec 文件,添加:
# 引入 lib 中所有静态库 s.vendored_libraries = 'Classes/lib/*.a' # 引入第三方 pod s.dependency 'MBProgressHUD' s.dependency 'Masonry' # 引入系统 framework s.frameworks = 'UIKit','Foundation','CoreMedia','AudioToolbox','VideoToolbox' # 引入系统静态库 s.libraries = 'stdc++' # 引入图片资源 s.resources = ['Assets/*.png'] # iOS 兼容版本 s.ios.deployment_target = '10.0' # 只支持真机,不支持模拟器,去掉 x86_64\i386 valid_archs = ['arm64','arm64e','armv7','armv7s'] s.xcconfig = { 'VALID_ARCHS' => valid_archs.join(' '), } # 使用 use_frameworks!, s.static_framework = true
s.static_framework 这句很关键,如果 flutter 项目中使用了 Swift 库,则必须在 Podfile 中使用 use_frameworks!,那么插件工程也必须 use_frameworks!。二者保持一致,否则会出现各种问题。
-
将图片等静态资源拷贝到 ios/Assets 下。这样打包后,会在 Pods 工程的 Development Pods/<插件名称>/ 下多出一个 Resources 目录,图片资源会放到这个目录下。
-
Open iOS module in Xcode 功能打包。如果出现错误,可以进入 example 目录,手动打包:
flutter --no-color build ios --no-simulator
因为这个插件只支持真机,不支持模拟器,所以需要使用 --no-simulator 选项。
-
打完包后,进入 example/ios 目录,用 Xcode 打开 Runner.xcworkspace 文件,然后 pod install。
-
修改 ZhgdNativePlugin.m 文件的 handleMethodCall 方法:
#import "DHAPI.h" #import "LivePreviewViewController.h" ... ... -(void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result{ if ([[call method] isEqualToString:@"hello"]) { FlutterAppDelegate* delegate = (FlutterAppDelegate*)[[UIApplication sharedApplication]delegate]; FlutterViewController* rootVC = (FlutterViewController*)delegate.window.rootViewController; LoginForm* form = [LoginForm new]; form.IP = call.arguments[@"IP"]; form.port = call.arguments[@"port"]; form.userName = call.arguments[@"userName"]; form.password = call.arguments[@"password"]; form.name = call.arguments[@"name"]; form.describe = call.arguments[@"describe"]; [DHAPI IPLogin:form success:^(LoginResult * _Nonnull result) { NSLog(@"登录成功:loginID = %ld,channel = %d",result.loginId,result.channel); LivePreviewViewController* vc = [LivePreviewViewController new]; vc.loginInfo = result; [rootVC presentViewController:vc animated:YES completion:nil]; } failed:^(NSError * _Nonnull error) { NSLog(@"%@",error.localizedDescription); }]; } else { result(FlutterMethodNotImplemented); }
}
```
- 修改开发者签名,选择真机设备,编译运行。
最好每完成一个步骤,都运行一下,并用 Xcode 打开再运行一下,以保证所有环节都正常。如果某些步骤出现运行不起来的情况,重新创建插件工程,然后从头再来。
常见问题
flutter 无法在真机上运行
-
安装 Xcode 命令行工具:xcode-select --install
-
重启终端。
-
安装 usbmuxd:
brew install --HEAD usbmuxd
-
创建软连接:
brew link usbmuxd
-
安装 imobiledevice:
brew install --HEAD libimobiledevice
-
如果报错 syntax error near unexpected token `libusbmuxd,’,则需要执行:
brew link --overwrite pkg-config
再重新安装。
-
如果报错 Package requirements (libusbmuxd >= 1.1.0) were not met,说明你安装的 usbmuxd 版本 < 1.1,则需要用以下方式安装:
-
卸载 usbmuxd :
brew uninstall --ignore-dependencies usbmuxd
-
重新安装 usbmuxd :
brew install --HEAD usbmuxd
-
重新创建 usbmuxd 的连接:
brew unlink usbmuxd brew link usbmuxd
-
重新安装 libimobiledevice:
brew install --HEAD libimobiledevice
-
-
安装 ideviceinstaller:
brew install ideviceinstaller
-
安装 ios-deploy:
brew install ios-deploy
Flutter 卡在 package get 的解决办法
storage.googleapis.com 被墙了,解决办法是编辑 .bash_profile 文件,添加两个环境变量:
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
Invalid VCS root mapping
点击 Configure…,找到 Version Control->Directory,将红色的 删除,然后 Apply。
执行命令行 flutter build 出错:Target file “lib/main.dart” not found.
这是一个插件工程,有两个 main.dart,你可能执行错了。插件工程本身是不能执行的,你应该执行实际上应该是插件工程下面的 example 工程。你应该进入 example 目录下执行命令,这样才会选择 example/lib 目录下的 main.dart 文件。
编译 Xcode 工程时报错 Expected identifier or ‘(’
- 在 o-c 文件中调用了 c++ 代码,将 o-c 文件修改为 o-c++ 文件(将文件后缀名从 .m 修改为 .mm)。
- 将.h文件File Type改为Objective C++ Preprocessed Source,默认C Header.