安装 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.