fqreader.dart 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. library fqreader;
  2. import 'dart:async';
  3. import 'dart:io';
  4. import 'dart:typed_data';
  5. import 'dart:ui' as ui;
  6. import 'package:flutter/material.dart';
  7. import 'package:flutter/services.dart';
  8. typedef ScanEvent = Future<bool> Function(String value);
  9. class Fqreader {
  10. static const MethodChannel _channel =
  11. const MethodChannel('fqreader');
  12. static Future<String> decodeImg(File file,List<ScanType> scanType) async{
  13. var scanStr = new List<String>();
  14. scanType.forEach((item){
  15. scanStr.add(item.toString());
  16. });
  17. List<int> data = file.readAsBytesSync();
  18. Uint8List uData = new Uint8List.fromList(data);
  19. return await _channel.invokeMethod('decodeImg',{
  20. "image": uData,
  21. "scanType": scanStr
  22. });
  23. }
  24. static Future<int> _initView({
  25. @required Rect viewRect,
  26. @required Rect scanRect,
  27. @required List<ScanType> scanType,
  28. double devicePixelRatio
  29. }) async {
  30. var scanStr = new List<String>();
  31. scanType.forEach((item){
  32. scanStr.add(item.toString());
  33. });
  34. final int textureId = await _channel.invokeMethod('initView',{
  35. "viewRect":{
  36. "left":(viewRect.left * devicePixelRatio).toInt(),
  37. "top":(viewRect.top* devicePixelRatio).toInt(),
  38. "right":(viewRect.right* devicePixelRatio).toInt(),
  39. "bottom":(viewRect.bottom* devicePixelRatio).toInt()
  40. },
  41. "scanRect":{
  42. "left":(scanRect.left* devicePixelRatio).toInt(),
  43. "top":(scanRect.top* devicePixelRatio).toInt(),
  44. "right":(scanRect.right* devicePixelRatio).toInt(),
  45. "bottom":(scanRect.bottom* devicePixelRatio).toInt(),
  46. },
  47. "scanType": scanStr
  48. });
  49. return textureId;
  50. }
  51. static Future _startScan() async{
  52. await _channel.invokeMethod('startScan');
  53. }
  54. static Future _stopScan() async{
  55. await _channel.invokeMethod('stopScan');
  56. }
  57. static Future _turnOn() async{
  58. await _channel.invokeMethod("turnOn");
  59. }
  60. static Future _turnOff() async{
  61. await _channel.invokeMethod("turnOff");
  62. }
  63. static Future _release() async{
  64. await _channel.invokeMethod("release");
  65. }
  66. }
  67. class ScanView extends StatefulWidget{
  68. /**
  69. * 扫描事件
  70. */
  71. final ScanEvent onScan;
  72. /**
  73. * 扫描区域大小
  74. */
  75. final Rect scanRect;
  76. /**
  77. * ScanView控件大小
  78. */
  79. final Rect viewRect;
  80. /**
  81. * 是否立即扫描
  82. */
  83. final bool autoScan;
  84. /**
  85. * 是否连续扫描
  86. */
  87. final bool continuityScan;
  88. /**
  89. * 连续扫描间隔
  90. */
  91. final Duration scanInterval;
  92. /**
  93. * 扫描的条码类型
  94. */
  95. final List<ScanType> scanType;
  96. const ScanView({
  97. Key key,
  98. this.onScan,
  99. @required this.viewRect,
  100. @required this.scanRect,
  101. this.scanType = const [ScanType.ALL],
  102. this.autoScan = true,
  103. this.continuityScan = false,
  104. this.scanInterval = const Duration(milliseconds:500)})
  105. : super(key:key);
  106. @override
  107. State<StatefulWidget> createState() =>ScanViewState();
  108. }
  109. class ScanViewState extends State<ScanView>{
  110. int _textureId;
  111. StreamSubscription _readySubscription;
  112. @override
  113. void initState() {
  114. // TODO: implement initState
  115. super.initState();
  116. MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window);
  117. Fqreader._initView(
  118. viewRect: widget.viewRect,
  119. scanRect:widget.scanRect,
  120. devicePixelRatio:mediaQuery.devicePixelRatio,
  121. scanType: widget.scanType
  122. ).then((textureId){
  123. setState(() {
  124. _textureId = textureId;
  125. });
  126. if(widget.autoScan){
  127. Fqreader._startScan();
  128. }
  129. _readySubscription = new EventChannel('fqreader/scanEvents$_textureId')
  130. .receiveBroadcastStream()
  131. .listen(_listener);
  132. });
  133. }
  134. @override
  135. Widget build(BuildContext context) {
  136. return _textureId != null
  137. ? new Texture(textureId: _textureId)
  138. : new Container();
  139. }
  140. @override
  141. void dispose(){
  142. super.dispose();
  143. _readySubscription.cancel();
  144. Fqreader._release();
  145. }
  146. /**
  147. * 开始扫描
  148. */
  149. Future startScan() async{
  150. await Fqreader._startScan();
  151. }
  152. /**
  153. * 暂停扫描
  154. */
  155. Future stopScan() async{
  156. await Fqreader._stopScan();
  157. }
  158. /**
  159. * 开灯
  160. */
  161. Future turnOn() async{
  162. await Fqreader._turnOn();
  163. }
  164. /**
  165. * 关灯
  166. */
  167. Future turnOff() async{
  168. await Fqreader._turnOff();
  169. }
  170. void _listener(dynamic value) {
  171. if(widget != null)
  172. {
  173. if(!widget.continuityScan) //是否连续扫描
  174. {
  175. Fqreader._stopScan();
  176. }
  177. widget.onScan(value).then((result){
  178. if(widget.continuityScan && result){
  179. Future.delayed(widget.scanInterval,(){
  180. Fqreader._startScan();
  181. });
  182. }else{
  183. Fqreader._stopScan();
  184. }
  185. });
  186. }
  187. }
  188. }
  189. enum ScanType{
  190. /**
  191. * 所有条形码
  192. */
  193. ALL,
  194. /**
  195. * 普通二维码
  196. */
  197. QR_CODE,
  198. /**
  199. * 二维码 主要用于航空。比如坐飞机行李箱上贴的便签
  200. */
  201. AZTEC,
  202. /**
  203. * 条形码
  204. */
  205. CODABAR,
  206. /**
  207. * CODE 39 条形码
  208. */
  209. CODE_39,
  210. /**
  211. * CODE 92 条形码
  212. */
  213. CODE_93,
  214. /**
  215. * CODE 128 条形码
  216. */
  217. CODE_128,
  218. /**
  219. * 商品用条形码 EAN8
  220. */
  221. EAN8,
  222. /**
  223. * 商品用条形码 EAN13
  224. */
  225. EAN13,
  226. /**
  227. * 全球贸易货号。主要用于运输方面的条形码
  228. */
  229. ITF,
  230. /**
  231. * 一种二维码
  232. */
  233. DATA_MATRIX,
  234. /**
  235. * PDF417条码是一种高密度、高信息含量的便携式数据文件
  236. */
  237. PDF_417
  238. }