commit
27d0d6d11d
|
|
@ -12,6 +12,15 @@
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.CAMERA" />
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_BLUETOOTH_ADMIN" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
|
||||||
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
tools:replace="android:label"
|
tools:replace="android:label"
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ const TextStyle productTextStyle = const TextStyle(
|
||||||
fontWeight: FontWeight.w400, color: Colors.black, fontSize: 15);
|
fontWeight: FontWeight.w400, color: Colors.black, fontSize: 15);
|
||||||
const TextStyle buttonTitleTextStyle = const TextStyle(
|
const TextStyle buttonTitleTextStyle = const TextStyle(
|
||||||
fontWeight: FontWeight.w700, color: whiteColor, fontSize: 14);
|
fontWeight: FontWeight.w700, color: whiteColor, fontSize: 14);
|
||||||
|
const TextStyle buttonTitleDisableTextStyle = const TextStyle(
|
||||||
|
fontWeight: FontWeight.w700, color: fillColor, fontSize: 14);
|
||||||
const TextStyle buttonBigTitleTextStyle = const TextStyle(
|
const TextStyle buttonBigTitleTextStyle = const TextStyle(
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
color: whiteColor,
|
color: whiteColor,
|
||||||
|
|
|
||||||
|
|
@ -49,9 +49,31 @@ class _ImageShowContainerState extends State<ImageShowContainer> {
|
||||||
final DialogService _dialogService = locator<DialogService>();
|
final DialogService _dialogService = locator<DialogService>();
|
||||||
|
|
||||||
final BluetoothDevice printerBtDevice = Redux.store.state.settingState.printerBT;
|
final BluetoothDevice printerBtDevice = Redux.store.state.settingState.printerBT;
|
||||||
|
final BluetoothManager bluetoothManager = BluetoothManager.instance;
|
||||||
|
|
||||||
bool _printing = false;
|
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 {
|
void _print() async {
|
||||||
final SettingState state = Redux.store.state.settingState;
|
final SettingState state = Redux.store.state.settingState;
|
||||||
if(state.printerBT == null) {
|
if(state.printerBT == null) {
|
||||||
|
|
@ -61,7 +83,7 @@ class _ImageShowContainerState extends State<ImageShowContainer> {
|
||||||
|
|
||||||
bool isIos = Platform.isIOS;
|
bool isIos = Platform.isIOS;
|
||||||
int chunkSizeBytes = 3096;
|
int chunkSizeBytes = 3096;
|
||||||
int queueSleepTimeMs = 50;
|
int queueSleepTimeMs = 100;
|
||||||
|
|
||||||
if(isIos){
|
if(isIos){
|
||||||
chunkSizeBytes = 75;
|
chunkSizeBytes = 75;
|
||||||
|
|
@ -95,12 +117,14 @@ class _ImageShowContainerState extends State<ImageShowContainer> {
|
||||||
_dialogService.showDialog(description: res.msg);
|
_dialogService.showDialog(description: res.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
await Future.delayed(Duration(seconds: 7));
|
||||||
setState(() {
|
setState(() {
|
||||||
_printing = false;
|
_printing = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
@ -124,7 +148,7 @@ class _ImageShowContainerState extends State<ImageShowContainer> {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
IconButton(icon: Icon(Icons.print), onPressed: _print)
|
IconButton(icon: Icon(Icons.print), onPressed: _preparePrint)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: ListView(
|
body: ListView(
|
||||||
|
|
|
||||||
|
|
@ -117,13 +117,13 @@ Future<Ticket> testTicketImage(PaperSize paper) async {
|
||||||
// Print image
|
// Print image
|
||||||
final ByteData byteData = await rootBundle.load('assets/images/check.png');
|
final ByteData byteData = await rootBundle.load('assets/images/check.png');
|
||||||
final Uint8List bytes = byteData.buffer.asUint8List();
|
final Uint8List bytes = byteData.buffer.asUint8List();
|
||||||
final Im.Image imagea = Im.decodeImage(bytes);
|
final Im.Image image = Im.decodeImage(bytes);
|
||||||
// Using `ESC *`
|
// Using `ESC *`
|
||||||
//ticket.image(imagea);
|
//ticket.image(imagea);
|
||||||
// Using `GS v 0` (obsolete)
|
// Using `GS v 0` (obsolete)
|
||||||
//ticket.imageRaster(imagea);
|
//ticket.imageRaster(imagea);
|
||||||
// Using `GS ( L`
|
// Using `GS ( L`
|
||||||
ticket.imageRaster(imagea, imageFn: PosImageFn.bitImageRaster);
|
ticket.imageRaster(image, imageFn: PosImageFn.bitImageRaster);
|
||||||
//ticket.image(imagea);
|
//ticket.image(imagea);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -137,8 +137,8 @@ Future<Ticket> printImageCheck(PaperSize paper, String base64Src) async {
|
||||||
final Ticket ticket = Ticket(paper);
|
final Ticket ticket = Ticket(paper);
|
||||||
final Uint8List bytes = base64Decode(base64Src);
|
final Uint8List bytes = base64Decode(base64Src);
|
||||||
final Im.Image image = Im.decodeImage(bytes);
|
final Im.Image image = Im.decodeImage(bytes);
|
||||||
//ticket.imageRaster(image, imageFn: PosImageFn.bitImageRaster);
|
ticket.imageRaster(image, imageFn: PosImageFn.bitImageRaster);
|
||||||
ticket.image(image);
|
//ticket.image(image);
|
||||||
ticket.feed(2);
|
ticket.feed(2);
|
||||||
ticket.cut();
|
ticket.cut();
|
||||||
return ticket;
|
return ticket;
|
||||||
|
|
@ -209,17 +209,15 @@ Future<Ticket> printTextCheck(PaperSize paper, String encoding, var data ) async
|
||||||
const double qrSize = 200;
|
const double qrSize = 200;
|
||||||
try {
|
try {
|
||||||
final uiImg = await QrPainter(
|
final uiImg = await QrPainter(
|
||||||
|
|
||||||
data: qr,
|
data: qr,
|
||||||
version: QrVersions.auto,
|
version: QrVersions.auto,
|
||||||
gapless: true,
|
gapless: true,
|
||||||
).toImageData(qrSize);
|
).toImageData(qrSize);
|
||||||
final dir = await getTemporaryDirectory();
|
//final dir = await getTemporaryDirectory();
|
||||||
final pathName = '${dir.path}/qr_tmp.png';
|
//final pathName = '${dir.path}/qr_tmp.png';
|
||||||
final qrFile = File(pathName);
|
//final qrFile = File(pathName);
|
||||||
final imgFile = await qrFile.writeAsBytes(uiImg.buffer.asUint8List());
|
//final imgFile = await qrFile.writeAsBytes(uiImg.buffer.asUint8List());
|
||||||
final img = Im.decodePng(imgFile.readAsBytesSync());
|
final img = Im.decodePng(uiImg.buffer.asUint8List());
|
||||||
|
|
||||||
ticket.image(img);
|
ticket.image(img);
|
||||||
|
|
||||||
//ticket.qrcode(qr, size: QRSize.Size1 );
|
//ticket.qrcode(qr, size: QRSize.Size1 );
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:typed_data';
|
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/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/route_names.dart';
|
||||||
import 'package:aman_kassa_flutter/core/services/dialog_service.dart';
|
import 'package:aman_kassa_flutter/core/services/dialog_service.dart';
|
||||||
import 'package:aman_kassa_flutter/core/services/navigator_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_bluetooth/esc_pos_bluetooth.dart';
|
||||||
import 'package:esc_pos_utils/esc_pos_utils.dart';
|
import 'package:esc_pos_utils/esc_pos_utils.dart';
|
||||||
import 'package:flutter/material.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:aman_kassa_flutter/views/settings/printer/PrinterTest.dart';
|
||||||
import 'package:flutter_redux/flutter_redux.dart';
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
|
import 'package:logger/logger.dart';
|
||||||
|
|
||||||
import 'component/setting_item.dart';
|
import 'component/setting_item.dart';
|
||||||
import './printer/data/settings_envi.dart';
|
import './printer/data/settings_envi.dart';
|
||||||
|
|
@ -28,29 +34,42 @@ class SettingPrinterView extends StatefulWidget {
|
||||||
class _SettingPrinterViewState extends State<SettingPrinterView> {
|
class _SettingPrinterViewState extends State<SettingPrinterView> {
|
||||||
NavigatorService _navigatorService = locator<NavigatorService>();
|
NavigatorService _navigatorService = locator<NavigatorService>();
|
||||||
final DialogService _dialogService = locator<DialogService>();
|
final DialogService _dialogService = locator<DialogService>();
|
||||||
PrinterBluetoothManager printerManager = PrinterBluetoothManager();
|
final PrinterBluetoothManager printerManager = PrinterBluetoothManager();
|
||||||
|
final BluetoothManager bluetoothManager = BluetoothManager.instance;
|
||||||
|
final Logger log = getLogger('SettingPrinterView');
|
||||||
|
|
||||||
|
bool _printing = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_permission();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _testPrint() async {
|
void _testPrint() async {
|
||||||
|
setState(() {
|
||||||
|
_printing = true;
|
||||||
|
});
|
||||||
|
try {
|
||||||
final SettingState state = Redux.store.state.settingState;
|
final SettingState state = Redux.store.state.settingState;
|
||||||
printerManager.selectPrinter(PrinterBluetooth(state.printerBT));
|
printerManager.selectPrinter(PrinterBluetooth(state.printerBT));
|
||||||
bool isIos = Platform.isIOS;
|
bool isIos = Platform.isIOS;
|
||||||
int chunkSizeBytes = 3096;
|
int chunkSizeBytes = 3096;
|
||||||
int queueSleepTimeMs = 50;
|
int queueSleepTimeMs = 100;
|
||||||
|
|
||||||
if(isIos) {
|
if (isIos) {
|
||||||
chunkSizeBytes = 75;
|
chunkSizeBytes = 75;
|
||||||
queueSleepTimeMs = 10;
|
queueSleepTimeMs = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.i(chunkSizeBytes);
|
||||||
|
log.i(queueSleepTimeMs);
|
||||||
|
|
||||||
// TODO Don't forget to choose printer's paper
|
// TODO Don't forget to choose printer's paper
|
||||||
PaperSize paper = state.printerPaperSize == SettingPrinterPaperM80 ? PaperSize.mm80 : PaperSize.mm58;
|
PaperSize paper = state.printerPaperSize == SettingPrinterPaperM80 ? PaperSize.mm80 : PaperSize.mm58;
|
||||||
if(SettingPrinterEncodingImage == state.printerEncoding) {
|
if (SettingPrinterEncodingImage == state.printerEncoding) {
|
||||||
final PosPrintResult res = await printerManager.printTicket(
|
final PosPrintResult res = await printerManager.printTicket(
|
||||||
await testTicketImage(paper),
|
await testTicketImage(paper),
|
||||||
chunkSizeBytes: chunkSizeBytes,
|
chunkSizeBytes: chunkSizeBytes,
|
||||||
|
|
@ -65,6 +84,17 @@ class _SettingPrinterViewState extends State<SettingPrinterView> {
|
||||||
);
|
);
|
||||||
_dialogService.showDialog(description: res.msg);
|
_dialogService.showDialog(description: res.msg);
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('ERROR');
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
//7 sec safe disconnect
|
||||||
|
await Future.delayed(Duration(seconds: 7));
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_printing = false;
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,13 +138,15 @@ class _SettingPrinterViewState extends State<SettingPrinterView> {
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
AmanIconButtonHorizontal(
|
BusyButtonIcon(
|
||||||
icon: Icons.local_printshop_outlined,
|
icon: Icons.local_printshop_outlined,
|
||||||
title: 'Напечатать тестовую страницу',
|
title: 'Напечатать тестовую страницу',
|
||||||
activeColor: primaryColor,
|
busy: _printing,
|
||||||
selected: vm.printerBT != null,
|
enabled: vm.printerBT != null,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_testPrint();
|
|
||||||
|
_startInitialPrint();
|
||||||
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -127,4 +159,57 @@ class _SettingPrinterViewState extends State<SettingPrinterView> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Метод для получения постоянного доступа к местополения
|
||||||
|
//только для 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');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ class _BusyButtonState extends State<BusyButton> {
|
||||||
? AutoSizeText(
|
? AutoSizeText(
|
||||||
widget.title,
|
widget.title,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: buttonTitleTextStyle,
|
style: widget.enabled ? buttonTitleTextStyle : buttonTitleDisableTextStyle,
|
||||||
minFontSize: 2,
|
minFontSize: 2,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ class _BusyButtonIconState extends State<BusyButtonIcon> {
|
||||||
Text(
|
Text(
|
||||||
widget.title,
|
widget.title,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: buttonTitleTextStyle,
|
style: widget.enabled ? buttonTitleTextStyle : buttonTitleDisableTextStyle,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
14
pubspec.lock
14
pubspec.lock
|
|
@ -401,6 +401,20 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.2"
|
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:
|
petitparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ dependencies:
|
||||||
esc_pos_utils: ^0.3.6 # no edit for esc_pos_bluetooth: ^0.2.8
|
esc_pos_utils: ^0.3.6 # no edit for esc_pos_bluetooth: ^0.2.8
|
||||||
charset_converter: ^1.0.3
|
charset_converter: ^1.0.3
|
||||||
crypto: ^2.1.5
|
crypto: ^2.1.5
|
||||||
|
permission_handler: ^5.0.1+2
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue