diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index d20f883..f9d06d5 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -12,6 +12,15 @@ + + + + + + + + + { final DialogService _dialogService = locator(); final BluetoothDevice printerBtDevice = Redux.store.state.settingState.printerBT; + final BluetoothManager bluetoothManager = BluetoothManager.instance; bool _printing = false; + void _preparePrint() async { + if (Platform.isIOS) { + await _print(); + } else { + bluetoothManager.state.listen((val) { + print("state = $val"); + if (!mounted) return; + if (val == 12) { + print('on'); + _print(); + + } else if (val == 10) { + print('off'); + _dialogService.showDialog( + description: 'Отсутвует соеденение Bluetooth или он отключен' , title: 'Bluetooth'); + } + print('state is $val'); + }); + } + } + void _print() async { final SettingState state = Redux.store.state.settingState; if(state.printerBT == null) { @@ -61,7 +83,7 @@ class _ImageShowContainerState extends State { bool isIos = Platform.isIOS; int chunkSizeBytes = 3096; - int queueSleepTimeMs = 50; + int queueSleepTimeMs = 100; if(isIos){ chunkSizeBytes = 75; @@ -95,11 +117,13 @@ class _ImageShowContainerState extends State { _dialogService.showDialog(description: res.msg); } } - } finally { - setState(() { - _printing = false; - }); + } catch (e) { + print(e); } + await Future.delayed(Duration(seconds: 7)); + setState(() { + _printing = false; + }); } @override @@ -124,7 +148,7 @@ class _ImageShowContainerState extends State { ), ) else - IconButton(icon: Icon(Icons.print), onPressed: _print) + IconButton(icon: Icon(Icons.print), onPressed: _preparePrint) ], ), body: ListView( diff --git a/lib/views/settings/printer/PrinterTest.dart b/lib/views/settings/printer/PrinterTest.dart index e9e646b..3dbaba7 100644 --- a/lib/views/settings/printer/PrinterTest.dart +++ b/lib/views/settings/printer/PrinterTest.dart @@ -117,13 +117,13 @@ Future testTicketImage(PaperSize paper) async { // Print image final ByteData byteData = await rootBundle.load('assets/images/check.png'); final Uint8List bytes = byteData.buffer.asUint8List(); - final Im.Image imagea = Im.decodeImage(bytes); + final Im.Image image = Im.decodeImage(bytes); // Using `ESC *` //ticket.image(imagea); // Using `GS v 0` (obsolete) //ticket.imageRaster(imagea); // Using `GS ( L` - ticket.imageRaster(imagea, imageFn: PosImageFn.bitImageRaster); + ticket.imageRaster(image, imageFn: PosImageFn.bitImageRaster); //ticket.image(imagea); @@ -137,8 +137,8 @@ Future printImageCheck(PaperSize paper, String base64Src) async { final Ticket ticket = Ticket(paper); final Uint8List bytes = base64Decode(base64Src); final Im.Image image = Im.decodeImage(bytes); - //ticket.imageRaster(image, imageFn: PosImageFn.bitImageRaster); - ticket.image(image); + ticket.imageRaster(image, imageFn: PosImageFn.bitImageRaster); + //ticket.image(image); ticket.feed(2); ticket.cut(); return ticket; @@ -209,17 +209,15 @@ Future printTextCheck(PaperSize paper, String encoding, var data ) async const double qrSize = 200; try { final uiImg = await QrPainter( - data: qr, version: QrVersions.auto, gapless: true, ).toImageData(qrSize); - final dir = await getTemporaryDirectory(); - final pathName = '${dir.path}/qr_tmp.png'; - final qrFile = File(pathName); - final imgFile = await qrFile.writeAsBytes(uiImg.buffer.asUint8List()); - final img = Im.decodePng(imgFile.readAsBytesSync()); - + //final dir = await getTemporaryDirectory(); + //final pathName = '${dir.path}/qr_tmp.png'; + //final qrFile = File(pathName); + //final imgFile = await qrFile.writeAsBytes(uiImg.buffer.asUint8List()); + final img = Im.decodePng(uiImg.buffer.asUint8List()); ticket.image(img); //ticket.qrcode(qr, size: QRSize.Size1 ); diff --git a/lib/views/settings/setting_printer_view.dart b/lib/views/settings/setting_printer_view.dart index 6e0e8ca..a94b72f 100644 --- a/lib/views/settings/setting_printer_view.dart +++ b/lib/views/settings/setting_printer_view.dart @@ -1,7 +1,11 @@ import 'dart:io'; import 'dart:typed_data'; +import 'package:aman_kassa_flutter/core/models/dialog_models.dart'; +import 'package:aman_kassa_flutter/widgets/fields/busy_button_icon.dart'; +import 'package:flutter_bluetooth_basic/flutter_bluetooth_basic.dart'; import 'package:aman_kassa_flutter/core/locator.dart'; +import 'package:aman_kassa_flutter/core/logger.dart'; import 'package:aman_kassa_flutter/core/route_names.dart'; import 'package:aman_kassa_flutter/core/services/dialog_service.dart'; import 'package:aman_kassa_flutter/core/services/navigator_service.dart'; @@ -13,8 +17,10 @@ import 'package:aman_kassa_flutter/widgets/fields/aman_icon_button_horizontal.da import 'package:esc_pos_bluetooth/esc_pos_bluetooth.dart'; import 'package:esc_pos_utils/esc_pos_utils.dart'; import 'package:flutter/material.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'package:aman_kassa_flutter/views/settings/printer/PrinterTest.dart'; import 'package:flutter_redux/flutter_redux.dart'; +import 'package:logger/logger.dart'; import 'component/setting_item.dart'; import './printer/data/settings_envi.dart'; @@ -28,44 +34,68 @@ class SettingPrinterView extends StatefulWidget { class _SettingPrinterViewState extends State { NavigatorService _navigatorService = locator(); final DialogService _dialogService = locator(); - PrinterBluetoothManager printerManager = PrinterBluetoothManager(); + final PrinterBluetoothManager printerManager = PrinterBluetoothManager(); + final BluetoothManager bluetoothManager = BluetoothManager.instance; + final Logger log = getLogger('SettingPrinterView'); + bool _printing = false; @override void initState() { super.initState(); + _permission(); + } void _testPrint() async { - final SettingState state = Redux.store.state.settingState; - printerManager.selectPrinter(PrinterBluetooth(state.printerBT)); - bool isIos = Platform.isIOS; - int chunkSizeBytes = 3096; - int queueSleepTimeMs = 50; + setState(() { + _printing = true; + }); + try { + final SettingState state = Redux.store.state.settingState; + printerManager.selectPrinter(PrinterBluetooth(state.printerBT)); + bool isIos = Platform.isIOS; + int chunkSizeBytes = 3096; + int queueSleepTimeMs = 100; - if(isIos) { - chunkSizeBytes = 75; - queueSleepTimeMs = 10; - } - // TODO Don't forget to choose printer's paper - PaperSize paper = state.printerPaperSize == SettingPrinterPaperM80 ? PaperSize.mm80 : PaperSize.mm58; - if(SettingPrinterEncodingImage == state.printerEncoding) { - final PosPrintResult res = await printerManager.printTicket( - await testTicketImage(paper), - chunkSizeBytes: chunkSizeBytes, - queueSleepTimeMs: queueSleepTimeMs - ); - _dialogService.showDialog(description: res.msg); - } else { - final PosPrintResult res = await printerManager.printTicket( - await printTextCheck(paper, state.printerEncoding, exampleJson['check_text']), - chunkSizeBytes: chunkSizeBytes, - queueSleepTimeMs: queueSleepTimeMs - ); - _dialogService.showDialog(description: res.msg); + if (isIos) { + chunkSizeBytes = 75; + queueSleepTimeMs = 10; + } + + log.i(chunkSizeBytes); + log.i(queueSleepTimeMs); + + // TODO Don't forget to choose printer's paper + PaperSize paper = state.printerPaperSize == SettingPrinterPaperM80 ? PaperSize.mm80 : PaperSize.mm58; + if (SettingPrinterEncodingImage == state.printerEncoding) { + final PosPrintResult res = await printerManager.printTicket( + await testTicketImage(paper), + chunkSizeBytes: chunkSizeBytes, + queueSleepTimeMs: queueSleepTimeMs + ); + _dialogService.showDialog(description: res.msg); + } else { + final PosPrintResult res = await printerManager.printTicket( + await printTextCheck(paper, state.printerEncoding, exampleJson['check_text']), + chunkSizeBytes: chunkSizeBytes, + queueSleepTimeMs: queueSleepTimeMs + ); + _dialogService.showDialog(description: res.msg); + } + } catch (e) { + print('ERROR'); + print(e); } + //7 sec safe disconnect + await Future.delayed(Duration(seconds: 7)); + + setState(() { + _printing = false; + }); + } @override @@ -108,13 +138,15 @@ class _SettingPrinterViewState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ - AmanIconButtonHorizontal( + BusyButtonIcon( icon: Icons.local_printshop_outlined, title: 'Напечатать тестовую страницу', - activeColor: primaryColor, - selected: vm.printerBT != null, + busy: _printing, + enabled: vm.printerBT != null, onPressed: () { - _testPrint(); + + _startInitialPrint(); + }, ), ], @@ -127,4 +159,57 @@ class _SettingPrinterViewState extends State { ), ); } + + //Метод для получения постоянного доступа к местополения + //только для Android + void _permission() async { + if( Platform.isAndroid) { + var status = await Permission.locationAlways.status; + log.i(status); + if (status.isUndetermined || status.isDenied || status.isPermanentlyDenied) { + DialogResponse response = await _dialogService.showConfirmationDialog( + title: 'Доступ', + description: 'Для поиска устройств Bluetooth необходимо предоставить доступ к отслеживанию геолокации.', + cancelTitle: 'Нет', + confirmationTitle: 'Хорошо', + ); + if (response.confirmed) { + if (await Permission.locationAlways + .request() + .isGranted) { + print('Granted'); + } else { + _dialogService.showDialog( + description: 'Необходимо указать постоянный доступ к местоположении для поиска принтера'); + _navigatorService.pop(); + } + } else { + _navigatorService.pop(); + } + } + } + } + + void _startInitialPrint() async { + + + if (Platform.isIOS) { + await _testPrint(); + } else { + bluetoothManager.state.listen((val) { + print("state = $val"); + if (!mounted) return; + if (val == 12) { + print('on'); + _testPrint(); + + } else if (val == 10) { + print('off'); + _dialogService.showDialog( + description: 'Отсутвует соеденение Bluetooth или он отключен' , title: 'Bluetooth'); + } + print('state is $val'); + }); + } + } } diff --git a/lib/widgets/fields/busy_button.dart b/lib/widgets/fields/busy_button.dart index d3c879a..5e5c7d4 100644 --- a/lib/widgets/fields/busy_button.dart +++ b/lib/widgets/fields/busy_button.dart @@ -52,7 +52,7 @@ class _BusyButtonState extends State { ? AutoSizeText( widget.title, textAlign: TextAlign.center, - style: buttonTitleTextStyle, + style: widget.enabled ? buttonTitleTextStyle : buttonTitleDisableTextStyle, minFontSize: 2, maxLines: 1, ) diff --git a/lib/widgets/fields/busy_button_icon.dart b/lib/widgets/fields/busy_button_icon.dart index fcd413c..6365f2e 100644 --- a/lib/widgets/fields/busy_button_icon.dart +++ b/lib/widgets/fields/busy_button_icon.dart @@ -68,7 +68,7 @@ class _BusyButtonIconState extends State { Text( widget.title, textAlign: TextAlign.center, - style: buttonTitleTextStyle, + style: widget.enabled ? buttonTitleTextStyle : buttonTitleDisableTextStyle, maxLines: 1, ), ], diff --git a/pubspec.lock b/pubspec.lock index cf57921..2b3bd71 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -401,6 +401,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.9.2" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.0+2" + permission_handler_platform_interface: + dependency: transitive + description: + name: permission_handler_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" petitparser: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 11b3846..668046f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,6 +38,7 @@ dependencies: esc_pos_utils: ^0.3.6 # no edit for esc_pos_bluetooth: ^0.2.8 charset_converter: ^1.0.3 crypto: ^2.1.5 + permission_handler: ^5.0.1+2 dev_dependencies: flutter_test: sdk: flutter