最近准备使用 Flutter 做点小东西,可能会涉及到与原生的交互,参考 使用平台通道编写平台特定的代码 这篇文章实践了一下,记录一下过程和其中遇到的问题。
实践环境说明
- macOS Big Sur
- Vistual Studio Code
- Flutter 1.22.6
- Dart 2.10.5
- Xcode 12.4
创建工程
环境的搭建我略过了,如果有需要可以后续在写一篇实践篇。
- 按照文档,在想要创建工程的文件夹打开命令行,直接使用
flutter create -i swift -a kotlin batterylevel
(因为想使用 swift 和 kotlin,如果使用 java 和 Objective-C 可以直接使用flutter create batterylevel
命令 )创建一个显示设备电量的工程,这一步没有什么问题。 - 创建完成后在命令行先使用
open -a Simulator
打开一个模拟的手机。 - 在命令后内输入 flutter run ,可以使工程在模拟的手机内运行,可以看到一个简易的页面。
添加 Flutter 代码调用函数
- 首先声明一个
MethodChannel
,MethodChannel
的参数名称为通道名称,在单个应用中应该唯一。
static const platform = const MethodChannel("samples.flutter.io/battery");
- 声明显示电量的字符串
String _batteryLevel = 'Unknown battery level.';
- 声明一个获取电量函数调用原生代码
Future<Null> _getBatteryLevel() async {
String batteryLevel;
try {
final int result = await platform.invokeMethod('getBatteryLevel');
batteryLevel = 'Battery level at $result %.';
} on PlatformException catch (e) {
batteryLevel = "Failed to get battery level: '${e.message}'. ";
}
setState(() {
_batteryLevel = batteryLevel;
});
}
- 定义控件,一个
RaisedButton
用于点击获取电量交互,一个Text
用于显示电量。两个控件放到Widget
的数组内。
RaisedButton(
child: new Text('Get Battery Level'),
onPressed: _getBatteryLevel,
),
Text(_batteryLevel)
ios 获取电池电量
- 使用 Xcode 打开项目内的 ios 文件夹。
- 打开 AppDelegate.swift 文件,修改 application 函数为
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self);
let controller: FlutterBinaryMessenger = window?.rootViewController as! FlutterBinaryMessenger;
let batteryChannel = FlutterMethodChannel.init(name: "samples.flutter.io/battery", binaryMessenger: controller);
batteryChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: FlutterResult) -> Void in
if ("getBatteryLevel" == call.method) {
receiveBatteryLevel(result: result)
} else {
result(FlutterMethodNotImplemented)
}
})
return super.application(application, didFinishLaunchingWithOptions: launchOptions);
}
不知道是不是因为 Flutter 更新的原因, 这里我参照文档的时候发现文档有个地方有问题。FlutterMethodChannel.init
的 binaryMessenger
参数类型是 FlutterBinaryMessenger
, 但是参考文档里面写的是 FlutterViewController
, 所以我声明的 controller
是 FlutterBinaryMessenger
.
然后在该文件的最后添加获取电池电量函数,参考文档里面 UIDeviceBatteryState
这个提示找不到,后来我查看了 UIDevice
的文档,发现应该是 UIDevice.BatteryState
。
private func receiveBatteryLevel(result: FlutterResult) {
let device = UIDevice.current;
device.isBatteryMonitoringEnabled = true;
if (device.batteryState == UIDevice.BatteryState.unknown) {
result(FlutterError.init(code: "UNAVAILABLE", message: "Battery info unavailable", details: nil))
} else {
result(Int(device.batteryLevel * 100))
}
}
运行程序
在工程目录打开命令行,输入 flutter run,运行项目,稍等一会 app 会安装到模拟的手机中,点击 Get Battery Level 按钮,发现电量显示 Battery info unavailable
。我发现是因为模拟器的 UIDevice.batteryState
就是为UIDevice.BatteryState.unknown
,所以为了测试获取电量正确还得连接真机。
如果需要连接真机得设置 Signing & Capabilities
, 点击 Runner
,在页面中选择 Signing & Capabilities
,在 Team 的选择框中选择 Add an Account,输入自己的 Apply Id 用户名和密码就可以了,成功后确保没有报错,我遇到输入的 Bundle Identifier 已经存在,重新换一个就好了。如果有报错会在这个页面的 Status 里面显示,仔细阅读可以解决。我之前网上搜索说需要添加 iOS Development,但是我的 Xcode 是不需要的,只有一个 Apple Development。连接上真机后,继续 flutter run。然后点击 Get Battery Level 按钮,发现可以显示出实际的电量。到此 Flutter 调用 iOS 就完成了。
注意:需要在 iPhone 的设置中信任该 app
如果你有多个设备,可以先使用 flutter devices 查看设备的 id。
然后 flutter run -d 设备ID,指定运行的设备。
其他问题
- 遇到 Xcode 工程中的
Debug.xcconfig
和Release.xcconfig
引用了Generated.xcconfig
,但是项目中没有Generated.xcconfig
,可以按照下面步骤解决- flutter clean (in terminal)
- flutter build (in terminal)
- In Xcode, then clean project
- In Xcode, then build project
- 提示 Info.plist does not exist. The Flutter "Thin Binary" build phase must run after "Copy Bundle Resources". 我 clean 一下之后在重新 build 解决了。
参考资料
- 使用平台通道编写平台特定的代码
- UIDevice
- Could not find included file 'Generated.xcconfig' in search paths (in target 'Runner')
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!