一.Package
类型
-
Dart packages
:用Dart
编写的通用包,其中一些可能包含Flutter
特定的功能,因此依赖于Flutter
框架,仅可用于Flutter
,例如fluro
包。 -
Plugin packages
:一种专用的Dart
包,其中包含一个用Dart
代码编写的API
以及一个或多个特定于平台的实现,例如url_launcher
包。
二.开发Dart packages
1.创建包
flutter create --template=package hello
2.直接在hello/lib
下进行flutter
平台的代码开发。
三.开发Plugin packages
1.创建包
--platforms=
后面表示插件支持的平台,可用的平台有:android
、ios
、web
、linux
、macos
和windows
。
--org
用于生成插件的包标识符。
-a
表示android
支持的语言,默认为kotlin
。
-i
表示ios
支持的语言,默认为swift
。
flutter create --org com.example --template=plugin --platforms=android,ios -i swift -a kotlin hello
2.添加ios
平台代码
<1>确保代码至少已经构建过一次:
cd hello/example
flutter clean
flutter build ios --no-codesign
<2>启动Xcode:hello/example/ios/Runner.xcworkspace
,开始编辑ios
平台代码。
<3>添加第三方依赖Pods/Development Pods/hello/Pod/hello.podspec
:
Pod::Spec.new do |s|
# lines skipped
s.dependency 'MTBBarcodeScanner'
添加完成后
pod install
<4>插件代码位于Pods/Development Pods/hello/../../example/ios/.symlinks/plugins/hello/ios/Classes
下。
遵守FlutterPlatformViewFactory
协议的文件:
import UIKit
class BarcodeScannerFactory: NSObject, FlutterPlatformViewFactory {
private var messenger: FlutterBinaryMessenger?
init(messenger: FlutterBinaryMessenger) {
super.init()
self.messenger = messenger
}
func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
/// 注:frame和viewId获取不到,frame为zero,viewId为0
return BarcodeScannerView(
frame: frame,
viewIdentifier: viewId,
arguments: args,
binaryMessenger: messenger
)
}
func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
return FlutterStandardMessageCodec(readerWriter: FlutterStandardReaderWriter())
}
}
遵守FlutterPlatformView
协议的文件:
import UIKit
import MTBBarcodeScanner
class BarcodeScannerView: NSObject, FlutterPlatformView {
private var scannerView: UIView!
private var scanner: MTBBarcodeScanner!
init(
frame: CGRect,
viewIdentifier viewId: Int64,
arguments args: Any?,
binaryMessenger messenger: FlutterBinaryMessenger?
) {
super.init()
scannerView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
scanner = MTBBarcodeScanner(previewView: scannerView)
do {
try scanner.startScanning(resultBlock: { _ in })
} catch {}
}
func view() -> UIView {
return scannerView;
}
}
在插件中注册FlutterPlatformViewFactory
:
import Flutter
import UIKit
class BarcodeScannerPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
registrar.register(BarcodeScannerFactory(messenger: registrar.messenger()), withId: "view_type_id_scanner_view")
}
}
3.添加android
平台代码
<1>运行example文件代码
构建依赖:
cd hello/example
flutter pub get
Android Studio->File->Open
,选择hello/example/android/build.gradle
启动并运行。
<2>启动Android Studio
:hello/android
,开始编辑android
平台代码。
<3>添加第三方依赖Gradle Scripts/build.gradle(Module:android.hello)
:
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
/// 添加第三方库
implementation 'me.dm7.barcodescanner:zxing:1.9.13'
}
<4>插件代码位于hello/java/
下。
若出现
Unresolved reference: io.flutter
,选择File->Invalidate Caches/Restart...
。
继承混合类PlatformViewFactory
的文件:
import android.content.Context
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory
class BarcodeScannerFactory(private var messenger: BinaryMessenger) : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
return BarcodeScannerView(messenger, context, viewId, args)
}
}
继承混合类PlatformView
的文件:
import android.content.Context
import android.view.View
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.platform.PlatformView
import me.dm7.barcodescanner.zxing.ZXingScannerView
class BarcodeScannerView(binaryMessenger: BinaryMessenger, context: Context, viewId: Int, args: Any?) : PlatformView {
private var scannerView = ZXingScannerView(context)
init {
scannerView.startCamera()
}
override fun getView(): View {
return scannerView
}
override fun dispose() {}
}
在插件中注册PlatformViewFactory
:
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
flutterPluginBinding.platformViewRegistry.registerViewFactory("view_type_id_scanner_view", BarcodeScannerFactory(flutterPluginBinding.binaryMessenger))
}
4.添加flutter
平台代码
代码位于hello/lib
:
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class BarcodeScanner extends StatelessWidget {
const BarcodeScanner({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
const String viewType = 'view_type_id_scanner_view';
const Map<String, dynamic> creationParams = {'name': '张三'};
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return const AndroidView(
viewType: viewType,
creationParams: creationParams,
creationParamsCodec: StandardMessageCodec(),
);
case TargetPlatform.iOS:
return const UiKitView(
viewType: viewType,
creationParams: creationParams,
creationParamsCodec: StandardMessageCodec(),
);
default:
return const Text('暂不支持该平台');
}
}
}
四.插件发布
1.完善pubspec.yaml
文件
name: 插件名称
description: 插件描述
version: 插件版本号,0.0.1
author: 作者,xxxx<xx@xxx.com>
homepage: 项目主页地址
publish_to: 填写私有服务器的地址(如果是发布到flutter pub则不用填写,插件默认是上传到flutter pub)
2.检验是否可以发布
flutter packages pub publish --dry-run
--dry-run 参数表示本次执行会检查插件的配置信息是否有效,插件是否满足上传条件。如果成功的话并不会真正的将插件上传,而是会显示本次要发布插件的信息,并提示成功。一般在插件的正式发布前,建议先执行该命令,避免在上传过程中出现错误。
3.正式发布
发布到pub平台:
flutter packages pub publish
发布到私有服务器:
flutter packages pub publish --server $服务器地址
pubspec.yaml文件中列出的包作者与授权发布该包的人员列表不同。发布某个软件包的第一个版本的人自动成为第一个也是唯一一个有权上传其他版本软件包的人。要允许或禁止其他人上载版本,请使用pub uploader命令。
五.iOS
中podspec
文件
1.Podfile
与podspec
的区别
-
Podfile
指的是将本地或远端的库导入到该工程。 -
podspec
指的是依赖于该库,若该库在本地没有,会先去cocoapods
下载导入到该工程。
2.podsepc
依赖于git
库
podsepc
文件中的s.dependency
只能依赖于cocoapods
中的版本,而不能依赖于git
库。可使用以下方法解决。
事例:依赖于IMKit
的git
库https://github.com/imkit/imkit-ios-framework-v3.git
<1>在插件工程的podsepc
文件中依赖:
s.dependency 'IMKit'
<2>在项目工程的Podfile
文件中导入:
target 'Runner' do
use_frameworks!
use_modular_headers!
pod 'IMKit', :git => 'https://github.com/imkit/imkit-ios-framework-v3.git'
end
3.podsepc
依赖于cocoapods的静态framework库
事例:依赖于静态库PrintSDK.framework
<1>在插件工程的podsepc
文件中依赖:
# 使用静态库
s.static_framework = true
# 依赖第三方的framework
s.dependency 'PrinterSDK'
# 依赖系统库(可选)
s.frameworks = 'UIKit', 'SystemConfiguration'
# Xcode里面Build Settings ->Other Linker Flags设置-ObjC(可选)
s.pod_target_xcconfig = { 'OTHER_LDFLAGS' => '-lObjC' }
若不设置s.static_framework = true
,会报错:The 'Pods-Runner' target has transitive dependencies that include statically linked binaries
。