深色模式
Flutter创建插件的步骤
说明
Flutter插件是一种用于封装平台特定代码的组件,它通过方法通道(Method Channel) 将Dart代码与平台(如Android和iOS)代码连接起来。插件可以使Flutter应用访问原生平台的功能,如相机、地理位置、蓝牙等。
开发插件的步骤:
- 定义插件Dart API
- 编写原生平台代码
- 连接Dart与原生平台
另外:
联合插件:将原生平台代码拆分为单独的包,并组合到主插件包中,参考:Federated plugins
共享iOS与macOS平台的代码:要在插件中共享iOS与macOS平台的代码,参考:Shared iOS and macOS implementations
下面讨论开发插件的步骤。
创建项目
创建一个名为hello的插件,支持Android、iOS:
sh
flutter create --template plugin --platforms android,ios --project-name hello --org com.example hello-plugin
项目结构:
hello_plugin/
├── android/
│ └── src/... # Android平台代码
├── example/ # 示例项目,它把外层的插件项目当作依赖,用于测试与演示。
├── ios/
│ └── Classes/... # iOS平台代码
├── lib/
│ └── hello.dart # Dart接口,插件的API
├── pubspec.yaml # 包配置
主要代码:
yaml
name: hello
description: "A new Flutter plugin project."
version: 0.0.1
homepage:
environment:
sdk: ^3.5.3
flutter: '>=3.3.0'
dependencies:
flutter:
sdk: flutter
plugin_platform_interface: ^2.0.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^4.0.0
flutter:
plugin:
platforms:
android:
package: com.example.hello
pluginClass: HelloPlugin
ios:
pluginClass: HelloPlugin
dart
import 'hello_platform_interface.dart';
class Hello {
Future<String?> getPlatformVersion() {
return HelloPlatform.instance.getPlatformVersion();
}
}
kotlin
package com.example.hello
import androidx.annotation.NonNull
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
/** HelloPlugin */
class HelloPlugin: FlutterPlugin, MethodCallHandler {
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private lateinit var channel : MethodChannel
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "hello")
channel.setMethodCallHandler(this)
}
override fun onMethodCall(call: MethodCall, result: Result) {
if (call.method == "getPlatformVersion") {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
} else {
result.notImplemented()
}
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}
}
swift
import Flutter
import UIKit
public class HelloPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "hello", binaryMessenger: registrar.messenger())
let instance = HelloPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "getPlatformVersion":
result("iOS " + UIDevice.current.systemVersion)
default:
result(FlutterMethodNotImplemented)
}
}
}
实现
创建的项目中,已包含简单的实现代码,下面说明一下:
定义插件API
编辑lib/hello.dart
,定义API。
在lib/hello.dart
中,默认定义了一个getPlatformVersion
方法。
实现Android平台
编译example
为了顺利打开项目,先编译一次hello/example
项目:
sh
flutter build apk --config-only
打开example
编译后,使用Android Studio打开
hello/example/android/build.gradle
。WARNING
是打开示例项目
hello/example/android/build.gradle
,不是外层的hello/android/build.gradle
!打开后,进行Gradle Sync。
实现API
编辑HelloPlugin.kt
,实现API。
实现iOS平台
编译example
为了顺利打开项目,先编译一次hello/example
项目:
sh
flutter build ios --no-codesign --config-only
打开example
编译后,使用XCode打开hello/example/ios/Runner.xcworkspace
。
实现API
编辑HelloPlugin.swift
。
如果要添加CocoaPod依赖,参考:Add CocoaPod dependencies
连接Dart与平台代码
连接的原理是Method Channel。
在lib/hello.dart
中,已有默认代码。
记录
Android
获取ApplicationContext
kotlin
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
val context = flutterPluginBinding.applicationContext
}
获取Activity
kotlin
class HelloPlugin : FlutterPlugin, ActivityAware {
private var activity: Activity? = null
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
activity = binding.activity
}
override fun onDetachedFromActivityForConfigChanges() {
activity = null
}
override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
activity = binding.activity
}
override fun onDetachedFromActivity() {
activity = null
}
}
iOS
获取UIViewController
swift
let viewController = UIApplication.shared.keyWindow?.rootViewController