在Flutter中实现广播模式的条码扫码插件,可以通过MethodChannel接收原生平台的扫码结果,并使用Stream进行广播。以下是核心实现步骤:
1. 插件基本结构
创建Flutter插件:
flutter create --template=plugin barcode_scanner
2. Dart端实现
// lib/barcode_scanner.dart
import 'dart:async';
import 'package:flutter/services.dart';
class BarcodeScanner {
static const MethodChannel _channel =
MethodChannel('barcode_scanner');
static final StreamController<String> _streamController =
StreamController.broadcast(); // 广播Stream
static Stream<String> get onBarcodeScanned => _streamController.stream;
static Future<void> startScan() async {
try {
await _channel.invokeMethod('startScan');
} on PlatformException catch (e) {
print("启动扫描失败: ${e.message}");
}
}
// 供原生平台调用的结果接收方法
static void receiveBarcodeResult(String barcode) {
_streamController.add(barcode); // 广播结果
}
}
3. Android端实现 (Kotlin)
// android/src/main/kotlin/BarcodeScannerPlugin.kt
class BarcodeScannerPlugin : MethodCallHandler {
private var activity: Activity? = null
companion object {
@JvmStatic
fun registerWith(registrar: Registrar) {
val plugin = BarcodeScannerPlugin()
plugin.activity = registrar.activity()
val channel = MethodChannel(registrar.messenger(), "barcode_scanner")
channel.setMethodCallHandler(plugin)
}
}
override fun onMethodCall(call: MethodCall, result: Result) {
when (call.method) {
"startScan" -> {
// 启动扫码Activity(如ZXing)
val intent = Intent(activity, ScanActivity::class.java)
activity?.startActivity(intent)
result.success(null)
}
else -> result.notImplemented()
}
}
// 在扫码结果返回时调用Flutter端
fun sendBarcodeResult(barcode: String) {
MethodChannel(flutterView, "barcode_scanner").invokeMethod(
"receiveBarcodeResult", barcode)
}
}
4. iOS端实现 (Swift)
// ios/Classes/BarcodeScannerPlugin.swift
public class SwiftBarcodeScannerPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(
name: "barcode_scanner",
binaryMessenger: registrar.messenger())
let instance = SwiftBarcodeScannerPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "startScan":
// 启动原生扫码控制器
let scanner = ScannerViewController()
scanner.completion = { barcode in
// 回调结果到Flutter
if let barcode = barcode {
self.invokeFlutterMethod("receiveBarcodeResult", arguments: barcode)
}
}
UIApplication.shared.keyWindow?.rootViewController?.present(scanner, animated: true)
result(nil)
default:
result(FlutterMethodNotImplemented)
}
}
private func invokeFlutterMethod(_ method: String, arguments: Any?) {
// 通过MethodChannel回调到Dart端
channel?.invokeMethod(method, arguments: arguments)
}
}
5. 使用方式
// 在Flutter应用中
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 监听广播
BarcodeScanner.onBarcodeScanned.listen((barcode) {
print("收到条码: $barcode");
// 多个页面都会同时收到通知
});
return MaterialApp(
home: Scaffold(
body: Center(
child: ElevatedButton(
onPressed: BarcodeScanner.startScan,
child: Text('开始扫码'),
),
),
),
);
}
}
关键点说明:
- 广播模式:使用
StreamController.broadcast()创建广播流
- 跨平台通信:通过MethodChannel实现Dart与原生平台的双向通信
- 结果分发:原生平台将扫码结果通过MethodChannel回调到Dart端,再通过Stream广播
- 多监听器:任何监听
onBarcodeScanned的Widget都会实时收到扫码结果
这种实现方式允许应用中的多个组件同时监听扫码结果,适合需要实时更新多个UI界面的场景。