dopos_print 0.1.2 copy "dopos_print: ^0.1.2" to clipboard
dopos_print: ^0.1.2 copied to clipboard

***** EASY TO USE ***** The dopos_print plugin is a Flutter plugin designed to interface with thermal printers on Windows and Android (Bluetooth printers) OR Ethernet Printers. This plugin enables Flu [...]

example/lib/main.dart

import 'dart:convert';
import 'dart:developer';

import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:dopos_print/dopos_print.dart';
import 'package:permission_handler/permission_handler.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // Request Bluetooth permissions
  await _requestBluetoothPermission();
  runApp(const MyApp());
}

Future<void> _requestBluetoothPermission() async {
  if (Platform.isAndroid) {
    await _requestBluetoothPermissions();
    await _requestLocationPermission();
  }
}

Future<void> _requestBluetoothPermissions() async {
  PermissionStatus bluetoothScanPermission =
      await Permission.bluetoothScan.request();
  PermissionStatus bluetoothConnectPermission =
      await Permission.bluetoothConnect.request();

  if (bluetoothScanPermission.isGranted &&
      bluetoothConnectPermission.isGranted) {
    print("Bluetooth permissions granted");
  } else {
    print("Bluetooth permissions denied");
    if (bluetoothScanPermission.isPermanentlyDenied ||
        bluetoothConnectPermission.isPermanentlyDenied) {
      openAppSettings();
    }
  }
}

Future<void> _requestLocationPermission() async {
  PermissionStatus locationPermission =
      await Permission.locationWhenInUse.request();

  if (locationPermission.isGranted) {
    print("Location permission granted");
  } else if (locationPermission.isDenied) {
    print("Location permission denied");
  } else if (locationPermission.isPermanentlyDenied) {
    openAppSettings();
  }
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final DoposPrint _doposPrintPlugin = DoposPrint();
  List<Map<String, String>> _printers = [];
  String _jsonInput = '';
  String? _selectedPrinter;

  late Map<String, dynamic> _SAMPLE_JSON_INSTRUCTION_;
  TextEditingController _jsonD = TextEditingController();

  // New variables for LAN printing option
  TextEditingController _ipController = TextEditingController();
  TextEditingController _portController = TextEditingController();
  String _printerType = 'Bluetooth'; // To track which radio option is selected

  @override
  void initState() {
    super.initState();
    _checkPermissions();
  }

  Future<void> _checkPermissions() async {
    if (await Permission.bluetoothConnect.request().isGranted) {
      await _preparePrintInstructions();
      _jsonD.text = jsonEncode(_SAMPLE_JSON_INSTRUCTION_).toString();
      _loadPrinters();
    } else {
      // Handle permission denial gracefully
      print('Bluetooth/Storage permission denied!');
    }
  }

  Future<void> _preparePrintInstructions() async {
    final image = await _loadImagePathFromAssets('assets/images/image.png');
    _SAMPLE_JSON_INSTRUCTION_ = {
      "printerWidth": 384,
      "charLimit": 32,
      "startX": 0,
      "startY": 0,
      "data": [
        {
          "startX": 0,
          "endX": 100,
          "lineSpacing": 0,
          "imagePath": image,
          "imageWidth": 250,
          "imageHeight": 90,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": " ",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "DANGAPARA, SULTANPUR, BURDWAN",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "Phone: 8765346533",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "GSTIN: ",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "................................",
          "fontSize": 8,
          "fontWeight": "Bold",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": " ",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "TAX INVOICE",
          "fontSize": 10,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": " ",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 50,
          "text": "Date: 15/08/24",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "left",
          "isNewLine": false
        },
        {
          "startX": 50,
          "endX": 100,
          "text": "Time: 09:58:09",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "Bill No.: D9S1O0004",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "left",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "................................",
          "fontSize": 8,
          "fontWeight": "Bold",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 15,
          "text": "Sl.",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "left",
          "isNewLine": false
        },
        {
          "startX": 15,
          "endX": 68,
          "text": "ITEM",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "left",
          "isNewLine": false
        },
        {
          "startX": 71,
          "endX": 100,
          "text": "MRP",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 25,
          "text": "RATE",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": false
        },
        {
          "startX": 25,
          "endX": 50,
          "text": "QTY",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": false
        },
        {
          "startX": 50,
          "endX": 75,
          "text": "TAX%",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": false
        },
        {
          "startX": 75,
          "endX": 100,
          "text": "TOTAL",
          "fontSize": 8,
          "fontWeight": "Bold",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "................................",
          "fontSize": 8,
          "fontWeight": "Bold",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 15,
          "text": "1.",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "left",
          "isNewLine": false
        },
        {
          "startX": 15,
          "endX": 68,
          "text": "RACIRAFT SYRUP 250ML.",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "left",
          "isNewLine": false
        },
        {
          "startX": 70,
          "endX": 100,
          "text": "215.00",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 25,
          "text": "182.20",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": false
        },
        {
          "startX": 25,
          "endX": 50,
          "text": "1.000",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": false
        },
        {
          "startX": 50,
          "endX": 75,
          "text": "18.00",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": false
        },
        {
          "startX": 75,
          "endX": 100,
          "text": "215.00",
          "fontSize": 8,
          "fontWeight": "Bold",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "................................",
          "fontSize": 8,
          "fontWeight": "Bold",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 40,
          "text": "Total",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "left",
          "isNewLine": false
        },
        {
          "startX": 40,
          "endX": 100,
          "text": "215.00",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 40,
          "text": "Tax Amt.",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "left",
          "isNewLine": false
        },
        {
          "startX": 40,
          "endX": 100,
          "text": "32.80",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 40,
          "text": "Round off",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "left",
          "isNewLine": false
        },
        {
          "startX": 40,
          "endX": 100,
          "text": "0.00",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": " ",
          "fontSize": 10,
          "fontWeight": "Bold",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "Net Payable:  215",
          "fontSize": 10,
          "fontWeight": "Bold",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": " ",
          "fontSize": 10,
          "fontWeight": "Bold",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "ITEM(S)/QTY: 1/1.000",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "left",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "TOTAL INCL. OF ALL GST TAX.",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "left",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "********************************",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 50,
          "text": "TAX%",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "left",
          "isNewLine": false
        },
        {
          "startX": 50,
          "endX": 100,
          "text": "TAXABLE",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 33,
          "text": "CGST",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": false
        },
        {
          "startX": 33,
          "endX": 63,
          "text": "SGST",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": false
        },
        {
          "startX": 65,
          "endX": 100,
          "text": "TAX AMT",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "................................",
          "fontSize": 8,
          "fontWeight": "Bold",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 50,
          "text": "18.0%",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "left",
          "isNewLine": false
        },
        {
          "startX": 50,
          "endX": 100,
          "text": "182.20",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 33,
          "text": "16.40",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": false
        },
        {
          "startX": 33,
          "endX": 64,
          "text": "16.40",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": false
        },
        {
          "startX": 65,
          "endX": 100,
          "text": "32.80",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "********************************",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "YOU SAVED:  0.00",
          "fontSize": 10,
          "fontWeight": "Bold",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "********************************",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 60,
          "text": "Payment Mode:",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "left",
          "isNewLine": false
        },
        {
          "startX": 60,
          "endX": 100,
          "text": "CASH",
          "fontSize": 8,
          "fontWeight": "Bold",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 60,
          "text": "CASH:",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "left",
          "isNewLine": false
        },
        {
          "startX": 60,
          "endX": 100,
          "text": "215.00",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "right",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "................................",
          "fontSize": 8,
          "fontWeight": "Bold",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        },
        {
          "startX": 0,
          "endX": 100,
          "text": "Thank You, Visit again!!!",
          "fontSize": 8,
          "fontWeight": "Normal",
          "lineSpacing": 0,
          "align": "center",
          "isNewLine": true
        }
      ]
    };

    setState(() {});
  }

  Future<String> _loadImagePathFromAssets(String assetPath) async {
    final byteData = await rootBundle.load(assetPath);
    final tempDir = await getTemporaryDirectory();
    final file = File('${tempDir.path}/image.png');
    await file.writeAsBytes(byteData.buffer.asUint8List(), flush: true);
    return file.path;
  }

  Future<void> _loadPrinters() async {
    try {
      final printers = await _doposPrintPlugin.listPrinters();
      setState(() {
        _printers = printers;
      });
    } catch (e) {
      log('Failed to load printers: $e');
    }
  }

  Future<void> _print() async {
    _jsonInput = _jsonD.text;

    if (_jsonInput.isEmpty) {
      log('Please enter JSON data.');
      return;
    }

    try {
      final tempDir = await getTemporaryDirectory();
      final tempFile = File('${tempDir.path}/printInstructions.json');
      await tempFile.writeAsString(_jsonInput);

      if (_printerType == 'Bluetooth' && _selectedPrinter != null) {
        await _doposPrintPlugin.print(
          int.parse(_selectedPrinter!),
          tempFile.path,
        );
      } else if (_printerType == 'LAN') {
        String ip = _ipController.text;
        String port = _portController.text;

        if (ip.isNotEmpty && port.isNotEmpty) {
          await _doposPrintPlugin.ethernetPrint(ip, port, tempFile.path);
        } else {
          log('Please enter both IP and Port.');
        }
      }

      log('Print command sent successfully.');
    } on PlatformException catch (e) {
      log('Failed to send print command: ${e.message}');
    } catch (e) {
      log('Error: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Printer App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Printer App'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const SizedBox(height: 20),
              // Radio buttons to select printer type (Bluetooth or LAN)
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Radio<String>(
                    value: 'Bluetooth',
                    groupValue: _printerType,
                    onChanged: (String? value) {
                      setState(() {
                        _printerType = value!;
                      });
                    },
                  ),
                  const Text('Bluetooth Printer'),
                  Radio<String>(
                    value: 'LAN',
                    groupValue: _printerType,
                    onChanged: (String? value) {
                      setState(() {
                        _printerType = value!;
                      });
                    },
                  ),
                  const Text('LAN Printer'),
                ],
              ),
              const SizedBox(height: 20),
              if (_printerType == 'Bluetooth' && _printers.isNotEmpty)
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 16.0),
                  child: DropdownButton<String>(
                    hint: const Text('Select Printer'),
                    value: _selectedPrinter,
                    onChanged: (String? newValue) {
                      setState(() {
                        _selectedPrinter = newValue;
                      });
                    },
                    items: _printers.map((printer) {
                      final printerIndex = printer.keys.first;
                      final printerName = printer.values.first;
                      log("$printerIndex===>$printerName");
                      return DropdownMenuItem<String>(
                        value: printerIndex, // Ensure printerIndex is unique
                        child: Row(
                          children: <Widget>[
                            const Icon(Icons.print),
                            const SizedBox(width: 10),
                            Text(printerName),
                          ],
                        ),
                      );
                    }).toList(),
                  ),
                ),
              // If LAN printer is selected, show IP and Port input fields
              if (_printerType == 'LAN')
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 16.0),
                  child: Column(
                    children: [
                      TextField(
                        controller: _ipController,
                        decoration: const InputDecoration(
                          labelText: 'IP Address',
                          border: OutlineInputBorder(),
                        ),
                      ),
                      const SizedBox(height: 10),
                      TextField(
                        controller: _portController,
                        decoration: const InputDecoration(
                          labelText: 'Port',
                          border: OutlineInputBorder(),
                        ),
                      ),
                    ],
                  ),
                ),
              const SizedBox(height: 20),
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 16.0),
                child: TextField(
                  controller: _jsonD,
                  maxLines: 10,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: 'Enter JSON Data',
                  ),
                ),
              ),
              const SizedBox(height: 20),
              ElevatedButton(
                onPressed: _print,
                child: const Text('Print'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
2
likes
0
points
44
downloads

Publisher

unverified uploader

Weekly Downloads

***** EASY TO USE ***** The dopos_print plugin is a Flutter plugin designed to interface with thermal printers on Windows and Android (Bluetooth printers) OR Ethernet Printers. This plugin enables Flutter applications to list available thermal printers and send print jobs to a selected printer. The plugin supports printing text and images using JSON-formatted print instructions, allowing for flexible and customizable print layouts. It leverages the native Windows (c# and c++) and Android (JAVA).

Homepage

License

unknown (license)

Dependencies

flutter

More

Packages that depend on dopos_print