Flutter 原生插件开发流程

4,265 阅读2分钟

一、Package类型

1、纯Dart库

用Dart编写的传统package,依赖于Flutter框架,使用返回仅限于Flutter;

2、原生插件

使用Dart编写,按需使用Java(kotlin)或Objc(Swift),分别在Android 和 iOS平台实现的package。

二、原生插件类型的Package的开发

1、创建Package

flutter create --org com.example --template=plugin pluginName

默认情况下,iOS代码使用swift语言编写,Android代码使用Kotlin语言编写。但是你可以通过 -i 指定iOS的语言;-a指定Android的开发语言。

flutter create --template=plugin -i objc -a java pluginName

pluginName目录下会创建一个插件工程:

  • lib/pluginName.dart:
    • Dart 插件 API 实现。
  • android/src/main/java/com/example/​hello/PluginNamePlugin.kt:
    • Android 平台原生插件 API 实现。
  • ios/Classes/PluginNamePlugin.m:
    • iOS 平台原生插件 API 实现。
  • example/:
    • 一个依赖于该插件并说明了如何使用它的 Flutter 应用。

2、实现Package

2.1、定义PackageApi(.dart部分)

原生插件类型 package 的 API 在 Dart 代码中要首先定义好,使用 Flutter 编辑器,打开 pluginName/ 主目录,并找到 lib/pluginName.dart 文件。

这一步定义了与原生交互的字段等信息。

2.2、Android平台

  • 编译apk
    • 进入pluginName/example目录下;
    • 运行 flutter build apk
  • 进入工程pluginName/example/Android
    • PluginNamePlugin.kt下添加Android代码;
  • Project Structure目录下
    • Modules中,pluginName_androidpluginName_example_android下的sources可以去掉
  • 运行即可查看结果。
  • 示例代码
class FlutterCryptoPlugin: MethodCallHandler {
  @JvmField val CHARSET = Charsets.UTF_8

  companion object {
    @JvmStatic
    fun registerWith(registrar: Registrar) {
      val channel = MethodChannel(registrar.messenger(), "flutter_crypto_plugin")
      channel.setMethodCallHandler(FlutterCryptoPlugin())
    }
  }

  override fun onMethodCall(call: MethodCall, result: Result) {
    if (call.method == "getPlatformVersion") {
      result.success("Android ${android.os.Build.VERSION.RELEASE}")
    } else if (call.method == "...") {
		// todo
    } else {
      result.notImplemented()
    }
  }
}

2.3、iOS平台

  • 编译
    • 进入pluginName/example目录;
    • 执行flutter build ios --no-codesign
  • 如果需要第三方
    • 进入文件pluginName.podspec文件;
    • 添加需要的第三方,示例:s.dependency 'CryptoSwift', '~> 0.13.1'
  • 用xcode打开pluginName/example/ios/Runner.xcworkspace
    • 插件代码位于Pods/DevelopmentPods/hello/Classes/
  • 示例代码
public class SwiftFlutterCryptoPlugin: NSObject, FlutterPlugin {
      
    public static func register(with registrar: FlutterPluginRegistrar) {
        let channel = FlutterMethodChannel(name: "flutter_crypto_plugin", binaryMessenger: registrar.messenger())
        let instance = SwiftFlutterCryptoPlugin()
        registrar.addMethodCallDelegate(instance, channel: channel)
    }
    
    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        if call.method == "getPlatformVersion" {
            result("iOS " + UIDevice.current.systemVersion)
        } else if call.method == "..." {
        // todo 
        } else {
        	result(FlutterMethodNotImplemented)
        }
   }
}

3、添加文档

  • README.md:介绍包的文件
  • CHANGELOG.md 记录每个版本中的更改
  • LICENSE 包含软件包许可条款的文件
  • 所有公共API的API文档 (详情见下文)

4、发布Package

4.1、运行 dry-run 命令以查看是否都准备OK

flutter packages pub publish --dry-run

4.2、运行发布

flutter packages pub publish

5、本地添加开发的Package

5.1、上传到了pub

dependencies:
  flutter:
    sdk: flutter
  // 三方包
  pluginName: ^0.0.1

5.2、本地添加

dependencies:
    // 包名
    pluginName:
        // 本地包路径:可以是相对路径,也可以是绝对路径
        path: ../../code/pkg1

5.3、git远程仓库

dependencies:
  // 包名
  pluginName:
    git:
      // 远程仓库 url
      url: .....
      // 远程仓库中的包的相对路径
      path: packages/package1