Flutter在Linux及Chrome Web平台实现QR扫码遇qrview不支持错误求助
解决Flutter Linux/Web平台二维码扫码的不支持错误
错误原因
你使用的qr_code_scanner库仅支持iOS和Android平台,没有为Linux、Web提供默认实现,因此运行时抛出Unsupported operation: Trying to use the default qrview implementation for TargetPlatform.linux but there isn't a default one错误。
方案1:切换支持多平台的扫码库(推荐)
使用mobile_scanner库,它原生支持Android、iOS、Web、Linux等多平台,无需额外适配即可实现摄像头扫码。
步骤1:替换依赖
修改pubspec.yaml,移除qr_code_scanner,添加mobile_scanner:
dependencies: flutter: sdk: flutter mobile_scanner: ^4.0.0 # 使用最新版本 url_launcher: ^6.2.0
步骤2:修改扫码组件代码
替换原Scanner组件为以下适配代码:
import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; import 'package:url_launcher/url_launcher.dart'; class Scanner extends StatefulWidget { const Scanner({super.key}); @override _ScannerState createState() => _ScannerState(); } class _ScannerState extends State<Scanner> { MobileScannerController? controller; bool isScanning = true; @override void dispose() { controller?.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Center(child: Text("Scan the Building QR Code")), ), body: Stack( children: [ MobileScanner( controller: MobileScannerController( detectionSpeed: DetectionSpeed.normal, facing: CameraFacing.back, ), onDetect: (capture) async { if (!isScanning) return; isScanning = false; final List<Barcode> barcodes = capture.barcodes; if (barcodes.isNotEmpty) { final code = barcodes.first.rawValue; if (code != null) { if (await canLaunchUrl(Uri.parse(code))) { await launchUrl(Uri.parse(code)); } else { await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Could not find viable URL'), content: SingleChildScrollView( child: ListBody( children: [ Text('Barcode Type: ${barcodes.first.format.name}'), Text('Data: $code'), ], ), ), actions: [ TextButton( child: const Text('OK'), onPressed: () => Navigator.of(context).pop(), ), ], ), ); } } } // 延迟恢复扫描,避免重复触发 await Future.delayed(const Duration(seconds: 2)); isScanning = true; }, ), Center( child: Container( width: 300, height: 300, decoration: BoxDecoration( border: Border.all(color: Colors.black, width: 4), borderRadius: BorderRadius.circular(12), ), ), ) ], ), ); } }
方案2:针对Linux/Web平台做兼容适配(保留原库)
如果需要继续使用qr_code_scanner,可以通过平台判断,为Linux/Web提供图片解析扫码的替代方案:
步骤1:添加依赖
新增图片选择和二维码解析库:
dependencies: qr_code_scanner: ^1.0.1 url_launcher: ^6.2.0 image_picker: ^1.0.4 qr_code_parser: ^1.0.0
步骤2:修改组件代码,添加平台判断
import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'package:qr_code_parser/qr_code_parser.dart'; import 'package:qr_code_scanner/qr_code_scanner.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:image/image.dart' as img; class Scanner extends StatefulWidget { const Scanner({super.key}); @override _ScannerState createState() => _ScannerState(); } class _ScannerState extends State<Scanner> { final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); late QRViewController controller; @override void dispose() { if (!kIsWeb && defaultTargetPlatform != TargetPlatform.linux) { controller.dispose(); } super.dispose(); } // 解析本地图片二维码 Future<void> _scanFromImage() async { final picker = ImagePicker(); final pickedFile = await picker.pickImage(source: ImageSource.gallery); if (pickedFile == null) return; final bytes = await pickedFile.readAsBytes(); final image = img.decodeImage(bytes); if (image == null) return; final result = await QrCodeParser().parse(image); if (result != null) { _handleScanResult(result.code); } } // 处理扫描结果 Future<void> _handleScanResult(String? code) async { if (code == null) return; if (await canLaunchUrl(Uri.parse(code))) { await launchUrl(Uri.parse(code)); } else { await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Could not find viable URL'), content: SingleChildScrollView( child: ListBody( children: [ const Text('Barcode Type: QR Code'), Text('Data: $code'), ], ), ), actions: [ TextButton( child: const Text('OK'), onPressed: () => Navigator.of(context).pop(), ), ], ), ); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Center(child: Text("Scan the Building QR Code")), ), body: kIsWeb || defaultTargetPlatform == TargetPlatform.linux ? Center( child: ElevatedButton( onPressed: _scanFromImage, child: const Text("选择二维码图片扫码"), ), ) : Stack( children: [ Column( children: [ Expanded( flex: 4, child: Stack( children: [ QRView( key: qrKey, onQRViewCreated: (QRViewController controller) { this.controller = controller; controller.scannedDataStream.listen((scanData) { controller.pauseCamera(); _handleScanResult(scanData.code).then((_) => controller.resumeCamera()); }); }, ), Center( child: Container( width: 300, height: 300, decoration: BoxDecoration( border: Border.all(color: Colors.black, width: 4), borderRadius: BorderRadius.circular(12), ), ), ) ], ), ), ], ), ], ), ); } }
额外注意事项
- Web平台:如果使用摄像头扫码,需要在
web/index.html中添加摄像头权限声明:<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="permission" content="camera"> - Linux平台:如果使用摄像头扫码,需要确保应用已获取摄像头权限,可通过系统设置手动授权。
内容的提问来源于stack exchange,提问作者Kambale
相关产品推荐
相关产品推荐

