安装 flutter

  1. 下载 flutter SDK,地址:
https://flutter.dev/docs/get-started/install/macos
  1. 解压缩:
unzip ~/Downloads/flutter_macos_v1.7.8+hotfix.4-stable.zip
  1. 添加路径到 path 变量:
open -e .bash_profile

在 .bash_profile 中编辑:

export PATH=${PATH}:下载的文件夹路径/flutter/bin:$PATH

刷新 .bash_profile:

source .bash_profile
  1. 检查:
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 插件


flutter iOS 无线调试 flutter写ios_ios

安装后需重启 Android Studio。

创建插件工程并引入第三方依赖

  1. 创建插件工程 zhgd_native_plugin。
  2. 默认插件工程使用项目名称 zhgd_native_plugin 作为通道名,我们需要修改通道名为你和 flutter 端约定的通道名,比如 origin_channel:
  1. 搜索 MethodChannel(,将通道名称从 zhgd_native_plugin 修改为你和 flutter 端约定的通道名称 origin_channel。
  2. 搜索 @“zhgd_native_plugin”,将 o-c 代码中的通道名称修改为 @“origin_channel”。
  1. 默认插件工程调用的方法名为 getPlatformVersion,我们需要修改方法名为你和 flutter 端约定的方法名,比如 hello:
  1. 搜索 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 参数。

  1. 拷贝 include 目录和 lib 目录到 ios/Classes 目录下
  2. 将 .h/.m 文件拷贝到 ios/Classes 目录下
  3. 打开插件的 .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!。二者保持一致,否则会出现各种问题。

  1. 将图片等静态资源拷贝到 ios/Assets 下。这样打包后,会在 Pods 工程的 Development Pods/<插件名称>/ 下多出一个 Resources 目录,图片资源会放到这个目录下。
  2. Open iOS module in Xcode 功能打包。如果出现错误,可以进入 example 目录,手动打包:
flutter --no-color build ios --no-simulator

因为这个插件只支持真机,不支持模拟器,所以需要使用 --no-simulator 选项。

  1. 打完包后,进入 example/ios 目录,用 Xcode 打开 Runner.xcworkspace 文件,然后 pod install。
  2. 修改 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);
}

}

```
  1. 修改开发者签名,选择真机设备,编译运行。

最好每完成一个步骤,都运行一下,并用 Xcode 打开再运行一下,以保证所有环节都正常。如果某些步骤出现运行不起来的情况,重新创建插件工程,然后从头再来。

常见问题

flutter 无法在真机上运行

  1. 安装 Xcode 命令行工具:xcode-select --install
  2. 重启终端。
  3. 安装 usbmuxd:
brew install --HEAD usbmuxd
  1. 创建软连接:
brew link usbmuxd
  1. 安装 imobiledevice:
brew install --HEAD libimobiledevice
  1. 如果报错 syntax error near unexpected token `libusbmuxd,’,则需要执行:
brew link --overwrite pkg-config

再重新安装。

  1. 如果报错 Package requirements (libusbmuxd >= 1.1.0) were not met,说明你安装的 usbmuxd 版本 < 1.1,则需要用以下方式安装:
  1. 卸载 usbmuxd :
brew uninstall --ignore-dependencies usbmuxd
  1. 重新安装 usbmuxd :
brew install --HEAD usbmuxd
  1. 重新创建 usbmuxd 的连接:
brew unlink usbmuxd
 brew link usbmuxd
  1. 重新安装 libimobiledevice:
brew install --HEAD libimobiledevice
  1. 安装 ideviceinstaller:
brew install ideviceinstaller
  1. 安装 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 ‘(’

  1. 在 o-c 文件中调用了 c++ 代码,将 o-c 文件修改为 o-c++ 文件(将文件后缀名从 .m 修改为 .mm)。
  2. 将.h文件File Type改为Objective C++ Preprocessed Source,默认C Header.