├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ └── styles.xml
│ │ │ ├── drawable-mdpi
│ │ │ │ └── logo.png
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── layout
│ │ │ │ └── activity_main.xml
│ │ │ └── drawable
│ │ │ │ └── ic_launcher_background.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── dantsu
│ │ │ │ └── thermalprinter
│ │ │ │ ├── async
│ │ │ │ ├── AsyncTcpEscPosPrint.java
│ │ │ │ ├── AsyncUsbEscPosPrint.java
│ │ │ │ ├── AsyncEscPosPrinter.java
│ │ │ │ ├── AsyncBluetoothEscPosPrint.java
│ │ │ │ └── AsyncEscPosPrint.java
│ │ │ │ └── MainActivity.java
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── dantsu
│ │ │ └── thermalprinter
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── dantsu
│ │ └── thermalprinter
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── escposprinter
├── consumer-rules.pro
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ └── values
│ │ │ │ └── strings.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── com
│ │ │ └── dantsu
│ │ │ └── escposprinter
│ │ │ ├── exceptions
│ │ │ ├── EscPosParserException.java
│ │ │ ├── EscPosBarcodeException.java
│ │ │ ├── EscPosEncodingException.java
│ │ │ └── EscPosConnectionException.java
│ │ │ ├── textparser
│ │ │ ├── IPrinterTextParserElement.java
│ │ │ ├── PrinterTextParserQRCode.java
│ │ │ ├── PrinterTextParserTag.java
│ │ │ ├── PrinterTextParserString.java
│ │ │ ├── PrinterTextParserLine.java
│ │ │ ├── PrinterTextParserBarcode.java
│ │ │ ├── PrinterTextParserImg.java
│ │ │ ├── PrinterTextParser.java
│ │ │ └── PrinterTextParserColumn.java
│ │ │ ├── barcode
│ │ │ ├── BarcodeEAN8.java
│ │ │ ├── BarcodeUPCA.java
│ │ │ ├── BarcodeEAN13.java
│ │ │ ├── Barcode128.java
│ │ │ ├── Barcode39.java
│ │ │ ├── BarcodeUPCE.java
│ │ │ ├── BarcodeNumber.java
│ │ │ └── Barcode.java
│ │ │ ├── EscPosCharsetEncoding.java
│ │ │ ├── connection
│ │ │ ├── usb
│ │ │ │ ├── UsbConnections.java
│ │ │ │ ├── UsbDeviceHelper.java
│ │ │ │ ├── UsbPrintersConnections.java
│ │ │ │ ├── UsbConnection.java
│ │ │ │ └── UsbOutputStream.java
│ │ │ ├── bluetooth
│ │ │ │ ├── BluetoothConnections.java
│ │ │ │ ├── BluetoothPrintersConnections.java
│ │ │ │ └── BluetoothConnection.java
│ │ │ ├── DeviceConnection.java
│ │ │ └── tcp
│ │ │ │ └── TcpConnection.java
│ │ │ ├── EscPosPrinterSize.java
│ │ │ └── EscPosPrinter.java
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── dantsu
│ │ │ └── escposprinter
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── dantsu
│ │ └── escposprinter
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
├── LICENSE
└── build.gradle
├── .github
└── FUNDING.yml
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── LICENSE
├── gradle.properties
├── gradlew.bat
├── gradlew
└── README.md
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/escposprinter/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: DantSu
2 |
--------------------------------------------------------------------------------
/escposprinter/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':escposprinter'
2 | rootProject.name='ThermalPrinter'
3 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ThermalPrinter
3 |
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DantSu/ESCPOS-ThermalPrinter-Android/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 | .externalNativeBuild
9 | .cxx
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DantSu/ESCPOS-ThermalPrinter-Android/HEAD/app/src/main/res/drawable-mdpi/logo.png
--------------------------------------------------------------------------------
/escposprinter/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ThermalPrinter ESC POS Bluetooth
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DantSu/ESCPOS-ThermalPrinter-Android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DantSu/ESCPOS-ThermalPrinter-Android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DantSu/ESCPOS-ThermalPrinter-Android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DantSu/ESCPOS-ThermalPrinter-Android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DantSu/ESCPOS-ThermalPrinter-Android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/escposprinter/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DantSu/ESCPOS-ThermalPrinter-Android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DantSu/ESCPOS-ThermalPrinter-Android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DantSu/ESCPOS-ThermalPrinter-Android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DantSu/ESCPOS-ThermalPrinter-Android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DantSu/ESCPOS-ThermalPrinter-Android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed May 03 12:31:57 CEST 2023
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/exceptions/EscPosParserException.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.exceptions;
2 |
3 | public class EscPosParserException extends Exception {
4 | public EscPosParserException(String errorMessage) {
5 | super(errorMessage);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/exceptions/EscPosBarcodeException.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.exceptions;
2 |
3 | public class EscPosBarcodeException extends Exception {
4 | public EscPosBarcodeException(String errorMessage) {
5 | super(errorMessage);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/exceptions/EscPosEncodingException.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.exceptions;
2 |
3 | public class EscPosEncodingException extends Exception {
4 | public EscPosEncodingException(String errorMessage) {
5 | super(errorMessage);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/exceptions/EscPosConnectionException.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.exceptions;
2 |
3 | public class EscPosConnectionException extends Exception {
4 | public EscPosConnectionException(String errorMessage) {
5 | super(errorMessage);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dantsu/thermalprinter/async/AsyncTcpEscPosPrint.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.thermalprinter.async;
2 |
3 | import android.content.Context;
4 |
5 | public class AsyncTcpEscPosPrint extends AsyncEscPosPrint {
6 | public AsyncTcpEscPosPrint(Context context) {
7 | super(context);
8 | }
9 |
10 | public AsyncTcpEscPosPrint(Context context, OnPrintFinished onPrintFinished) {
11 | super(context, onPrintFinished);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dantsu/thermalprinter/async/AsyncUsbEscPosPrint.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.thermalprinter.async;
2 |
3 | import android.content.Context;
4 |
5 | public class AsyncUsbEscPosPrint extends AsyncEscPosPrint {
6 | public AsyncUsbEscPosPrint(Context context) {
7 | super(context);
8 | }
9 |
10 | public AsyncUsbEscPosPrint(Context context, OnPrintFinished onPrintFinished) {
11 | super(context, onPrintFinished);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/test/java/com/dantsu/thermalprinter/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.thermalprinter;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/escposprinter/src/test/java/com/dantsu/escposprinter/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/textparser/IPrinterTextParserElement.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.textparser;
2 |
3 | import com.dantsu.escposprinter.EscPosPrinterCommands;
4 | import com.dantsu.escposprinter.exceptions.EscPosConnectionException;
5 | import com.dantsu.escposprinter.exceptions.EscPosEncodingException;
6 |
7 | public interface IPrinterTextParserElement {
8 | int length() throws EscPosEncodingException;
9 | IPrinterTextParserElement print(EscPosPrinterCommands printerSocket) throws EscPosEncodingException, EscPosConnectionException;
10 | }
11 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/barcode/BarcodeEAN8.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.barcode;
2 |
3 | import com.dantsu.escposprinter.EscPosPrinterCommands;
4 | import com.dantsu.escposprinter.EscPosPrinterSize;
5 | import com.dantsu.escposprinter.exceptions.EscPosBarcodeException;
6 |
7 | public class BarcodeEAN8 extends BarcodeNumber {
8 | public BarcodeEAN8(EscPosPrinterSize printerSize, String code, float widthMM, float heightMM, int textPosition) throws EscPosBarcodeException {
9 | super(printerSize, EscPosPrinterCommands.BARCODE_TYPE_EAN8, code, widthMM, heightMM, textPosition);
10 | }
11 |
12 | @Override
13 | public int getCodeLength() {
14 | return 8;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/barcode/BarcodeUPCA.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.barcode;
2 |
3 | import com.dantsu.escposprinter.EscPosPrinterCommands;
4 | import com.dantsu.escposprinter.EscPosPrinterSize;
5 | import com.dantsu.escposprinter.exceptions.EscPosBarcodeException;
6 |
7 | public class BarcodeUPCA extends BarcodeNumber {
8 |
9 | public BarcodeUPCA(EscPosPrinterSize printerSize, String code, float widthMM, float heightMM, int textPosition) throws EscPosBarcodeException {
10 | super(printerSize, EscPosPrinterCommands.BARCODE_TYPE_UPCA, code, widthMM, heightMM, textPosition);
11 | }
12 |
13 | @Override
14 | public int getCodeLength() {
15 | return 12;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/barcode/BarcodeEAN13.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.barcode;
2 |
3 | import com.dantsu.escposprinter.EscPosPrinterCommands;
4 | import com.dantsu.escposprinter.EscPosPrinterSize;
5 | import com.dantsu.escposprinter.exceptions.EscPosBarcodeException;
6 |
7 | public class BarcodeEAN13 extends BarcodeNumber {
8 |
9 | public BarcodeEAN13(EscPosPrinterSize printerSize, String code, float widthMM, float heightMM, int textPosition) throws EscPosBarcodeException {
10 | super(printerSize, EscPosPrinterCommands.BARCODE_TYPE_EAN13, code, widthMM, heightMM, textPosition);
11 | }
12 |
13 | @Override
14 | public int getCodeLength() {
15 | return 13;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/escposprinter/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/barcode/Barcode128.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.barcode;
2 |
3 | import com.dantsu.escposprinter.EscPosPrinterSize;
4 | import com.dantsu.escposprinter.EscPosPrinterCommands;
5 | import com.dantsu.escposprinter.exceptions.EscPosBarcodeException;
6 |
7 | public class Barcode128 extends Barcode {
8 | public Barcode128(EscPosPrinterSize printerSize, String code, float widthMM, float heightMM, int textPosition) throws EscPosBarcodeException {
9 | super(printerSize, EscPosPrinterCommands.BARCODE_TYPE_128, code, widthMM, heightMM, textPosition);
10 | }
11 |
12 | @Override
13 | public int getCodeLength() {
14 | return this.code.length();
15 | }
16 |
17 | @Override
18 | public int getColsCount() {
19 | return (this.getCodeLength() + 5) * 11;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/barcode/Barcode39.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.barcode;
2 |
3 | import com.dantsu.escposprinter.EscPosPrinterSize;
4 | import com.dantsu.escposprinter.EscPosPrinterCommands;
5 | import com.dantsu.escposprinter.exceptions.EscPosBarcodeException;
6 |
7 | public class Barcode39 extends Barcode {
8 | public Barcode39(EscPosPrinterSize printerSize, String code, float widthMM, float heightMM, int textPosition) throws EscPosBarcodeException {
9 | super(printerSize, EscPosPrinterCommands.BARCODE_TYPE_39, code, widthMM, heightMM, textPosition);
10 | }
11 |
12 | @Override
13 | public int getCodeLength() {
14 | return this.code.length();
15 | }
16 |
17 | @Override
18 | public int getColsCount() {
19 | return (this.getCodeLength() + 4) * 16;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/EscPosCharsetEncoding.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter;
2 |
3 | public class EscPosCharsetEncoding {
4 | private String charsetName;
5 | private byte[] charsetCommand;
6 |
7 | /**
8 | * Create new instance of EscPosCharsetEncoding.
9 | *
10 | * @param charsetName Name of charset encoding (Ex: windows-1252)
11 | * @param escPosCharsetId Id of charset encoding for your printer (Ex: 16)
12 | */
13 | public EscPosCharsetEncoding(String charsetName, int escPosCharsetId) {
14 | this.charsetName = charsetName;
15 | this.charsetCommand = new byte[]{0x1B, 0x74, (byte) escPosCharsetId};
16 | }
17 |
18 | public byte[] getCommand() {
19 | return this.charsetCommand;
20 | }
21 |
22 | public String getName() {
23 | return this.charsetName;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/dantsu/thermalprinter/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.thermalprinter;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android usbDevice.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 |
25 | assertEquals("com.dantsu.thermalprinter", appContext.getPackageName());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/escposprinter/src/androidTest/java/com/dantsu/escposprinter/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android usbDevice.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 |
25 | assertEquals("com.dantsu.thermalprinter_escpos.test", appContext.getPackageName());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Franck ALARY
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 33
5 | defaultConfig {
6 | applicationId "com.dantsu.thermalprinter"
7 | minSdkVersion 16
8 | targetSdkVersion 33
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
12 | }
13 | compileOptions {
14 | sourceCompatibility JavaVersion.VERSION_1_8
15 | targetCompatibility JavaVersion.VERSION_1_8
16 | }
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | }
24 |
25 | dependencies {
26 | implementation fileTree(dir: 'libs', include: ['*.jar'])
27 | implementation 'androidx.appcompat:appcompat:1.6.1'
28 | testImplementation 'junit:junit:4.12'
29 | androidTestImplementation 'androidx.test.ext:junit:1.1.5'
30 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
31 | implementation project(path: ':escposprinter')
32 | }
33 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 |
21 |
--------------------------------------------------------------------------------
/escposprinter/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Franck ALARY
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
22 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dantsu/thermalprinter/async/AsyncEscPosPrinter.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.thermalprinter.async;
2 |
3 | import com.dantsu.escposprinter.EscPosPrinterSize;
4 | import com.dantsu.escposprinter.connection.DeviceConnection;
5 |
6 | public class AsyncEscPosPrinter extends EscPosPrinterSize {
7 | private DeviceConnection printerConnection;
8 | private String[] textsToPrint = new String[0];
9 |
10 | public AsyncEscPosPrinter(DeviceConnection printerConnection, int printerDpi, float printerWidthMM, int printerNbrCharactersPerLine) {
11 | super(printerDpi, printerWidthMM, printerNbrCharactersPerLine);
12 | this.printerConnection = printerConnection;
13 | }
14 |
15 | public DeviceConnection getPrinterConnection() {
16 | return this.printerConnection;
17 | }
18 |
19 | public AsyncEscPosPrinter setTextsToPrint(String[] textsToPrint) {
20 | this.textsToPrint = textsToPrint;
21 | return this;
22 | }
23 |
24 | public AsyncEscPosPrinter addTextToPrint(String textToPrint) {
25 | String[] tmp = new String[this.textsToPrint.length + 1];
26 | System.arraycopy(this.textsToPrint, 0, tmp, 0, this.textsToPrint.length);
27 | tmp[this.textsToPrint.length] = textToPrint;
28 | this.textsToPrint = tmp;
29 | return this;
30 | }
31 |
32 | public String[] getTextsToPrint() {
33 | return this.textsToPrint;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/connection/usb/UsbConnections.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.connection.usb;
2 |
3 | import android.content.Context;
4 | import android.hardware.usb.UsbDevice;
5 | import android.hardware.usb.UsbManager;
6 |
7 | import androidx.annotation.Nullable;
8 |
9 | import java.util.Collection;
10 |
11 | public class UsbConnections {
12 | protected UsbManager usbManager;
13 |
14 | /**
15 | * Create a new instance of UsbConnections
16 | *
17 | * @param context Application context
18 | */
19 | public UsbConnections(Context context) {
20 | this.usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
21 | }
22 |
23 | /**
24 | * Get a list of USB devices available.
25 | * @return Return an array of UsbConnection instance
26 | */
27 | @Nullable
28 | public UsbConnection[] getList() {
29 | if (this.usbManager == null) {
30 | return null;
31 | }
32 |
33 | Collection devicesList = this.usbManager.getDeviceList().values();
34 | UsbConnection[] usbDevices = new UsbConnection[devicesList.size()];
35 |
36 | if (devicesList.size() > 0) {
37 | int i = 0;
38 | for (UsbDevice device : devicesList) {
39 | usbDevices[i++] = new UsbConnection(this.usbManager, device);
40 | }
41 | }
42 |
43 | return usbDevices;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/barcode/BarcodeUPCE.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.barcode;
2 |
3 | import com.dantsu.escposprinter.EscPosPrinterCommands;
4 | import com.dantsu.escposprinter.EscPosPrinterSize;
5 | import com.dantsu.escposprinter.exceptions.EscPosBarcodeException;
6 |
7 | public class BarcodeUPCE extends Barcode {
8 |
9 | public BarcodeUPCE(EscPosPrinterSize printerSize, String code, float widthMM, float heightMM, int textPosition) throws EscPosBarcodeException {
10 | super(printerSize, EscPosPrinterCommands.BARCODE_TYPE_UPCE, code, widthMM, heightMM, textPosition);
11 | this.checkCode();
12 | }
13 |
14 | public int getCodeLength() {
15 | return 6;
16 | }
17 |
18 | @Override
19 | public int getColsCount() {
20 | return this.getCodeLength() * 7 + 16;
21 | }
22 |
23 | private void checkCode() throws EscPosBarcodeException {
24 | int codeLength = this.getCodeLength();
25 |
26 | if (this.code.length() < codeLength) {
27 | throw new EscPosBarcodeException("Code is too short for the barcode type.");
28 | }
29 |
30 | try {
31 | this.code = this.code.substring(0, codeLength);
32 | for (int i = 0; i < codeLength; i++) {
33 | Integer.parseInt(this.code.substring(i, i + 1), 10);
34 | }
35 | } catch (NumberFormatException e) {
36 | e.printStackTrace();
37 | throw new EscPosBarcodeException("Invalid barcode number");
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/connection/bluetooth/BluetoothConnections.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.connection.bluetooth;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.bluetooth.BluetoothAdapter;
5 | import android.bluetooth.BluetoothDevice;
6 |
7 | import androidx.annotation.Nullable;
8 |
9 | import java.util.Set;
10 |
11 | public class BluetoothConnections {
12 | protected BluetoothAdapter bluetoothAdapter;
13 |
14 | /**
15 | * Create a new instance of BluetoothConnections
16 | */
17 | public BluetoothConnections() {
18 | this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
19 | }
20 |
21 | /**
22 | * Get a list of bluetooth devices available.
23 | * @return Return an array of BluetoothConnection instance
24 | */
25 | @SuppressLint("MissingPermission")
26 | @Nullable
27 | public BluetoothConnection[] getList() {
28 | if (this.bluetoothAdapter == null) {
29 | return null;
30 | }
31 |
32 | if(!this.bluetoothAdapter.isEnabled()) {
33 | return null;
34 | }
35 |
36 | Set bluetoothDevicesList = this.bluetoothAdapter.getBondedDevices();
37 | BluetoothConnection[] bluetoothDevices = new BluetoothConnection[bluetoothDevicesList.size()];
38 |
39 | if (bluetoothDevicesList.size() > 0) {
40 | int i = 0;
41 | for (BluetoothDevice device : bluetoothDevicesList) {
42 | bluetoothDevices[i++] = new BluetoothConnection(device);
43 | }
44 | }
45 |
46 | return bluetoothDevices;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/escposprinter/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.library'
3 | id 'maven-publish'
4 | }
5 |
6 | def libraryVersionCode = 3003000
7 | def libraryVersionName = "3.3.0"
8 |
9 | android {
10 | compileSdkVersion 33
11 |
12 | defaultConfig {
13 | minSdkVersion 16
14 | targetSdkVersion 33
15 | versionCode libraryVersionCode
16 | versionName libraryVersionName
17 |
18 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
19 | consumerProguardFiles 'consumer-rules.pro'
20 | }
21 |
22 | buildTypes {
23 | release {
24 | minifyEnabled false
25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
26 | }
27 | }
28 |
29 | }
30 |
31 | dependencies {
32 | implementation fileTree(dir: 'libs', include: ['*.jar'])
33 |
34 | implementation 'androidx.appcompat:appcompat:1.6.1'
35 | implementation 'com.google.zxing:core:3.4.0'
36 | testImplementation 'junit:junit:4.13.2'
37 | androidTestImplementation 'androidx.test.ext:junit:1.1.5'
38 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
39 | }
40 |
41 |
42 | afterEvaluate {
43 | publishing {
44 | publications {
45 | release(MavenPublication) {
46 | groupId = 'com.github.DantSu'
47 | artifactId = 'ESCPOS-ThermalPrinter-Android'
48 | version = libraryVersionName
49 | pom {
50 | name = 'Android library for ESC/POS Thermal Printer'
51 | description = 'Useful library to help Android developers to print with (Bluetooth, TCP, USB) ESC/POS thermal printers.'
52 | }
53 | afterEvaluate {
54 | from components.release
55 | }
56 | }
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/dantsu/thermalprinter/async/AsyncBluetoothEscPosPrint.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.thermalprinter.async;
2 |
3 | import android.content.Context;
4 |
5 | import com.dantsu.escposprinter.connection.DeviceConnection;
6 | import com.dantsu.escposprinter.connection.bluetooth.BluetoothPrintersConnections;
7 | import com.dantsu.escposprinter.exceptions.EscPosConnectionException;
8 |
9 | public class AsyncBluetoothEscPosPrint extends AsyncEscPosPrint {
10 | public AsyncBluetoothEscPosPrint(Context context) {
11 | super(context);
12 | }
13 |
14 | public AsyncBluetoothEscPosPrint(Context context, OnPrintFinished onPrintFinished) {
15 | super(context, onPrintFinished);
16 | }
17 |
18 | protected PrinterStatus doInBackground(AsyncEscPosPrinter... printersData) {
19 | if (printersData.length == 0) {
20 | return new PrinterStatus(null, AsyncEscPosPrint.FINISH_NO_PRINTER);
21 | }
22 |
23 | AsyncEscPosPrinter printerData = printersData[0];
24 | DeviceConnection deviceConnection = printerData.getPrinterConnection();
25 |
26 | this.publishProgress(AsyncEscPosPrint.PROGRESS_CONNECTING);
27 |
28 | if (deviceConnection == null) {
29 | printersData[0] = new AsyncEscPosPrinter(
30 | BluetoothPrintersConnections.selectFirstPaired(),
31 | printerData.getPrinterDpi(),
32 | printerData.getPrinterWidthMM(),
33 | printerData.getPrinterNbrCharactersPerLine()
34 | );
35 | printersData[0].setTextsToPrint(printerData.getTextsToPrint());
36 | } else {
37 | try {
38 | deviceConnection.connect();
39 | } catch (EscPosConnectionException e) {
40 | e.printStackTrace();
41 | }
42 | }
43 |
44 | return super.doInBackground(printersData);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/connection/usb/UsbDeviceHelper.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.connection.usb;
2 |
3 | import android.hardware.usb.UsbConstants;
4 | import android.hardware.usb.UsbDevice;
5 | import android.hardware.usb.UsbEndpoint;
6 | import android.hardware.usb.UsbInterface;
7 |
8 | import androidx.annotation.Nullable;
9 |
10 | public class UsbDeviceHelper {
11 | /**
12 | * Find the correct USB interface for printing
13 | *
14 | * @param usbDevice USB device
15 | * @return correct USB interface for printing, null if not found
16 | */
17 | @Nullable
18 | static public UsbInterface findPrinterInterface(UsbDevice usbDevice) {
19 | if (usbDevice == null) {
20 | return null;
21 | }
22 | int interfacesCount = usbDevice.getInterfaceCount();
23 | for (int i = 0; i < interfacesCount; i++) {
24 | UsbInterface usbInterface = usbDevice.getInterface(i);
25 | if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_PRINTER) {
26 | return usbInterface;
27 | }
28 | }
29 | return null;
30 | }
31 |
32 | /**
33 | * Find the USB endpoint for device input
34 | *
35 | * @param usbInterface USB interface
36 | * @return Input endpoint or null if not found
37 | */
38 | @Nullable
39 | static public UsbEndpoint findEndpointIn(UsbInterface usbInterface) {
40 | if (usbInterface != null) {
41 | int endpointsCount = usbInterface.getEndpointCount();
42 | for (int i = 0; i < endpointsCount; i++) {
43 | UsbEndpoint endpoint = usbInterface.getEndpoint(i);
44 | if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK && endpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
45 | return endpoint;
46 | }
47 | }
48 | }
49 | return null;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/barcode/BarcodeNumber.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.barcode;
2 |
3 | import com.dantsu.escposprinter.EscPosPrinterSize;
4 | import com.dantsu.escposprinter.exceptions.EscPosBarcodeException;
5 |
6 | public abstract class BarcodeNumber extends Barcode {
7 |
8 | public BarcodeNumber(EscPosPrinterSize printerSize, int barcodeType, String code, float widthMM, float heightMM, int textPosition) throws EscPosBarcodeException {
9 | super(printerSize, barcodeType, code, widthMM, heightMM, textPosition);
10 | this.checkCode();
11 | }
12 |
13 | @Override
14 | public int getColsCount() {
15 | return this.getCodeLength() * 7 + 11;
16 | }
17 |
18 | private void checkCode() throws EscPosBarcodeException {
19 | int codeLength = this.getCodeLength() - 1;
20 |
21 | if (this.code.length() < codeLength) {
22 | throw new EscPosBarcodeException("Code is too short for the barcode type.");
23 | }
24 |
25 | try {
26 |
27 | String code = this.code.substring(0, codeLength);
28 | int totalBarcodeKey = 0;
29 | for (int i = 0; i < codeLength; i++) {
30 | int
31 | pos = codeLength - 1 - i,
32 | intCode = Integer.parseInt(code.substring(pos, pos + 1), 10);
33 | if (i % 2 == 0) {
34 | intCode = 3 * intCode;
35 | }
36 | totalBarcodeKey += intCode;
37 | }
38 |
39 | String barcodeKey = String.valueOf(10 - (totalBarcodeKey % 10));
40 | if (barcodeKey.length() == 2) {
41 | barcodeKey = "0";
42 | }
43 | this.code = code + barcodeKey;
44 |
45 | } catch (NumberFormatException e) {
46 | e.printStackTrace();
47 | throw new EscPosBarcodeException("Invalid barcode number");
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/barcode/Barcode.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.barcode;
2 |
3 | import com.dantsu.escposprinter.EscPosPrinterSize;
4 | import com.dantsu.escposprinter.exceptions.EscPosBarcodeException;
5 |
6 | public abstract class Barcode {
7 |
8 | protected int barcodeType;
9 | protected String code;
10 | protected int colWidth;
11 | protected int height;
12 | protected int textPosition;
13 |
14 | Barcode(EscPosPrinterSize printerSize, int barcodeType, String code, float widthMM, float heightMM, int textPosition) throws EscPosBarcodeException {
15 | this.barcodeType = barcodeType;
16 | this.code = code;
17 | this.height = printerSize.mmToPx(heightMM);
18 | this.textPosition = textPosition;
19 |
20 | if(widthMM == 0f) {
21 | widthMM = printerSize.getPrinterWidthMM() * 0.7f;
22 | }
23 |
24 | int
25 | wantedPxWidth = widthMM > printerSize.getPrinterWidthMM() ? printerSize.getPrinterWidthPx() : printerSize.mmToPx(widthMM),
26 | colWidth = (int)Math.round((double) wantedPxWidth / (double) this.getColsCount());
27 |
28 | if((colWidth * this.getColsCount()) > printerSize.getPrinterWidthPx()) {
29 | --colWidth;
30 | }
31 |
32 | if(colWidth == 0) {
33 | throw new EscPosBarcodeException("Barcode is too long for the paper size.");
34 | }
35 |
36 | this.colWidth = colWidth;
37 | }
38 |
39 | public abstract int getCodeLength();
40 |
41 | public abstract int getColsCount();
42 |
43 | public int getBarcodeType() {
44 | return this.barcodeType;
45 | }
46 |
47 | public String getCode() {
48 | return this.code;
49 | }
50 |
51 | public int getHeight() {
52 | return this.height;
53 | }
54 |
55 | public int getTextPosition() {
56 | return this.textPosition;
57 | }
58 |
59 | public int getColWidth() {
60 | return this.colWidth;
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/connection/DeviceConnection.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.connection;
2 |
3 | import com.dantsu.escposprinter.exceptions.EscPosConnectionException;
4 |
5 | import java.io.IOException;
6 | import java.io.OutputStream;
7 |
8 | public abstract class DeviceConnection {
9 | protected OutputStream outputStream;
10 | protected byte[] data;
11 |
12 | public DeviceConnection() {
13 | this.outputStream = null;
14 | this.data = new byte[0];
15 | }
16 |
17 | public abstract DeviceConnection connect() throws EscPosConnectionException;
18 | public abstract DeviceConnection disconnect();
19 |
20 | /**
21 | * Check if OutputStream is open.
22 | *
23 | * @return true if is connected
24 | */
25 | public boolean isConnected() {
26 | return this.outputStream != null;
27 | }
28 |
29 | /**
30 | * Add data to send.
31 | */
32 | public void write(byte[] bytes) {
33 | byte[] data = new byte[bytes.length + this.data.length];
34 | System.arraycopy(this.data, 0, data, 0, this.data.length);
35 | System.arraycopy(bytes, 0, data, this.data.length, bytes.length);
36 | this.data = data;
37 | }
38 |
39 |
40 | /**
41 | * Send data to the device.
42 | */
43 | public void send() throws EscPosConnectionException {
44 | this.send(0);
45 | }
46 | /**
47 | * Send data to the device.
48 | */
49 | public void send(int addWaitingTime) throws EscPosConnectionException {
50 | if(!this.isConnected()) {
51 | throw new EscPosConnectionException("Unable to send data to device.");
52 | }
53 | try {
54 | this.outputStream.write(this.data);
55 | this.outputStream.flush();
56 | int waitingTime = addWaitingTime + this.data.length / 16;
57 | this.data = new byte[0];
58 | if(waitingTime > 0) {
59 | Thread.sleep(waitingTime);
60 | }
61 | } catch (IOException | InterruptedException e) {
62 | e.printStackTrace();
63 | throw new EscPosConnectionException(e.getMessage());
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/textparser/PrinterTextParserQRCode.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.textparser;
2 |
3 | import com.dantsu.escposprinter.EscPosPrinter;
4 | import com.dantsu.escposprinter.EscPosPrinterCommands;
5 | import com.dantsu.escposprinter.exceptions.EscPosBarcodeException;
6 | import com.dantsu.escposprinter.exceptions.EscPosEncodingException;
7 | import com.dantsu.escposprinter.exceptions.EscPosParserException;
8 |
9 | import java.util.Hashtable;
10 |
11 | public class PrinterTextParserQRCode extends PrinterTextParserImg {
12 |
13 | private static byte[] initConstructor(PrinterTextParserColumn printerTextParserColumn,
14 | Hashtable qrCodeAttributes, String data) throws EscPosParserException, EscPosBarcodeException {
15 | EscPosPrinter printer = printerTextParserColumn.getLine().getTextParser().getPrinter();
16 | data = data.trim();
17 |
18 | int size = printer.mmToPx(20f);
19 |
20 | if (qrCodeAttributes.containsKey(PrinterTextParser.ATTR_QRCODE_SIZE)) {
21 | String qrCodeAttribute = qrCodeAttributes.get(PrinterTextParser.ATTR_QRCODE_SIZE);
22 | if (qrCodeAttribute == null) {
23 | throw new EscPosParserException("Invalid QR code attribute : " + PrinterTextParser.ATTR_QRCODE_SIZE);
24 | }
25 | try {
26 | size = printer.mmToPx(Float.parseFloat(qrCodeAttribute));
27 | } catch(NumberFormatException nfe) {
28 | throw new EscPosParserException("Invalid QR code " + PrinterTextParser.ATTR_QRCODE_SIZE + " value");
29 | }
30 | }
31 |
32 | return EscPosPrinterCommands.QRCodeDataToBytes(data, size);
33 | }
34 |
35 | public PrinterTextParserQRCode(PrinterTextParserColumn printerTextParserColumn, String textAlign,
36 | Hashtable qrCodeAttributes, String data) throws EscPosParserException, EscPosBarcodeException {
37 | super(
38 | printerTextParserColumn,
39 | textAlign,
40 | PrinterTextParserQRCode.initConstructor(printerTextParserColumn, qrCodeAttributes, data)
41 | );
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/connection/usb/UsbPrintersConnections.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.connection.usb;
2 |
3 | import android.content.Context;
4 | import android.hardware.usb.UsbConstants;
5 | import android.hardware.usb.UsbDevice;
6 |
7 | import androidx.annotation.Nullable;
8 |
9 | import com.dantsu.escposprinter.exceptions.EscPosConnectionException;
10 |
11 | public class UsbPrintersConnections extends UsbConnections {
12 |
13 | /**
14 | * Create a new instance of UsbPrintersConnections
15 | *
16 | * @param context Application context
17 | */
18 | public UsbPrintersConnections(Context context) {
19 | super(context);
20 | }
21 |
22 | /**
23 | * Easy way to get the first USB printer paired / connected.
24 | *
25 | * @return a UsbConnection instance
26 | */
27 | @Nullable
28 | public static UsbConnection selectFirstConnected(Context context) {
29 | UsbPrintersConnections printers = new UsbPrintersConnections(context);
30 | UsbConnection[] bluetoothPrinters = printers.getList();
31 |
32 | if (bluetoothPrinters == null || bluetoothPrinters.length == 0) {
33 | return null;
34 | }
35 |
36 | return bluetoothPrinters[0];
37 | }
38 |
39 |
40 | /**
41 | * Get a list of USB printers.
42 | *
43 | * @return an array of UsbConnection
44 | */
45 | @Nullable
46 | public UsbConnection[] getList() {
47 | UsbConnection[] usbConnections = super.getList();
48 |
49 | if(usbConnections == null) {
50 | return null;
51 | }
52 |
53 | int i = 0;
54 | UsbConnection[] printersTmp = new UsbConnection[usbConnections.length];
55 | for (UsbConnection usbConnection : usbConnections) {
56 | UsbDevice device = usbConnection.getDevice();
57 | int usbClass = device.getDeviceClass();
58 | if((usbClass == UsbConstants.USB_CLASS_PER_INTERFACE || usbClass == UsbConstants.USB_CLASS_MISC ) && UsbDeviceHelper.findPrinterInterface(device) != null) {
59 | usbClass = UsbConstants.USB_CLASS_PRINTER;
60 | }
61 | if (usbClass == UsbConstants.USB_CLASS_PRINTER) {
62 | printersTmp[i++] = new UsbConnection(this.usbManager, device);
63 | }
64 | }
65 |
66 | UsbConnection[] usbPrinters = new UsbConnection[i];
67 | System.arraycopy(printersTmp, 0, usbPrinters, 0, i);
68 | return usbPrinters;
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/connection/bluetooth/BluetoothPrintersConnections.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.connection.bluetooth;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.bluetooth.BluetoothClass;
5 | import android.bluetooth.BluetoothDevice;
6 |
7 | import androidx.annotation.Nullable;
8 |
9 | import com.dantsu.escposprinter.exceptions.EscPosConnectionException;
10 |
11 | public class BluetoothPrintersConnections extends BluetoothConnections {
12 |
13 | /**
14 | * Easy way to get the first bluetooth printer paired / connected.
15 | *
16 | * @return a EscPosPrinterCommands instance
17 | */
18 | @Nullable
19 | public static BluetoothConnection selectFirstPaired() {
20 | BluetoothPrintersConnections printers = new BluetoothPrintersConnections();
21 | BluetoothConnection[] bluetoothPrinters = printers.getList();
22 |
23 | if (bluetoothPrinters != null && bluetoothPrinters.length > 0) {
24 | for (BluetoothConnection printer : bluetoothPrinters) {
25 | try {
26 | return printer.connect();
27 | } catch (EscPosConnectionException e) {
28 | e.printStackTrace();
29 | }
30 | }
31 | }
32 | return null;
33 | }
34 |
35 | /**
36 | * Get a list of bluetooth printers.
37 | *
38 | * @return an array of EscPosPrinterCommands
39 | */
40 | @SuppressLint("MissingPermission")
41 | @Nullable
42 | public BluetoothConnection[] getList() {
43 | BluetoothConnection[] bluetoothDevicesList = super.getList();
44 |
45 | if (bluetoothDevicesList == null) {
46 | return null;
47 | }
48 |
49 | int i = 0;
50 | BluetoothConnection[] printersTmp = new BluetoothConnection[bluetoothDevicesList.length];
51 | for (BluetoothConnection bluetoothConnection : bluetoothDevicesList) {
52 | BluetoothDevice device = bluetoothConnection.getDevice();
53 |
54 | int majDeviceCl = device.getBluetoothClass().getMajorDeviceClass(),
55 | deviceCl = device.getBluetoothClass().getDeviceClass();
56 |
57 | if (majDeviceCl == BluetoothClass.Device.Major.IMAGING && (deviceCl == 1664 || deviceCl == BluetoothClass.Device.Major.IMAGING)) {
58 | printersTmp[i++] = new BluetoothConnection(device);
59 | }
60 | }
61 | BluetoothConnection[] bluetoothPrinters = new BluetoothConnection[i];
62 | System.arraycopy(printersTmp, 0, bluetoothPrinters, 0, i);
63 | return bluetoothPrinters;
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/textparser/PrinterTextParserTag.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.textparser;
2 |
3 | import java.util.Hashtable;
4 |
5 | public class PrinterTextParserTag {
6 |
7 | private String tagName = "";
8 | private Hashtable attributes = new Hashtable();
9 | private int length = 0;
10 | private boolean isCloseTag = false;
11 |
12 | public PrinterTextParserTag(String tag) {
13 | tag = tag.trim();
14 |
15 | if(!tag.substring(0, 1).equals("<") || !tag.substring(tag.length() - 1).equals(">")) {
16 | return;
17 | }
18 |
19 | this.length = tag.length();
20 | int openTagIndex = tag.indexOf("<"),
21 | closeTagIndex = tag.indexOf(">"),
22 | nextSpaceIndex = tag.indexOf(" ");
23 |
24 | if(nextSpaceIndex != -1 && nextSpaceIndex < closeTagIndex) {
25 | this.tagName = tag.substring(openTagIndex + 1, nextSpaceIndex).toLowerCase();
26 |
27 | String attributesString = tag.substring(nextSpaceIndex, closeTagIndex).trim();
28 | while (attributesString.contains("='")) {
29 | int egalPos = attributesString.indexOf("='"), endPos = attributesString.indexOf("'", egalPos + 2);
30 |
31 | String attributeName = attributesString.substring(0, egalPos);
32 | String attributeValue = attributesString.substring(egalPos + 2, endPos);
33 |
34 | if(!attributeName.equals("")) {
35 | this.attributes.put(attributeName, attributeValue);
36 | }
37 |
38 | attributesString = attributesString.substring(endPos + 1).trim();
39 | }
40 | } else {
41 | this.tagName = tag.substring(openTagIndex + 1, closeTagIndex).toLowerCase();
42 | }
43 |
44 |
45 | if(this.tagName.substring(0, 1).equals("/")) {
46 | this.tagName = this.tagName.substring(1);
47 | this.isCloseTag = true;
48 | }
49 | }
50 |
51 | public String getTagName() {
52 | return this.tagName;
53 | }
54 |
55 | public Hashtable getAttributes() {
56 | return this.attributes;
57 | }
58 |
59 | public String getAttribute(String key) {
60 | return this.attributes.get(key);
61 | }
62 | public boolean hasAttribute(String key) {
63 | return this.attributes.containsKey(key);
64 | }
65 |
66 | public int getLength() {
67 | return this.length;
68 | }
69 |
70 | public boolean isCloseTag() {
71 | return this.isCloseTag;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/connection/usb/UsbConnection.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.connection.usb;
2 |
3 | import android.hardware.usb.UsbDevice;
4 | import android.hardware.usb.UsbManager;
5 |
6 | import com.dantsu.escposprinter.connection.DeviceConnection;
7 | import com.dantsu.escposprinter.exceptions.EscPosConnectionException;
8 |
9 | import java.io.IOException;
10 |
11 | public class UsbConnection extends DeviceConnection {
12 |
13 | private UsbManager usbManager;
14 | private UsbDevice usbDevice;
15 |
16 | /**
17 | * Create un instance of UsbConnection.
18 | *
19 | * @param usbManager an instance of UsbManager
20 | * @param usbDevice an instance of UsbDevice
21 | */
22 | public UsbConnection(UsbManager usbManager, UsbDevice usbDevice) {
23 | super();
24 | this.usbManager = usbManager;
25 | this.usbDevice = usbDevice;
26 | }
27 |
28 | /**
29 | * Get the instance UsbDevice connected.
30 | *
31 | * @return an instance of UsbDevice
32 | */
33 | public UsbDevice getDevice() {
34 | return this.usbDevice;
35 | }
36 |
37 | /**
38 | * Start socket connection with the usbDevice.
39 | */
40 | public UsbConnection connect() throws EscPosConnectionException {
41 | if (this.isConnected()) {
42 | return this;
43 | }
44 |
45 | try {
46 | this.outputStream = new UsbOutputStream(this.usbManager, this.usbDevice);
47 | this.data = new byte[0];
48 | } catch (IOException e) {
49 | e.printStackTrace();
50 | this.outputStream = null;
51 | throw new EscPosConnectionException("Unable to connect to USB device.");
52 | }
53 | return this;
54 | }
55 |
56 | /**
57 | * Close the socket connection with the usbDevice.
58 | */
59 | public UsbConnection disconnect() {
60 | this.data = new byte[0];
61 | if (this.isConnected()) {
62 | try {
63 | this.outputStream.close();
64 | } catch (IOException e) {
65 | e.printStackTrace();
66 | }
67 | this.outputStream = null;
68 | }
69 | return this;
70 | }
71 |
72 | /**
73 | * Send data to the device.
74 | */
75 | public void send() throws EscPosConnectionException {
76 | this.send(0);
77 | }
78 | /**
79 | * Send data to the device.
80 | */
81 | public void send(int addWaitingTime) throws EscPosConnectionException {
82 | try {
83 | this.outputStream.write(this.data);
84 | this.data = new byte[0];
85 | } catch (IOException e) {
86 | e.printStackTrace();
87 | throw new EscPosConnectionException(e.getMessage());
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/connection/usb/UsbOutputStream.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.connection.usb;
2 |
3 | import android.hardware.usb.UsbDevice;
4 | import android.hardware.usb.UsbDeviceConnection;
5 | import android.hardware.usb.UsbEndpoint;
6 | import android.hardware.usb.UsbInterface;
7 | import android.hardware.usb.UsbManager;
8 | import android.hardware.usb.UsbRequest;
9 |
10 | import androidx.annotation.NonNull;
11 |
12 | import java.io.IOException;
13 | import java.io.OutputStream;
14 | import java.nio.ByteBuffer;
15 |
16 | public class UsbOutputStream extends OutputStream {
17 | private UsbDeviceConnection usbConnection;
18 | private UsbInterface usbInterface;
19 | private UsbEndpoint usbEndpoint;
20 |
21 | public UsbOutputStream(UsbManager usbManager, UsbDevice usbDevice) throws IOException {
22 |
23 | this.usbInterface = UsbDeviceHelper.findPrinterInterface(usbDevice);
24 | if(this.usbInterface == null) {
25 | throw new IOException("Unable to find USB interface.");
26 | }
27 |
28 | this.usbEndpoint = UsbDeviceHelper.findEndpointIn(this.usbInterface);
29 | if(this.usbEndpoint == null) {
30 | throw new IOException("Unable to find USB endpoint.");
31 | }
32 |
33 | this.usbConnection = usbManager.openDevice(usbDevice);
34 | if(this.usbConnection == null) {
35 | throw new IOException("Unable to open USB connection.");
36 | }
37 | }
38 |
39 | @Override
40 | public void write(int i) throws IOException {
41 | this.write(new byte[]{(byte) i});
42 | }
43 |
44 | @Override
45 | public void write(@NonNull byte[] bytes) throws IOException {
46 | this.write(bytes, 0, bytes.length);
47 | }
48 |
49 | @Override
50 | public void write(final @NonNull byte[] bytes, final int offset, final int length) throws IOException {
51 | if (this.usbInterface == null || this.usbEndpoint == null || this.usbConnection == null) {
52 | throw new IOException("Unable to connect to USB device.");
53 | }
54 |
55 | if (!this.usbConnection.claimInterface(this.usbInterface, true)) {
56 | throw new IOException("Error during claim USB interface.");
57 | }
58 |
59 | ByteBuffer buffer = ByteBuffer.wrap(bytes);
60 | UsbRequest usbRequest = new UsbRequest();
61 | try {
62 | usbRequest.initialize(this.usbConnection, this.usbEndpoint);
63 | if (!usbRequest.queue(buffer, bytes.length)) {
64 | throw new IOException("Error queueing USB request.");
65 | }
66 | this.usbConnection.requestWait();
67 | } finally {
68 | usbRequest.close();
69 | }
70 | }
71 |
72 | @Override
73 | public void flush() throws IOException {
74 |
75 | }
76 |
77 | @Override
78 | public void close() throws IOException {
79 | if (this.usbConnection != null) {
80 | this.usbConnection.close();
81 | this.usbInterface = null;
82 | this.usbEndpoint = null;
83 | this.usbConnection = null;
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/textparser/PrinterTextParserString.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.textparser;
2 |
3 | import java.io.UnsupportedEncodingException;
4 | import java.util.Arrays;
5 |
6 | import com.dantsu.escposprinter.EscPosCharsetEncoding;
7 | import com.dantsu.escposprinter.EscPosPrinter;
8 | import com.dantsu.escposprinter.EscPosPrinterCommands;
9 | import com.dantsu.escposprinter.exceptions.EscPosEncodingException;
10 |
11 | public class PrinterTextParserString implements IPrinterTextParserElement {
12 | private EscPosPrinter printer;
13 | private String text;
14 | private byte[] textSize;
15 | private byte[] textColor;
16 | private byte[] textReverseColor;
17 | private byte[] textBold;
18 | private byte[] textUnderline;
19 | private byte[] textDoubleStrike;
20 |
21 | public PrinterTextParserString(PrinterTextParserColumn printerTextParserColumn, String text, byte[] textSize, byte[] textColor, byte[] textReverseColor, byte[] textBold, byte[] textUnderline, byte[] textDoubleStrike) {
22 | this.printer = printerTextParserColumn.getLine().getTextParser().getPrinter();
23 | this.text = text;
24 | this.textSize = textSize;
25 | this.textColor = textColor;
26 | this.textReverseColor = textReverseColor;
27 | this.textBold = textBold;
28 | this.textUnderline = textUnderline;
29 | this.textDoubleStrike = textDoubleStrike;
30 | }
31 |
32 | @Override
33 | public int length() throws EscPosEncodingException {
34 | EscPosCharsetEncoding charsetEncoding = this.printer.getEncoding();
35 |
36 | int coef = 1;
37 | if(Arrays.equals(this.textSize, EscPosPrinterCommands.TEXT_SIZE_DOUBLE_WIDTH) || Arrays.equals(this.textSize, EscPosPrinterCommands.TEXT_SIZE_BIG))
38 | coef = 2;
39 | else if(Arrays.equals(this.textSize, EscPosPrinterCommands.TEXT_SIZE_BIG_2))
40 | coef = 3;
41 | else if(Arrays.equals(this.textSize, EscPosPrinterCommands.TEXT_SIZE_BIG_3))
42 | coef = 4;
43 | else if(Arrays.equals(this.textSize, EscPosPrinterCommands.TEXT_SIZE_BIG_4))
44 | coef = 5;
45 | else if(Arrays.equals(this.textSize, EscPosPrinterCommands.TEXT_SIZE_BIG_5))
46 | coef = 6;
47 | else if(Arrays.equals(this.textSize, EscPosPrinterCommands.TEXT_SIZE_BIG_6))
48 | coef = 7;
49 |
50 | if (charsetEncoding != null) {
51 | try {
52 | return this.text.getBytes(charsetEncoding.getName()).length * coef;
53 | } catch (UnsupportedEncodingException e) {
54 | throw new EscPosEncodingException(e.getMessage());
55 | }
56 | }
57 |
58 | return this.text.length() * coef;
59 | }
60 |
61 | /**
62 | * Print text
63 | *
64 | * @param printerSocket Instance of EscPosPrinterCommands
65 | * @return this Fluent method
66 | */
67 | @Override
68 | public PrinterTextParserString print(EscPosPrinterCommands printerSocket) throws EscPosEncodingException {
69 | printerSocket.printText(this.text, this.textSize, this.textColor, this.textReverseColor, this.textBold, this.textUnderline, this.textDoubleStrike);
70 | return this;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/connection/tcp/TcpConnection.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.connection.tcp;
2 |
3 | import com.dantsu.escposprinter.connection.DeviceConnection;
4 | import com.dantsu.escposprinter.exceptions.EscPosConnectionException;
5 |
6 | import java.io.IOException;
7 | import java.net.InetAddress;
8 | import java.net.InetSocketAddress;
9 | import java.net.Socket;
10 | import java.net.SocketTimeoutException;
11 |
12 | public class TcpConnection extends DeviceConnection {
13 | private Socket socket = null;
14 | private String address;
15 | private int port;
16 | private int timeout;
17 |
18 | /**
19 | * Create un instance of TcpConnection.
20 | *
21 | * @param address IP address of the device
22 | * @param port Port of the device
23 | */
24 | public TcpConnection(String address, int port) {
25 | this(address, port, 30);
26 | }
27 |
28 | /**
29 | * Create un instance of TcpConnection.
30 | *
31 | * Overload of the above function TcpConnection()
32 | * Include timeout parameter in milliseconds.
33 | *
34 | * @param address IP address of the device
35 | * @param port Port of the device
36 | * @param timeout Timeout in milliseconds to establish a connection
37 | */
38 | public TcpConnection(String address, int port, int timeout) {
39 | super();
40 | this.address = address;
41 | this.port = port;
42 | this.timeout = timeout;
43 | }
44 |
45 | /**
46 | * Check if the TCP device is connected by socket.
47 | *
48 | * @return true if is connected
49 | */
50 | public boolean isConnected() {
51 | return this.socket != null && this.socket.isConnected() && super.isConnected();
52 | }
53 |
54 | /**
55 | * Start socket connection with the TCP device.
56 | */
57 | public TcpConnection connect() throws EscPosConnectionException {
58 | if (this.isConnected()) {
59 | return this;
60 | }
61 | try {
62 | this.socket = new Socket();
63 | this.socket.connect(new InetSocketAddress(InetAddress.getByName(this.address), this.port), this.timeout);
64 | this.outputStream = this.socket.getOutputStream();
65 | this.data = new byte[0];
66 | } catch (IOException e) {
67 | e.printStackTrace();
68 | this.disconnect();
69 | throw new EscPosConnectionException("Unable to connect to TCP device.");
70 | }
71 | return this;
72 | }
73 |
74 | /**
75 | * Close the socket connection with the TCP device.
76 | */
77 | public TcpConnection disconnect() {
78 | this.data = new byte[0];
79 | if (this.outputStream != null) {
80 | try {
81 | this.outputStream.close();
82 | this.outputStream = null;
83 | } catch (IOException e) {
84 | e.printStackTrace();
85 | }
86 | }
87 | if (this.socket != null) {
88 | try {
89 | this.socket.close();
90 | this.socket = null;
91 | } catch (IOException e) {
92 | e.printStackTrace();
93 | }
94 | }
95 | return this;
96 | }
97 |
98 | }
99 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/textparser/PrinterTextParserLine.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.textparser;
2 |
3 | import com.dantsu.escposprinter.exceptions.EscPosBarcodeException;
4 | import com.dantsu.escposprinter.exceptions.EscPosEncodingException;
5 | import com.dantsu.escposprinter.exceptions.EscPosParserException;
6 |
7 | import java.util.ArrayList;
8 | import java.util.regex.Matcher;
9 | import java.util.regex.Pattern;
10 |
11 | public class PrinterTextParserLine {
12 | private PrinterTextParser textParser;
13 | private int nbrColumns;
14 | private int nbrCharColumn;
15 | private int nbrCharForgetted;
16 | private int nbrCharColumnExceeded;
17 | private PrinterTextParserColumn[] columns;
18 |
19 | public PrinterTextParserLine(PrinterTextParser textParser, String textLine) throws EscPosParserException, EscPosBarcodeException, EscPosEncodingException {
20 | this.textParser = textParser;
21 | int nbrCharactersPerLine = this.getTextParser().getPrinter().getPrinterNbrCharactersPerLine();
22 |
23 | Pattern pattern = Pattern.compile(PrinterTextParser.getRegexAlignTags());
24 | Matcher matcher = pattern.matcher(textLine);
25 |
26 | ArrayList columnsList = new ArrayList();
27 | int lastPosition = 0;
28 |
29 | while (matcher.find()) {
30 | int startPosition = matcher.start();
31 | if(startPosition > 0) {
32 | columnsList.add(textLine.substring(lastPosition, startPosition));
33 | }
34 | lastPosition = startPosition;
35 | }
36 | columnsList.add(textLine.substring(lastPosition));
37 |
38 | this.nbrColumns = columnsList.size();
39 | this.nbrCharColumn = (int) Math.floor(((float) nbrCharactersPerLine) / ((float) this.nbrColumns));
40 | this.nbrCharForgetted = nbrCharactersPerLine - (nbrCharColumn * this.nbrColumns);
41 | this.nbrCharColumnExceeded = 0;
42 | this.columns = new PrinterTextParserColumn[this.nbrColumns];
43 |
44 | int i=0;
45 | for (String column : columnsList) {
46 | this.columns[i++] = new PrinterTextParserColumn(this, column);
47 | }
48 | }
49 |
50 |
51 | public PrinterTextParser getTextParser() {
52 | return this.textParser;
53 | }
54 |
55 | public PrinterTextParserColumn[] getColumns() {
56 | return this.columns;
57 | }
58 |
59 | public int getNbrColumns() {
60 | return this.nbrColumns;
61 | }
62 |
63 |
64 | public PrinterTextParserLine setNbrCharColumn(int newValue) {
65 | this.nbrCharColumn = newValue;
66 | return this;
67 | }
68 | public int getNbrCharColumn() {
69 | return this.nbrCharColumn;
70 | }
71 |
72 |
73 | public PrinterTextParserLine setNbrCharForgetted(int newValue) {
74 | this.nbrCharForgetted = newValue;
75 | return this;
76 | }
77 | public int getNbrCharForgetted() {
78 | return this.nbrCharForgetted;
79 | }
80 |
81 |
82 | public PrinterTextParserLine setNbrCharColumnExceeded(int newValue) {
83 | this.nbrCharColumnExceeded = newValue;
84 | return this;
85 | }
86 | public int getNbrCharColumnExceeded() {
87 | return this.nbrCharColumnExceeded;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
17 |
24 |
25 |
31 |
32 |
37 |
38 |
39 |
45 |
46 |
51 |
52 |
57 |
58 |
64 |
65 |
71 |
72 |
77 |
78 |
79 |
85 |
86 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/EscPosPrinterSize.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter;
2 |
3 |
4 | import android.graphics.Bitmap;
5 |
6 | public abstract class EscPosPrinterSize {
7 |
8 | public static final float INCH_TO_MM = 25.4f;
9 |
10 | protected int printerDpi;
11 | protected float printerWidthMM;
12 | protected int printerNbrCharactersPerLine;
13 | protected int printerWidthPx;
14 | protected int printerCharSizeWidthPx;
15 |
16 | protected EscPosPrinterSize(int printerDpi, float printerWidthMM, int printerNbrCharactersPerLine) {
17 | this.printerDpi = printerDpi;
18 | this.printerWidthMM = printerWidthMM;
19 | this.printerNbrCharactersPerLine = printerNbrCharactersPerLine;
20 | int printingWidthPx = this.mmToPx(this.printerWidthMM);
21 | this.printerWidthPx = printingWidthPx + (printingWidthPx % 8);
22 | this.printerCharSizeWidthPx = printingWidthPx / this.printerNbrCharactersPerLine;
23 | }
24 |
25 | /**
26 | * Get the maximum number of characters that can be printed on a line.
27 | *
28 | * @return int
29 | */
30 | public int getPrinterNbrCharactersPerLine() {
31 | return this.printerNbrCharactersPerLine;
32 | }
33 |
34 | /**
35 | * Get the printing width in millimeters
36 | *
37 | * @return float
38 | */
39 | public float getPrinterWidthMM() {
40 | return this.printerWidthMM;
41 | }
42 |
43 | /**
44 | * Get the printer DPI
45 | *
46 | * @return int
47 | */
48 | public int getPrinterDpi() {
49 | return this.printerDpi;
50 | }
51 |
52 | /**
53 | * Get the printing width in dot
54 | *
55 | * @return int
56 | */
57 | public int getPrinterWidthPx() {
58 | return this.printerWidthPx;
59 | }
60 |
61 | /**
62 | * Get the number of dot that a printed character contain
63 | *
64 | * @return int
65 | */
66 | public int getPrinterCharSizeWidthPx() {
67 | return this.printerCharSizeWidthPx;
68 | }
69 |
70 | /**
71 | * Convert from millimeters to dot the mmSize variable.
72 | *
73 | * @param mmSize Distance in millimeters to be converted
74 | * @return int
75 | */
76 | public int mmToPx(float mmSize) {
77 | return Math.round(mmSize * ((float) this.printerDpi) / EscPosPrinterSize.INCH_TO_MM);
78 | }
79 |
80 |
81 | /**
82 | * Convert Bitmap object to ESC/POS image.
83 | *
84 | * @param bitmap Instance of Bitmap
85 | * @param gradient false : Black and white image, true : Grayscale image
86 | * @return Bytes contain the image in ESC/POS command
87 | */
88 | public byte[] bitmapToBytes(Bitmap bitmap, boolean gradient) {
89 | boolean isSizeEdit = false;
90 | int bitmapWidth = bitmap.getWidth(),
91 | bitmapHeight = bitmap.getHeight(),
92 | maxWidth = this.printerWidthPx,
93 | maxHeight = 256;
94 |
95 | if (bitmapWidth > maxWidth) {
96 | bitmapHeight = Math.round(((float) bitmapHeight) * ((float) maxWidth) / ((float) bitmapWidth));
97 | bitmapWidth = maxWidth;
98 | isSizeEdit = true;
99 | }
100 | if (bitmapHeight > maxHeight) {
101 | bitmapWidth = Math.round(((float) bitmapWidth) * ((float) maxHeight) / ((float) bitmapHeight));
102 | bitmapHeight = maxHeight;
103 | isSizeEdit = true;
104 | }
105 |
106 | if (isSizeEdit) {
107 | bitmap = Bitmap.createScaledBitmap(bitmap, bitmapWidth, bitmapHeight, true);
108 | }
109 |
110 | return EscPosPrinterCommands.bitmapToBytes(bitmap, gradient);
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/connection/bluetooth/BluetoothConnection.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.connection.bluetooth;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.bluetooth.BluetoothAdapter;
5 | import android.bluetooth.BluetoothDevice;
6 | import android.bluetooth.BluetoothSocket;
7 | import android.os.ParcelUuid;
8 |
9 | import com.dantsu.escposprinter.connection.DeviceConnection;
10 | import com.dantsu.escposprinter.exceptions.EscPosConnectionException;
11 |
12 | import java.io.IOException;
13 | import java.util.Arrays;
14 | import java.util.UUID;
15 |
16 | public class BluetoothConnection extends DeviceConnection {
17 |
18 | private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
19 |
20 | private BluetoothDevice device;
21 | private BluetoothSocket socket = null;
22 |
23 | /**
24 | * Create un instance of BluetoothConnection.
25 | *
26 | * @param device an instance of BluetoothDevice
27 | */
28 | public BluetoothConnection(BluetoothDevice device) {
29 | super();
30 | this.device = device;
31 | }
32 |
33 | /**
34 | * Get the instance BluetoothDevice connected.
35 | *
36 | * @return an instance of BluetoothDevice
37 | */
38 | public BluetoothDevice getDevice() {
39 | return this.device;
40 | }
41 |
42 | /**
43 | * Check if OutputStream is open.
44 | *
45 | * @return true if is connected
46 | */
47 | @Override
48 | public boolean isConnected() {
49 | return this.socket != null && this.socket.isConnected() && super.isConnected();
50 | }
51 |
52 | /**
53 | * Start socket connection with the bluetooth device.
54 | */
55 | @SuppressLint("MissingPermission")
56 | public BluetoothConnection connect() throws EscPosConnectionException {
57 | if (this.isConnected()) {
58 | return this;
59 | }
60 |
61 | if (this.device == null) {
62 | throw new EscPosConnectionException("Bluetooth device is not connected.");
63 | }
64 |
65 | BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
66 |
67 | UUID uuid = this.getDeviceUUID();
68 |
69 | try {
70 | this.socket = this.device.createRfcommSocketToServiceRecord(uuid);
71 | bluetoothAdapter.cancelDiscovery();
72 | this.socket.connect();
73 | this.outputStream = this.socket.getOutputStream();
74 | this.data = new byte[0];
75 | } catch (IOException e) {
76 | e.printStackTrace();
77 | this.disconnect();
78 | throw new EscPosConnectionException("Unable to connect to bluetooth device.");
79 | }
80 | return this;
81 | }
82 |
83 | /**
84 | * Get bluetooth device UUID
85 | */
86 | protected UUID getDeviceUUID() {
87 | ParcelUuid[] uuids = device.getUuids();
88 | if (uuids != null && uuids.length > 0) {
89 | if (Arrays.asList(uuids).contains(new ParcelUuid(BluetoothConnection.SPP_UUID))) {
90 | return BluetoothConnection.SPP_UUID;
91 | }
92 | return uuids[0].getUuid();
93 | } else {
94 | return BluetoothConnection.SPP_UUID;
95 | }
96 | }
97 |
98 | /**
99 | * Close the socket connection with the bluetooth device.
100 | */
101 | public BluetoothConnection disconnect() {
102 | this.data = new byte[0];
103 | if (this.outputStream != null) {
104 | try {
105 | this.outputStream.close();
106 | } catch (IOException e) {
107 | e.printStackTrace();
108 | }
109 | this.outputStream = null;
110 | }
111 | if (this.socket != null) {
112 | try {
113 | this.socket.close();
114 | } catch (IOException e) {
115 | e.printStackTrace();
116 | }
117 | this.socket = null;
118 | }
119 | return this;
120 | }
121 |
122 | }
123 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/textparser/PrinterTextParserBarcode.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.textparser;
2 |
3 | import java.util.Hashtable;
4 |
5 | import com.dantsu.escposprinter.EscPosPrinter;
6 | import com.dantsu.escposprinter.EscPosPrinterCommands;
7 | import com.dantsu.escposprinter.barcode.Barcode;
8 | import com.dantsu.escposprinter.barcode.Barcode128;
9 | import com.dantsu.escposprinter.barcode.Barcode39;
10 | import com.dantsu.escposprinter.barcode.BarcodeEAN13;
11 | import com.dantsu.escposprinter.barcode.BarcodeEAN8;
12 | import com.dantsu.escposprinter.barcode.BarcodeUPCA;
13 | import com.dantsu.escposprinter.barcode.BarcodeUPCE;
14 | import com.dantsu.escposprinter.exceptions.EscPosBarcodeException;
15 | import com.dantsu.escposprinter.exceptions.EscPosEncodingException;
16 | import com.dantsu.escposprinter.exceptions.EscPosParserException;
17 |
18 | public class PrinterTextParserBarcode implements IPrinterTextParserElement {
19 |
20 | private Barcode barcode;
21 | private int length;
22 | private byte[] align;
23 |
24 | public PrinterTextParserBarcode(PrinterTextParserColumn printerTextParserColumn,
25 | String textAlign,
26 | Hashtable barcodeAttributes,
27 | String code) throws EscPosParserException, EscPosBarcodeException {
28 |
29 | EscPosPrinter printer = printerTextParserColumn.getLine().getTextParser().getPrinter();
30 | code = code.trim();
31 |
32 | this.align = EscPosPrinterCommands.TEXT_ALIGN_LEFT;
33 | switch (textAlign) {
34 | case PrinterTextParser.TAGS_ALIGN_CENTER:
35 | this.align = EscPosPrinterCommands.TEXT_ALIGN_CENTER;
36 | break;
37 | case PrinterTextParser.TAGS_ALIGN_RIGHT:
38 | this.align = EscPosPrinterCommands.TEXT_ALIGN_RIGHT;
39 | break;
40 | }
41 |
42 | this.length = printer.getPrinterNbrCharactersPerLine();
43 | float height = 10f;
44 |
45 | if (barcodeAttributes.containsKey(PrinterTextParser.ATTR_BARCODE_HEIGHT)) {
46 | String barCodeAttribute = barcodeAttributes.get(PrinterTextParser.ATTR_BARCODE_HEIGHT);
47 |
48 | if (barCodeAttribute == null) {
49 | throw new EscPosParserException("Invalid barcode attribute: " + PrinterTextParser.ATTR_BARCODE_HEIGHT);
50 | }
51 |
52 | try {
53 | height = Float.parseFloat(barCodeAttribute);
54 | } catch (NumberFormatException nfe) {
55 | throw new EscPosParserException("Invalid barcode " + PrinterTextParser.ATTR_BARCODE_HEIGHT + " value");
56 | }
57 | }
58 |
59 | float width = 0f;
60 | if (barcodeAttributes.containsKey(PrinterTextParser.ATTR_BARCODE_WIDTH)) {
61 | String barCodeAttribute = barcodeAttributes.get(PrinterTextParser.ATTR_BARCODE_WIDTH);
62 |
63 | if (barCodeAttribute == null) {
64 | throw new EscPosParserException("Invalid barcode attribute: " + PrinterTextParser.ATTR_BARCODE_WIDTH);
65 | }
66 |
67 | try {
68 | width = Float.parseFloat(barCodeAttribute);
69 | } catch (NumberFormatException nfe) {
70 | throw new EscPosParserException("Invalid barcode " + PrinterTextParser.ATTR_BARCODE_WIDTH + " value");
71 | }
72 | }
73 |
74 | int textPosition = EscPosPrinterCommands.BARCODE_TEXT_POSITION_BELOW;
75 | if (barcodeAttributes.containsKey(PrinterTextParser.ATTR_BARCODE_TEXT_POSITION)) {
76 | String barCodeAttribute = barcodeAttributes.get(PrinterTextParser.ATTR_BARCODE_TEXT_POSITION);
77 |
78 | if (barCodeAttribute == null) {
79 | throw new EscPosParserException("Invalid barcode attribute: " + PrinterTextParser.ATTR_BARCODE_TEXT_POSITION);
80 | }
81 |
82 | switch (barCodeAttribute) {
83 | case PrinterTextParser.ATTR_BARCODE_TEXT_POSITION_NONE:
84 | textPosition = EscPosPrinterCommands.BARCODE_TEXT_POSITION_NONE;
85 | break;
86 | case PrinterTextParser.ATTR_BARCODE_TEXT_POSITION_ABOVE:
87 | textPosition = EscPosPrinterCommands.BARCODE_TEXT_POSITION_ABOVE;
88 | break;
89 | }
90 | }
91 |
92 | String barcodeType = PrinterTextParser.ATTR_BARCODE_TYPE_EAN13;
93 |
94 | if (barcodeAttributes.containsKey(PrinterTextParser.ATTR_BARCODE_TYPE)) {
95 | barcodeType = barcodeAttributes.get(PrinterTextParser.ATTR_BARCODE_TYPE);
96 |
97 | if (barcodeType == null) {
98 | throw new EscPosParserException("Invalid barcode attribute : " + PrinterTextParser.ATTR_BARCODE_TYPE);
99 | }
100 | }
101 |
102 | switch (barcodeType) {
103 | case PrinterTextParser.ATTR_BARCODE_TYPE_EAN8:
104 | this.barcode = new BarcodeEAN8(printer, code, width, height, textPosition);
105 | break;
106 | case PrinterTextParser.ATTR_BARCODE_TYPE_EAN13:
107 | this.barcode = new BarcodeEAN13(printer, code, width, height, textPosition);
108 | break;
109 | case PrinterTextParser.ATTR_BARCODE_TYPE_UPCA:
110 | this.barcode = new BarcodeUPCA(printer, code, width, height, textPosition);
111 | break;
112 | case PrinterTextParser.ATTR_BARCODE_TYPE_UPCE:
113 | this.barcode = new BarcodeUPCE(printer, code, width, height, textPosition);
114 | break;
115 | case PrinterTextParser.ATTR_BARCODE_TYPE_128:
116 | this.barcode = new Barcode128(printer, code, width, height, textPosition);
117 | break;
118 | case PrinterTextParser.ATTR_BARCODE_TYPE_39:
119 | this.barcode = new Barcode39(printer, code, width, height, textPosition);
120 | break;
121 | default:
122 | throw new EscPosParserException("Invalid barcode attribute : " + PrinterTextParser.ATTR_BARCODE_TYPE);
123 | }
124 | }
125 |
126 | /**
127 | * Get the barcode width in char length.
128 | *
129 | * @return int
130 | */
131 | @Override
132 | public int length() throws EscPosEncodingException {
133 | return this.length;
134 | }
135 |
136 | /**
137 | * Print barcode
138 | *
139 | * @param printerSocket Instance of EscPosPrinterCommands
140 | * @return this Fluent method
141 | */
142 | @Override
143 | public PrinterTextParserBarcode print(EscPosPrinterCommands printerSocket) {
144 | printerSocket
145 | .setAlign(this.align)
146 | .printBarcode(this.barcode);
147 | return this;
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/textparser/PrinterTextParserImg.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.textparser;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.drawable.BitmapDrawable;
5 | import android.graphics.drawable.Drawable;
6 |
7 | import com.dantsu.escposprinter.EscPosPrinter;
8 | import com.dantsu.escposprinter.EscPosPrinterCommands;
9 | import com.dantsu.escposprinter.EscPosPrinterSize;
10 | import com.dantsu.escposprinter.exceptions.EscPosConnectionException;
11 | import com.dantsu.escposprinter.exceptions.EscPosEncodingException;
12 |
13 |
14 | public class PrinterTextParserImg implements IPrinterTextParserElement {
15 |
16 | /**
17 | * Convert Drawable instance to a hexadecimal string of the image data.
18 | *
19 | * @param printerSize A EscPosPrinterSize instance that will print the image.
20 | * @param drawable Drawable instance to be converted.
21 | * @return A hexadecimal string of the image data. Empty string if Drawable cannot be cast to BitmapDrawable.
22 | */
23 | public static String bitmapToHexadecimalString(EscPosPrinterSize printerSize, Drawable drawable) {
24 | if (drawable instanceof BitmapDrawable) {
25 | return PrinterTextParserImg.bitmapToHexadecimalString(printerSize, (BitmapDrawable) drawable);
26 | }
27 | return "";
28 | }
29 | /**
30 | * Convert Drawable instance to a hexadecimal string of the image data.
31 | *
32 | * @param printerSize A EscPosPrinterSize instance that will print the image.
33 | * @param drawable Drawable instance to be converted.
34 | * @param gradient false : Black and white image, true : Grayscale image
35 | * @return A hexadecimal string of the image data. Empty string if Drawable cannot be cast to BitmapDrawable.
36 | */
37 | public static String bitmapToHexadecimalString(EscPosPrinterSize printerSize, Drawable drawable, boolean gradient) {
38 | if (drawable instanceof BitmapDrawable) {
39 | return PrinterTextParserImg.bitmapToHexadecimalString(printerSize, (BitmapDrawable) drawable, gradient);
40 | }
41 | return "";
42 | }
43 |
44 | /**
45 | * Convert BitmapDrawable instance to a hexadecimal string of the image data.
46 | *
47 | * @param printerSize A EscPosPrinterSize instance that will print the image.
48 | * @param bitmapDrawable BitmapDrawable instance to be converted.
49 | * @return A hexadecimal string of the image data.
50 | */
51 | public static String bitmapToHexadecimalString(EscPosPrinterSize printerSize, BitmapDrawable bitmapDrawable) {
52 | return PrinterTextParserImg.bitmapToHexadecimalString(printerSize, bitmapDrawable.getBitmap());
53 | }
54 |
55 | /**
56 | * Convert BitmapDrawable instance to a hexadecimal string of the image data.
57 | *
58 | * @param printerSize A EscPosPrinterSize instance that will print the image.
59 | * @param bitmapDrawable BitmapDrawable instance to be converted.
60 | * @param gradient false : Black and white image, true : Grayscale image
61 | * @return A hexadecimal string of the image data.
62 | */
63 | public static String bitmapToHexadecimalString(EscPosPrinterSize printerSize, BitmapDrawable bitmapDrawable, boolean gradient) {
64 | return PrinterTextParserImg.bitmapToHexadecimalString(printerSize, bitmapDrawable.getBitmap(), gradient);
65 | }
66 |
67 | /**
68 | * Convert Bitmap instance to a hexadecimal string of the image data.
69 | *
70 | * @param printerSize A EscPosPrinterSize instance that will print the image.
71 | * @param bitmap Bitmap instance to be converted.
72 | * @return A hexadecimal string of the image data.
73 | */
74 | public static String bitmapToHexadecimalString(EscPosPrinterSize printerSize, Bitmap bitmap) {
75 | return PrinterTextParserImg.bitmapToHexadecimalString(printerSize, bitmap, true);
76 | }
77 |
78 | /**
79 | * Convert Bitmap instance to a hexadecimal string of the image data.
80 | *
81 | * @param printerSize A EscPosPrinterSize instance that will print the image.
82 | * @param bitmap Bitmap instance to be converted.
83 | * @param gradient false : Black and white image, true : Grayscale image
84 | * @return A hexadecimal string of the image data.
85 | */
86 | public static String bitmapToHexadecimalString(EscPosPrinterSize printerSize, Bitmap bitmap, boolean gradient) {
87 | return PrinterTextParserImg.bytesToHexadecimalString(printerSize.bitmapToBytes(bitmap, gradient));
88 | }
89 |
90 | /**
91 | * Convert byte array to a hexadecimal string of the image data.
92 | *
93 | * @param bytes Bytes contain the image in ESC/POS command.
94 | * @return A hexadecimal string of the image data.
95 | */
96 | public static String bytesToHexadecimalString(byte[] bytes) {
97 | StringBuilder imageHexString = new StringBuilder();
98 | for (byte aByte : bytes) {
99 | String hexString = Integer.toHexString(aByte & 0xFF);
100 | if (hexString.length() == 1) {
101 | imageHexString.append("0");
102 | }
103 | imageHexString.append(hexString);
104 | }
105 | return imageHexString.toString();
106 | }
107 |
108 | /**
109 | * Convert hexadecimal string of the image data to bytes ESC/POS command.
110 | *
111 | * @param hexString Hexadecimal string of the image data.
112 | * @return Bytes contain the image in ESC/POS command.
113 | */
114 | public static byte[] hexadecimalStringToBytes(String hexString) throws NumberFormatException {
115 | byte[] bytes = new byte[hexString.length() / 2];
116 | for (int i = 0; i < bytes.length; i++) {
117 | int pos = i * 2;
118 | bytes[i] = (byte) Integer.parseInt(hexString.substring(pos, pos + 2), 16);
119 | }
120 | return bytes;
121 | }
122 |
123 |
124 | private int length;
125 | private byte[] image;
126 |
127 | /**
128 | * Create new instance of PrinterTextParserImg.
129 | *
130 | * @param printerTextParserColumn Parent PrinterTextParserColumn instance.
131 | * @param textAlign Set the image alignment. Use PrinterTextParser.TAGS_ALIGN_... constants.
132 | * @param hexadecimalString Hexadecimal string of the image data.
133 | */
134 | public PrinterTextParserImg(PrinterTextParserColumn printerTextParserColumn, String textAlign, String hexadecimalString) {
135 | this(printerTextParserColumn, textAlign, PrinterTextParserImg.hexadecimalStringToBytes(hexadecimalString));
136 | }
137 |
138 | /**
139 | * Create new instance of PrinterTextParserImg.
140 | *
141 | * @param printerTextParserColumn Parent PrinterTextParserColumn instance.
142 | * @param textAlign Set the image alignment. Use PrinterTextParser.TAGS_ALIGN_... constants.
143 | * @param image Bytes contain the image in ESC/POS command.
144 | */
145 | public PrinterTextParserImg(PrinterTextParserColumn printerTextParserColumn, String textAlign, byte[] image) {
146 | EscPosPrinter printer = printerTextParserColumn.getLine().getTextParser().getPrinter();
147 |
148 | int
149 | byteWidth = ((int) image[4] & 0xFF) + ((int) image[5] & 0xFF) * 256,
150 | width = byteWidth * 8,
151 | height = ((int) image[6] & 0xFF) + ((int) image[7] & 0xFF) * 256,
152 | nbrByteDiff = (int) Math.floor(((float) (printer.getPrinterWidthPx() - width)) / 8f),
153 | nbrWhiteByteToInsert = 0;
154 |
155 | switch (textAlign) {
156 | case PrinterTextParser.TAGS_ALIGN_CENTER:
157 | nbrWhiteByteToInsert = Math.round(((float) nbrByteDiff) / 2f);
158 | break;
159 | case PrinterTextParser.TAGS_ALIGN_RIGHT:
160 | nbrWhiteByteToInsert = nbrByteDiff;
161 | break;
162 | }
163 |
164 | if (nbrWhiteByteToInsert > 0) {
165 | int newByteWidth = byteWidth + nbrWhiteByteToInsert;
166 | byte[] newImage = EscPosPrinterCommands.initGSv0Command(newByteWidth, height);
167 | for (int i = 0; i < height; i++) {
168 | System.arraycopy(image, (byteWidth * i + 8), newImage, (newByteWidth * i + nbrWhiteByteToInsert + 8), byteWidth);
169 | }
170 | image = newImage;
171 | }
172 |
173 | this.length = (int) Math.ceil(((float) byteWidth * 8) / ((float) printer.getPrinterCharSizeWidthPx()));
174 | this.image = image;
175 | }
176 |
177 | /**
178 | * Get the image width in char length.
179 | *
180 | * @return int
181 | */
182 | @Override
183 | public int length() throws EscPosEncodingException {
184 | return this.length;
185 | }
186 |
187 | /**
188 | * Print image
189 | *
190 | * @param printerSocket Instance of EscPosPrinterCommands
191 | * @return this Fluent method
192 | */
193 | @Override
194 | public PrinterTextParserImg print(EscPosPrinterCommands printerSocket) throws EscPosConnectionException {
195 | printerSocket.printImage(this.image);
196 | return this;
197 | }
198 | }
199 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dantsu/thermalprinter/async/AsyncEscPosPrint.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.thermalprinter.async;
2 |
3 | import android.app.AlertDialog;
4 | import android.app.ProgressDialog;
5 | import android.content.Context;
6 | import android.os.AsyncTask;
7 |
8 | import com.dantsu.escposprinter.EscPosCharsetEncoding;
9 | import com.dantsu.escposprinter.EscPosPrinter;
10 | import com.dantsu.escposprinter.connection.DeviceConnection;
11 | import com.dantsu.escposprinter.exceptions.EscPosBarcodeException;
12 | import com.dantsu.escposprinter.exceptions.EscPosConnectionException;
13 | import com.dantsu.escposprinter.exceptions.EscPosEncodingException;
14 | import com.dantsu.escposprinter.exceptions.EscPosParserException;
15 |
16 | import java.lang.ref.WeakReference;
17 |
18 | public abstract class AsyncEscPosPrint extends AsyncTask {
19 | public final static int FINISH_SUCCESS = 1;
20 | public final static int FINISH_NO_PRINTER = 2;
21 | public final static int FINISH_PRINTER_DISCONNECTED = 3;
22 | public final static int FINISH_PARSER_ERROR = 4;
23 | public final static int FINISH_ENCODING_ERROR = 5;
24 | public final static int FINISH_BARCODE_ERROR = 6;
25 |
26 | protected final static int PROGRESS_CONNECTING = 1;
27 | protected final static int PROGRESS_CONNECTED = 2;
28 | protected final static int PROGRESS_PRINTING = 3;
29 | protected final static int PROGRESS_PRINTED = 4;
30 |
31 | protected ProgressDialog dialog;
32 | protected WeakReference weakContext;
33 | protected OnPrintFinished onPrintFinished;
34 |
35 |
36 | public AsyncEscPosPrint(Context context) {
37 | this(context, null);
38 | }
39 |
40 | public AsyncEscPosPrint(Context context, OnPrintFinished onPrintFinished) {
41 | this.weakContext = new WeakReference<>(context);
42 | this.onPrintFinished = onPrintFinished;
43 | }
44 |
45 | protected PrinterStatus doInBackground(AsyncEscPosPrinter... printersData) {
46 | if (printersData.length == 0) {
47 | return new PrinterStatus(null, AsyncEscPosPrint.FINISH_NO_PRINTER);
48 | }
49 |
50 | this.publishProgress(AsyncEscPosPrint.PROGRESS_CONNECTING);
51 |
52 | AsyncEscPosPrinter printerData = printersData[0];
53 |
54 | try {
55 | DeviceConnection deviceConnection = printerData.getPrinterConnection();
56 |
57 | if(deviceConnection == null) {
58 | return new PrinterStatus(null, AsyncEscPosPrint.FINISH_NO_PRINTER);
59 | }
60 |
61 | EscPosPrinter printer = new EscPosPrinter(
62 | deviceConnection,
63 | printerData.getPrinterDpi(),
64 | printerData.getPrinterWidthMM(),
65 | printerData.getPrinterNbrCharactersPerLine(),
66 | new EscPosCharsetEncoding("windows-1252", 16)
67 | );
68 |
69 | // printer.useEscAsteriskCommand(true);
70 |
71 | this.publishProgress(AsyncEscPosPrint.PROGRESS_PRINTING);
72 |
73 | String[] textsToPrint = printerData.getTextsToPrint();
74 |
75 | for(String textToPrint : textsToPrint) {
76 | printer.printFormattedTextAndCut(textToPrint);
77 | Thread.sleep(500);
78 | }
79 |
80 | this.publishProgress(AsyncEscPosPrint.PROGRESS_PRINTED);
81 |
82 | } catch (EscPosConnectionException e) {
83 | e.printStackTrace();
84 | return new PrinterStatus(printerData, AsyncEscPosPrint.FINISH_PRINTER_DISCONNECTED);
85 | } catch (EscPosParserException e) {
86 | e.printStackTrace();
87 | return new PrinterStatus(printerData, AsyncEscPosPrint.FINISH_PARSER_ERROR);
88 | } catch (EscPosEncodingException e) {
89 | e.printStackTrace();
90 | return new PrinterStatus(printerData, AsyncEscPosPrint.FINISH_ENCODING_ERROR);
91 | } catch (EscPosBarcodeException e) {
92 | e.printStackTrace();
93 | return new PrinterStatus(printerData, AsyncEscPosPrint.FINISH_BARCODE_ERROR);
94 | } catch (InterruptedException e) {
95 | e.printStackTrace();
96 | }
97 | return new PrinterStatus(printerData, AsyncEscPosPrint.FINISH_SUCCESS);
98 | }
99 |
100 | protected void onPreExecute() {
101 | if (this.dialog == null) {
102 | Context context = weakContext.get();
103 |
104 | if (context == null) {
105 | return;
106 | }
107 |
108 | this.dialog = new ProgressDialog(context);
109 | this.dialog.setTitle("Printing in progress...");
110 | this.dialog.setMessage("...");
111 | this.dialog.setProgressNumberFormat("%1d / %2d");
112 | this.dialog.setCancelable(false);
113 | this.dialog.setIndeterminate(false);
114 | this.dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
115 | this.dialog.show();
116 | }
117 | }
118 |
119 | protected void onProgressUpdate(Integer... progress) {
120 | switch (progress[0]) {
121 | case AsyncEscPosPrint.PROGRESS_CONNECTING:
122 | this.dialog.setMessage("Connecting printer...");
123 | break;
124 | case AsyncEscPosPrint.PROGRESS_CONNECTED:
125 | this.dialog.setMessage("Printer is connected...");
126 | break;
127 | case AsyncEscPosPrint.PROGRESS_PRINTING:
128 | this.dialog.setMessage("Printer is printing...");
129 | break;
130 | case AsyncEscPosPrint.PROGRESS_PRINTED:
131 | this.dialog.setMessage("Printer has finished...");
132 | break;
133 | }
134 | this.dialog.setProgress(progress[0]);
135 | this.dialog.setMax(4);
136 | }
137 |
138 | protected void onPostExecute(PrinterStatus result) {
139 | this.dialog.dismiss();
140 | this.dialog = null;
141 |
142 | Context context = weakContext.get();
143 |
144 | if (context == null) {
145 | return;
146 | }
147 |
148 | switch (result.getPrinterStatus()) {
149 | case AsyncEscPosPrint.FINISH_SUCCESS:
150 | new AlertDialog.Builder(context)
151 | .setTitle("Success")
152 | .setMessage("Congratulation ! The texts are printed !")
153 | .show();
154 | break;
155 | case AsyncEscPosPrint.FINISH_NO_PRINTER:
156 | new AlertDialog.Builder(context)
157 | .setTitle("No printer")
158 | .setMessage("The application can't find any printer connected.")
159 | .show();
160 | break;
161 | case AsyncEscPosPrint.FINISH_PRINTER_DISCONNECTED:
162 | new AlertDialog.Builder(context)
163 | .setTitle("Broken connection")
164 | .setMessage("Unable to connect the printer.")
165 | .show();
166 | break;
167 | case AsyncEscPosPrint.FINISH_PARSER_ERROR:
168 | new AlertDialog.Builder(context)
169 | .setTitle("Invalid formatted text")
170 | .setMessage("It seems to be an invalid syntax problem.")
171 | .show();
172 | break;
173 | case AsyncEscPosPrint.FINISH_ENCODING_ERROR:
174 | new AlertDialog.Builder(context)
175 | .setTitle("Bad selected encoding")
176 | .setMessage("The selected encoding character returning an error.")
177 | .show();
178 | break;
179 | case AsyncEscPosPrint.FINISH_BARCODE_ERROR:
180 | new AlertDialog.Builder(context)
181 | .setTitle("Invalid barcode")
182 | .setMessage("Data send to be converted to barcode or QR code seems to be invalid.")
183 | .show();
184 | break;
185 | }
186 | if(this.onPrintFinished != null) {
187 | if (result.getPrinterStatus() == AsyncEscPosPrint.FINISH_SUCCESS) {
188 | this.onPrintFinished.onSuccess(result.getAsyncEscPosPrinter());
189 | } else {
190 | this.onPrintFinished.onError(result.getAsyncEscPosPrinter(), result.getPrinterStatus());
191 | }
192 | }
193 | }
194 |
195 | public static class PrinterStatus {
196 | private AsyncEscPosPrinter asyncEscPosPrinter;
197 | private int printerStatus;
198 |
199 | public PrinterStatus (AsyncEscPosPrinter asyncEscPosPrinter, int printerStatus) {
200 | this.asyncEscPosPrinter = asyncEscPosPrinter;
201 | this.printerStatus = printerStatus;
202 | }
203 |
204 | public AsyncEscPosPrinter getAsyncEscPosPrinter() {
205 | return asyncEscPosPrinter;
206 | }
207 |
208 | public int getPrinterStatus() {
209 | return printerStatus;
210 | }
211 | }
212 |
213 | public static abstract class OnPrintFinished {
214 | public abstract void onError(AsyncEscPosPrinter asyncEscPosPrinter, int codeException);
215 | public abstract void onSuccess(AsyncEscPosPrinter asyncEscPosPrinter);
216 | }
217 | }
218 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/textparser/PrinterTextParser.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.textparser;
2 |
3 | import java.util.Arrays;
4 |
5 | import com.dantsu.escposprinter.EscPosPrinter;
6 | import com.dantsu.escposprinter.EscPosPrinterCommands;
7 | import com.dantsu.escposprinter.exceptions.EscPosBarcodeException;
8 | import com.dantsu.escposprinter.exceptions.EscPosEncodingException;
9 | import com.dantsu.escposprinter.exceptions.EscPosParserException;
10 |
11 | public class PrinterTextParser {
12 |
13 | public static final String TAGS_ALIGN_LEFT = "L";
14 | public static final String TAGS_ALIGN_CENTER = "C";
15 | public static final String TAGS_ALIGN_RIGHT = "R";
16 | public static final String[] TAGS_ALIGN = {PrinterTextParser.TAGS_ALIGN_LEFT, PrinterTextParser.TAGS_ALIGN_CENTER, PrinterTextParser.TAGS_ALIGN_RIGHT};
17 |
18 | public static final String TAGS_IMAGE = "img";
19 | public static final String TAGS_BARCODE = "barcode";
20 | public static final String TAGS_QRCODE = "qrcode";
21 |
22 | public static final String ATTR_BARCODE_WIDTH = "width";
23 | public static final String ATTR_BARCODE_HEIGHT = "height";
24 | public static final String ATTR_BARCODE_TYPE = "type";
25 | public static final String ATTR_BARCODE_TYPE_EAN8 = "ean8";
26 | public static final String ATTR_BARCODE_TYPE_EAN13 = "ean13";
27 | public static final String ATTR_BARCODE_TYPE_UPCA = "upca";
28 | public static final String ATTR_BARCODE_TYPE_UPCE = "upce";
29 | public static final String ATTR_BARCODE_TYPE_128 = "128";
30 | public static final String ATTR_BARCODE_TYPE_39 = "39";
31 | public static final String ATTR_BARCODE_TEXT_POSITION = "text";
32 | public static final String ATTR_BARCODE_TEXT_POSITION_NONE = "none";
33 | public static final String ATTR_BARCODE_TEXT_POSITION_ABOVE = "above";
34 | public static final String ATTR_BARCODE_TEXT_POSITION_BELOW = "below";
35 |
36 | public static final String TAGS_FORMAT_TEXT_FONT = "font";
37 | public static final String TAGS_FORMAT_TEXT_BOLD = "b";
38 | public static final String TAGS_FORMAT_TEXT_UNDERLINE = "u";
39 | public static final String[] TAGS_FORMAT_TEXT = {PrinterTextParser.TAGS_FORMAT_TEXT_FONT, PrinterTextParser.TAGS_FORMAT_TEXT_BOLD, PrinterTextParser.TAGS_FORMAT_TEXT_UNDERLINE};
40 |
41 | public static final String ATTR_FORMAT_TEXT_UNDERLINE_TYPE = "type";
42 | public static final String ATTR_FORMAT_TEXT_UNDERLINE_TYPE_NORMAL = "normal";
43 | public static final String ATTR_FORMAT_TEXT_UNDERLINE_TYPE_DOUBLE = "double";
44 |
45 | public static final String ATTR_FORMAT_TEXT_FONT_SIZE = "size";
46 | public static final String ATTR_FORMAT_TEXT_FONT_SIZE_BIG = "big";
47 | public static final String ATTR_FORMAT_TEXT_FONT_SIZE_BIG_2 = "big-2";
48 | public static final String ATTR_FORMAT_TEXT_FONT_SIZE_BIG_3 = "big-3";
49 | public static final String ATTR_FORMAT_TEXT_FONT_SIZE_BIG_4 = "big-4";
50 | public static final String ATTR_FORMAT_TEXT_FONT_SIZE_BIG_5 = "big-5";
51 | public static final String ATTR_FORMAT_TEXT_FONT_SIZE_BIG_6 = "big-6";
52 | public static final String ATTR_FORMAT_TEXT_FONT_SIZE_TALL = "tall";
53 | public static final String ATTR_FORMAT_TEXT_FONT_SIZE_WIDE = "wide";
54 | public static final String ATTR_FORMAT_TEXT_FONT_SIZE_NORMAL = "normal";
55 |
56 | public static final String ATTR_FORMAT_TEXT_FONT_COLOR = "color";
57 | public static final String ATTR_FORMAT_TEXT_FONT_COLOR_BLACK = "black";
58 | public static final String ATTR_FORMAT_TEXT_FONT_COLOR_BG_BLACK = "bg-black";
59 | public static final String ATTR_FORMAT_TEXT_FONT_COLOR_RED = "red";
60 | public static final String ATTR_FORMAT_TEXT_FONT_COLOR_BG_RED = "bg-red";
61 |
62 | public static final String ATTR_QRCODE_SIZE = "size";
63 |
64 | private static String regexAlignTags;
65 | public static String getRegexAlignTags() {
66 | if(PrinterTextParser.regexAlignTags == null) {
67 | StringBuilder regexAlignTags = new StringBuilder();
68 | for (int i = 0; i < PrinterTextParser.TAGS_ALIGN.length; i++) {
69 | regexAlignTags.append("|\\[").append(PrinterTextParser.TAGS_ALIGN[i]).append("\\]");
70 | }
71 | PrinterTextParser.regexAlignTags = regexAlignTags.toString().substring(1);
72 | }
73 | return PrinterTextParser.regexAlignTags;
74 | }
75 |
76 | public static boolean isTagTextFormat(String tagName) {
77 | if (tagName.substring(0, 1).equals("/")) {
78 | tagName = tagName.substring(1);
79 | }
80 |
81 | for (String tag : PrinterTextParser.TAGS_FORMAT_TEXT) {
82 | if (tag.equals(tagName)) {
83 | return true;
84 | }
85 | }
86 | return false;
87 | }
88 |
89 | public static byte[][] arrayByteDropLast(byte[][] arr) {
90 | if (arr.length == 0) {
91 | return arr;
92 | }
93 |
94 | byte[][] newArr = new byte[arr.length - 1][];
95 | System.arraycopy(arr, 0, newArr, 0, newArr.length);
96 |
97 | return newArr;
98 | }
99 |
100 | public static byte[][] arrayBytePush(byte[][] arr, byte[] add) {
101 | byte[][] newArr = new byte[arr.length + 1][];
102 | System.arraycopy(arr, 0, newArr, 0, arr.length);
103 | newArr[arr.length] = add;
104 | return newArr;
105 | }
106 |
107 |
108 |
109 |
110 | private EscPosPrinter printer;
111 | private byte[][] textSize = {EscPosPrinterCommands.TEXT_SIZE_NORMAL};
112 | private byte[][] textColor = {EscPosPrinterCommands.TEXT_COLOR_BLACK};
113 | private byte[][] textReverseColor = {EscPosPrinterCommands.TEXT_COLOR_REVERSE_OFF};
114 | private byte[][] textBold = {EscPosPrinterCommands.TEXT_WEIGHT_NORMAL};
115 | private byte[][] textUnderline = {EscPosPrinterCommands.TEXT_UNDERLINE_OFF};
116 | private byte[][] textDoubleStrike = {EscPosPrinterCommands.TEXT_DOUBLE_STRIKE_OFF};
117 | private String text = "";
118 |
119 | public PrinterTextParser(EscPosPrinter printer) {
120 | this.printer = printer;
121 | }
122 |
123 | public EscPosPrinter getPrinter() {
124 | return printer;
125 | }
126 |
127 | public PrinterTextParser setFormattedText(String text) {
128 | this.text = text;
129 | return this;
130 | }
131 |
132 | public byte[] getLastTextSize() {
133 | return this.textSize[this.textSize.length - 1];
134 | }
135 |
136 | public PrinterTextParser addTextSize(byte[] newTextSize) {
137 | this.textSize = PrinterTextParser.arrayBytePush(this.textSize, newTextSize);
138 | return this;
139 | }
140 |
141 | public PrinterTextParser dropLastTextSize() {
142 | if (this.textSize.length > 1) {
143 | this.textSize = PrinterTextParser.arrayByteDropLast(this.textSize);
144 | }
145 | return this;
146 | }
147 |
148 | public byte[] getLastTextColor() {
149 | return this.textColor[this.textColor.length - 1];
150 | }
151 |
152 | public PrinterTextParser addTextColor(byte[] newTextColor) {
153 | this.textColor = PrinterTextParser.arrayBytePush(this.textColor, newTextColor);
154 | return this;
155 | }
156 |
157 | public PrinterTextParser dropLastTextColor() {
158 | if (this.textColor.length > 1) {
159 | this.textColor = PrinterTextParser.arrayByteDropLast(this.textColor);
160 | }
161 | return this;
162 | }
163 |
164 | public byte[] getLastTextReverseColor() {
165 | return this.textReverseColor[this.textReverseColor.length - 1];
166 | }
167 |
168 | public PrinterTextParser addTextReverseColor(byte[] newTextReverseColor) {
169 | this.textReverseColor = PrinterTextParser.arrayBytePush(this.textReverseColor, newTextReverseColor);
170 | return this;
171 | }
172 |
173 | public PrinterTextParser dropLastTextReverseColor() {
174 | if (this.textReverseColor.length > 1) {
175 | this.textReverseColor = PrinterTextParser.arrayByteDropLast(this.textReverseColor);
176 | }
177 | return this;
178 | }
179 |
180 | public byte[] getLastTextBold() {
181 | return this.textBold[this.textBold.length - 1];
182 | }
183 |
184 | public PrinterTextParser addTextBold(byte[] newTextBold) {
185 | this.textBold = PrinterTextParser.arrayBytePush(this.textBold, newTextBold);
186 | return this;
187 | }
188 |
189 | public PrinterTextParser dropTextBold() {
190 | if (this.textBold.length > 1) {
191 | this.textBold = PrinterTextParser.arrayByteDropLast(this.textBold);
192 | }
193 | return this;
194 | }
195 |
196 | public byte[] getLastTextUnderline() {
197 | return this.textUnderline[this.textUnderline.length - 1];
198 | }
199 |
200 | public PrinterTextParser addTextUnderline(byte[] newTextUnderline) {
201 | this.textUnderline = PrinterTextParser.arrayBytePush(this.textUnderline, newTextUnderline);
202 | return this;
203 | }
204 |
205 | public PrinterTextParser dropLastTextUnderline() {
206 | if (this.textUnderline.length > 1) {
207 | this.textUnderline = PrinterTextParser.arrayByteDropLast(this.textUnderline);
208 | }
209 | return this;
210 | }
211 |
212 | public byte[] getLastTextDoubleStrike() {
213 | return this.textDoubleStrike[this.textDoubleStrike.length - 1];
214 | }
215 |
216 | public PrinterTextParser addTextDoubleStrike(byte[] newTextDoubleStrike) {
217 | this.textDoubleStrike = PrinterTextParser.arrayBytePush(this.textDoubleStrike, newTextDoubleStrike);
218 | return this;
219 | }
220 |
221 | public PrinterTextParser dropLastTextDoubleStrike() {
222 | if (this.textDoubleStrike.length > 1) {
223 | this.textDoubleStrike = PrinterTextParser.arrayByteDropLast(this.textDoubleStrike);
224 | }
225 | return this;
226 | }
227 |
228 | public PrinterTextParserLine[] parse() throws EscPosParserException, EscPosBarcodeException, EscPosEncodingException {
229 | String[] stringLines = this.text.split("\n|\r\n");
230 | PrinterTextParserLine[] lines = new PrinterTextParserLine[stringLines.length];
231 | int i = 0;
232 | for (String line : stringLines) {
233 | lines[i++] = new PrinterTextParserLine(this, line);
234 | }
235 | return lines;
236 | }
237 | }
238 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/EscPosPrinter.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter;
2 |
3 | import com.dantsu.escposprinter.connection.DeviceConnection;
4 | import com.dantsu.escposprinter.exceptions.EscPosBarcodeException;
5 | import com.dantsu.escposprinter.exceptions.EscPosConnectionException;
6 | import com.dantsu.escposprinter.exceptions.EscPosEncodingException;
7 | import com.dantsu.escposprinter.exceptions.EscPosParserException;
8 | import com.dantsu.escposprinter.textparser.PrinterTextParser;
9 | import com.dantsu.escposprinter.textparser.PrinterTextParserColumn;
10 | import com.dantsu.escposprinter.textparser.IPrinterTextParserElement;
11 | import com.dantsu.escposprinter.textparser.PrinterTextParserLine;
12 | import com.dantsu.escposprinter.textparser.PrinterTextParserString;
13 |
14 | public class EscPosPrinter extends EscPosPrinterSize {
15 |
16 | private EscPosPrinterCommands printer = null;
17 |
18 | /**
19 | * Create new instance of EscPosPrinter.
20 | *
21 | * @param printerConnection Instance of class which implement DeviceConnection
22 | * @param printerDpi DPI of the connected printer
23 | * @param printerWidthMM Printing width in millimeters
24 | * @param printerNbrCharactersPerLine The maximum number of characters that can be printed on a line.
25 | */
26 | public EscPosPrinter(DeviceConnection printerConnection, int printerDpi, float printerWidthMM, int printerNbrCharactersPerLine) throws EscPosConnectionException {
27 | this(printerConnection != null ? new EscPosPrinterCommands(printerConnection) : null, printerDpi, printerWidthMM, printerNbrCharactersPerLine);
28 | }
29 |
30 | /**
31 | * Create new instance of EscPosPrinter.
32 | *
33 | * @param printerConnection Instance of class which implement DeviceConnection
34 | * @param printerDpi DPI of the connected printer
35 | * @param printerWidthMM Printing width in millimeters
36 | * @param printerNbrCharactersPerLine The maximum number of characters that can be printed on a line.
37 | * @param charsetEncoding Set the charset encoding.
38 | */
39 | public EscPosPrinter(DeviceConnection printerConnection, int printerDpi, float printerWidthMM, int printerNbrCharactersPerLine, EscPosCharsetEncoding charsetEncoding) throws EscPosConnectionException {
40 | this(printerConnection != null ? new EscPosPrinterCommands(printerConnection, charsetEncoding) : null, printerDpi, printerWidthMM, printerNbrCharactersPerLine);
41 | }
42 |
43 | /**
44 | * Create new instance of EscPosPrinter.
45 | *
46 | * @param printer Instance of EscPosPrinterCommands
47 | * @param printerDpi DPI of the connected printer
48 | * @param printerWidthMM Printing width in millimeters
49 | * @param printerNbrCharactersPerLine The maximum number of characters that can be printed on a line.
50 | */
51 | public EscPosPrinter(EscPosPrinterCommands printer, int printerDpi, float printerWidthMM, int printerNbrCharactersPerLine) throws EscPosConnectionException {
52 | super(printerDpi, printerWidthMM, printerNbrCharactersPerLine);
53 | if (printer != null) {
54 | this.printer = printer.connect();
55 | }
56 | }
57 |
58 | /**
59 | * Close the connection with the printer.
60 | *
61 | * @return Fluent interface
62 | */
63 | public EscPosPrinter disconnectPrinter() {
64 | if (this.printer != null) {
65 | this.printer.disconnect();
66 | this.printer = null;
67 | }
68 | return this;
69 | }
70 |
71 | /**
72 | * Active "ESC *" command for image printing.
73 | *
74 | * @param enable true to use "ESC *", false to use "GS v 0"
75 | * @return Fluent interface
76 | */
77 | public EscPosPrinter useEscAsteriskCommand(boolean enable) {
78 | this.printer.useEscAsteriskCommand(enable);
79 | return this;
80 | }
81 |
82 | /**
83 | * Print a formatted text. Read the README.md for more information about text formatting options.
84 | *
85 | * @param text Formatted text to be printed.
86 | * @return Fluent interface
87 | */
88 | public EscPosPrinter printFormattedText(String text) throws EscPosConnectionException, EscPosParserException, EscPosEncodingException, EscPosBarcodeException {
89 | return this.printFormattedText(text, 20f);
90 | }
91 |
92 | /**
93 | * Print a formatted text. Read the README.md for more information about text formatting options.
94 | *
95 | * @param text Formatted text to be printed.
96 | * @param mmFeedPaper millimeter distance feed paper at the end.
97 | * @return Fluent interface
98 | */
99 | public EscPosPrinter printFormattedText(String text, float mmFeedPaper) throws EscPosConnectionException, EscPosParserException, EscPosEncodingException, EscPosBarcodeException {
100 | return this.printFormattedText(text, this.mmToPx(mmFeedPaper));
101 | }
102 |
103 | /**
104 | * Print a formatted text. Read the README.md for more information about text formatting options.
105 | *
106 | * @param text Formatted text to be printed.
107 | * @param dotsFeedPaper distance feed paper at the end.
108 | * @return Fluent interface
109 | */
110 | public EscPosPrinter printFormattedText(String text, int dotsFeedPaper) throws EscPosConnectionException, EscPosParserException, EscPosEncodingException, EscPosBarcodeException {
111 | if (this.printer == null || this.printerNbrCharactersPerLine == 0) {
112 | return this;
113 | }
114 |
115 | PrinterTextParser textParser = new PrinterTextParser(this);
116 | PrinterTextParserLine[] linesParsed = textParser
117 | .setFormattedText(text)
118 | .parse();
119 |
120 | this.printer.reset();
121 |
122 | for (PrinterTextParserLine line : linesParsed) {
123 | PrinterTextParserColumn[] columns = line.getColumns();
124 |
125 | IPrinterTextParserElement lastElement = null;
126 | for (PrinterTextParserColumn column : columns) {
127 | IPrinterTextParserElement[] elements = column.getElements();
128 | for (IPrinterTextParserElement element : elements) {
129 | element.print(this.printer);
130 | lastElement = element;
131 | }
132 | }
133 |
134 | if (lastElement instanceof PrinterTextParserString) {
135 | this.printer.newLine();
136 | }
137 | }
138 |
139 | this.printer.feedPaper(dotsFeedPaper);
140 | return this;
141 | }
142 |
143 | /**
144 | * Print a formatted text and cut the paper. Read the README.md for more information about text formatting options.
145 | *
146 | * @param text Formatted text to be printed.
147 | * @return Fluent interface
148 | */
149 | public EscPosPrinter printFormattedTextAndCut(String text) throws EscPosConnectionException, EscPosParserException, EscPosEncodingException, EscPosBarcodeException {
150 | return this.printFormattedTextAndCut(text, 20f);
151 | }
152 |
153 | /**
154 | * Print a formatted text and cut the paper. Read the README.md for more information about text formatting options.
155 | *
156 | * @param text Formatted text to be printed.
157 | * @param mmFeedPaper millimeter distance feed paper at the end.
158 | * @return Fluent interface
159 | */
160 | public EscPosPrinter printFormattedTextAndCut(String text, float mmFeedPaper) throws EscPosConnectionException, EscPosParserException, EscPosEncodingException, EscPosBarcodeException {
161 | return this.printFormattedTextAndCut(text, this.mmToPx(mmFeedPaper));
162 | }
163 |
164 | /**
165 | * Print a formatted text and cut the paper. Read the README.md for more information about text formatting options.
166 | *
167 | * @param text Formatted text to be printed.
168 | * @param dotsFeedPaper distance feed paper at the end.
169 | * @return Fluent interface
170 | */
171 | public EscPosPrinter printFormattedTextAndCut(String text, int dotsFeedPaper) throws EscPosConnectionException, EscPosParserException, EscPosEncodingException, EscPosBarcodeException {
172 | if (this.printer == null || this.printerNbrCharactersPerLine == 0) {
173 | return this;
174 | }
175 |
176 | this.printFormattedText(text, dotsFeedPaper);
177 | this.printer.cutPaper();
178 |
179 | return this;
180 | }
181 |
182 | /**
183 | * Print a formatted text, cut the paper and open the cash box. Read the README.md for more information about text formatting options.
184 | *
185 | * @param text Formatted text to be printed.
186 | * @param mmFeedPaper millimeter distance feed paper at the end.
187 | * @return Fluent interface
188 | */
189 | public EscPosPrinter printFormattedTextAndOpenCashBox(String text, float mmFeedPaper) throws EscPosConnectionException, EscPosParserException, EscPosEncodingException, EscPosBarcodeException {
190 | return this.printFormattedTextAndOpenCashBox(text, this.mmToPx(mmFeedPaper));
191 | }
192 |
193 | /**
194 | * Print a formatted text, cut the paper and open the cash box. Read the README.md for more information about text formatting options.
195 | *
196 | * @param text Formatted text to be printed.
197 | * @param dotsFeedPaper distance feed paper at the end.
198 | * @return Fluent interface
199 | */
200 | public EscPosPrinter printFormattedTextAndOpenCashBox(String text, int dotsFeedPaper) throws EscPosConnectionException, EscPosParserException, EscPosEncodingException, EscPosBarcodeException {
201 | if (this.printer == null || this.printerNbrCharactersPerLine == 0) {
202 | return this;
203 | }
204 |
205 | this.printFormattedTextAndCut(text, dotsFeedPaper);
206 | this.printer.openCashBox();
207 | return this;
208 | }
209 |
210 | /**
211 | * @return Charset encoding
212 | */
213 | public EscPosCharsetEncoding getEncoding() {
214 | return this.printer.getCharsetEncoding();
215 | }
216 |
217 |
218 | /**
219 | * Print all characters of all charset encoding
220 | *
221 | * @return Fluent interface
222 | */
223 | public EscPosPrinter printAllCharsetsEncodingCharacters() {
224 | this.printer.printAllCharsetsEncodingCharacters();
225 | return this;
226 | }
227 |
228 | /**
229 | * Print all characters of selected charsets encoding
230 | *
231 | * @param charsetsId Array of charset id to print.
232 | * @return Fluent interface
233 | */
234 | public EscPosPrinter printCharsetsEncodingCharacters(int[] charsetsId) {
235 | this.printer.printCharsetsEncodingCharacters(charsetsId);
236 | return this;
237 | }
238 |
239 | /**
240 | * Print all characters of a charset encoding
241 | *
242 | * @param charsetId Charset id to print.
243 | * @return Fluent interface
244 | */
245 | public EscPosPrinter printCharsetEncodingCharacters(int charsetId) {
246 | this.printer.printCharsetEncodingCharacters(charsetId);
247 | return this;
248 | }
249 | }
250 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dantsu/thermalprinter/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.thermalprinter;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.appcompat.app.AppCompatActivity;
5 | import androidx.core.app.ActivityCompat;
6 | import androidx.core.content.ContextCompat;
7 |
8 | import android.Manifest;
9 | import android.annotation.SuppressLint;
10 | import android.app.AlertDialog;
11 | import android.app.PendingIntent;
12 | import android.content.BroadcastReceiver;
13 | import android.content.Context;
14 | import android.content.Intent;
15 | import android.content.IntentFilter;
16 | import android.content.pm.PackageManager;
17 | import android.hardware.usb.UsbDevice;
18 | import android.hardware.usb.UsbManager;
19 | import android.os.Bundle;
20 | import android.util.DisplayMetrics;
21 | import android.util.Log;
22 | import android.widget.Button;
23 | import android.widget.EditText;
24 |
25 | import com.dantsu.escposprinter.connection.DeviceConnection;
26 | import com.dantsu.escposprinter.connection.bluetooth.BluetoothConnection;
27 | import com.dantsu.escposprinter.connection.bluetooth.BluetoothPrintersConnections;
28 | import com.dantsu.escposprinter.connection.tcp.TcpConnection;
29 | import com.dantsu.escposprinter.connection.usb.UsbConnection;
30 | import com.dantsu.escposprinter.connection.usb.UsbPrintersConnections;
31 | import com.dantsu.escposprinter.textparser.PrinterTextParserImg;
32 | import com.dantsu.thermalprinter.async.AsyncBluetoothEscPosPrint;
33 | import com.dantsu.thermalprinter.async.AsyncEscPosPrint;
34 | import com.dantsu.thermalprinter.async.AsyncEscPosPrinter;
35 | import com.dantsu.thermalprinter.async.AsyncTcpEscPosPrint;
36 | import com.dantsu.thermalprinter.async.AsyncUsbEscPosPrint;
37 |
38 | import java.text.SimpleDateFormat;
39 | import java.util.Date;
40 |
41 | public class MainActivity extends AppCompatActivity {
42 |
43 |
44 | @Override
45 | protected void onCreate(Bundle savedInstanceState) {
46 | super.onCreate(savedInstanceState);
47 | setContentView(R.layout.activity_main);
48 | Button button = (Button) this.findViewById(R.id.button_bluetooth_browse);
49 | button.setOnClickListener(view -> browseBluetoothDevice());
50 | button = (Button) findViewById(R.id.button_bluetooth);
51 | button.setOnClickListener(view -> printBluetooth());
52 | button = (Button) this.findViewById(R.id.button_usb);
53 | button.setOnClickListener(view -> printUsb());
54 | button = (Button) this.findViewById(R.id.button_tcp);
55 | button.setOnClickListener(view -> printTcp());
56 |
57 | }
58 |
59 |
60 | /*==============================================================================================
61 | ======================================BLUETOOTH PART============================================
62 | ==============================================================================================*/
63 |
64 | public interface OnBluetoothPermissionsGranted {
65 | void onPermissionsGranted();
66 | }
67 |
68 | public static final int PERMISSION_BLUETOOTH = 1;
69 | public static final int PERMISSION_BLUETOOTH_ADMIN = 2;
70 | public static final int PERMISSION_BLUETOOTH_CONNECT = 3;
71 | public static final int PERMISSION_BLUETOOTH_SCAN = 4;
72 |
73 | public OnBluetoothPermissionsGranted onBluetoothPermissionsGranted;
74 |
75 | @Override
76 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
77 | super.onRequestPermissionsResult(requestCode, permissions, grantResults);
78 | if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
79 | switch (requestCode) {
80 | case MainActivity.PERMISSION_BLUETOOTH:
81 | case MainActivity.PERMISSION_BLUETOOTH_ADMIN:
82 | case MainActivity.PERMISSION_BLUETOOTH_CONNECT:
83 | case MainActivity.PERMISSION_BLUETOOTH_SCAN:
84 | this.checkBluetoothPermissions(this.onBluetoothPermissionsGranted);
85 | break;
86 | }
87 | }
88 | }
89 |
90 | public void checkBluetoothPermissions(OnBluetoothPermissionsGranted onBluetoothPermissionsGranted) {
91 | this.onBluetoothPermissionsGranted = onBluetoothPermissionsGranted;
92 | if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.S && ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED) {
93 | ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH}, MainActivity.PERMISSION_BLUETOOTH);
94 | } else if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.S && ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_ADMIN) != PackageManager.PERMISSION_GRANTED) {
95 | ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_ADMIN}, MainActivity.PERMISSION_BLUETOOTH_ADMIN);
96 | } else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S && ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
97 | ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_CONNECT}, MainActivity.PERMISSION_BLUETOOTH_CONNECT);
98 | } else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S && ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
99 | ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_SCAN}, MainActivity.PERMISSION_BLUETOOTH_SCAN);
100 | } else {
101 | this.onBluetoothPermissionsGranted.onPermissionsGranted();
102 | }
103 | }
104 |
105 | private BluetoothConnection selectedDevice;
106 |
107 | public void browseBluetoothDevice() {
108 | this.checkBluetoothPermissions(() -> {
109 | final BluetoothConnection[] bluetoothDevicesList = (new BluetoothPrintersConnections()).getList();
110 |
111 | if (bluetoothDevicesList != null) {
112 | final String[] items = new String[bluetoothDevicesList.length + 1];
113 | items[0] = "Default printer";
114 | int i = 0;
115 | for (BluetoothConnection device : bluetoothDevicesList) {
116 | items[++i] = device.getDevice().getName();
117 | }
118 |
119 | AlertDialog.Builder alertDialog = new AlertDialog.Builder(MainActivity.this);
120 | alertDialog.setTitle("Bluetooth printer selection");
121 | alertDialog.setItems(
122 | items,
123 | (dialogInterface, i1) -> {
124 | int index = i1 - 1;
125 | if (index == -1) {
126 | selectedDevice = null;
127 | } else {
128 | selectedDevice = bluetoothDevicesList[index];
129 | }
130 | Button button = (Button) findViewById(R.id.button_bluetooth_browse);
131 | button.setText(items[i1]);
132 | }
133 | );
134 |
135 | AlertDialog alert = alertDialog.create();
136 | alert.setCanceledOnTouchOutside(false);
137 | alert.show();
138 | }
139 | });
140 |
141 | }
142 |
143 | public void printBluetooth() {
144 | this.checkBluetoothPermissions(() -> {
145 | new AsyncBluetoothEscPosPrint(
146 | this,
147 | new AsyncEscPosPrint.OnPrintFinished() {
148 | @Override
149 | public void onError(AsyncEscPosPrinter asyncEscPosPrinter, int codeException) {
150 | Log.e("Async.OnPrintFinished", "AsyncEscPosPrint.OnPrintFinished : An error occurred !");
151 | }
152 |
153 | @Override
154 | public void onSuccess(AsyncEscPosPrinter asyncEscPosPrinter) {
155 | Log.i("Async.OnPrintFinished", "AsyncEscPosPrint.OnPrintFinished : Print is finished !");
156 | }
157 | }
158 | )
159 | .execute(this.getAsyncEscPosPrinter(selectedDevice));
160 | });
161 | }
162 |
163 | /*==============================================================================================
164 | ===========================================USB PART=============================================
165 | ==============================================================================================*/
166 |
167 | private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
168 | private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
169 | public void onReceive(Context context, Intent intent) {
170 | String action = intent.getAction();
171 | if (MainActivity.ACTION_USB_PERMISSION.equals(action)) {
172 | synchronized (this) {
173 | UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
174 | UsbDevice usbDevice = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
175 | if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
176 | if (usbManager != null && usbDevice != null) {
177 | new AsyncUsbEscPosPrint(
178 | context,
179 | new AsyncEscPosPrint.OnPrintFinished() {
180 | @Override
181 | public void onError(AsyncEscPosPrinter asyncEscPosPrinter, int codeException) {
182 | Log.e("Async.OnPrintFinished", "AsyncEscPosPrint.OnPrintFinished : An error occurred !");
183 | }
184 |
185 | @Override
186 | public void onSuccess(AsyncEscPosPrinter asyncEscPosPrinter) {
187 | Log.i("Async.OnPrintFinished", "AsyncEscPosPrint.OnPrintFinished : Print is finished !");
188 | }
189 | }
190 | )
191 | .execute(getAsyncEscPosPrinter(new UsbConnection(usbManager, usbDevice)));
192 | }
193 | }
194 | }
195 | }
196 | }
197 | };
198 |
199 | public void printUsb() {
200 | UsbConnection usbConnection = UsbPrintersConnections.selectFirstConnected(this);
201 | UsbManager usbManager = (UsbManager) this.getSystemService(Context.USB_SERVICE);
202 |
203 | if (usbConnection == null || usbManager == null) {
204 | new AlertDialog.Builder(this)
205 | .setTitle("USB Connection")
206 | .setMessage("No USB printer found.")
207 | .show();
208 | return;
209 | }
210 |
211 | PendingIntent permissionIntent = PendingIntent.getBroadcast(
212 | this,
213 | 0,
214 | new Intent(MainActivity.ACTION_USB_PERMISSION),
215 | android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S ? PendingIntent.FLAG_MUTABLE : 0
216 | );
217 | IntentFilter filter = new IntentFilter(MainActivity.ACTION_USB_PERMISSION);
218 | registerReceiver(this.usbReceiver, filter);
219 | usbManager.requestPermission(usbConnection.getDevice(), permissionIntent);
220 | }
221 |
222 | /*==============================================================================================
223 | =========================================TCP PART===============================================
224 | ==============================================================================================*/
225 |
226 | public void printTcp() {
227 | final EditText ipAddress = (EditText) this.findViewById(R.id.edittext_tcp_ip);
228 | final EditText portAddress = (EditText) this.findViewById(R.id.edittext_tcp_port);
229 |
230 | try {
231 | new AsyncTcpEscPosPrint(
232 | this,
233 | new AsyncEscPosPrint.OnPrintFinished() {
234 | @Override
235 | public void onError(AsyncEscPosPrinter asyncEscPosPrinter, int codeException) {
236 | Log.e("Async.OnPrintFinished", "AsyncEscPosPrint.OnPrintFinished : An error occurred !");
237 | }
238 |
239 | @Override
240 | public void onSuccess(AsyncEscPosPrinter asyncEscPosPrinter) {
241 | Log.i("Async.OnPrintFinished", "AsyncEscPosPrint.OnPrintFinished : Print is finished !");
242 | }
243 | }
244 | )
245 | .execute(
246 | this.getAsyncEscPosPrinter(
247 | new TcpConnection(
248 | ipAddress.getText().toString(),
249 | Integer.parseInt(portAddress.getText().toString())
250 | )
251 | )
252 | );
253 | } catch (NumberFormatException e) {
254 | new AlertDialog.Builder(this)
255 | .setTitle("Invalid TCP port address")
256 | .setMessage("Port field must be an integer.")
257 | .show();
258 | e.printStackTrace();
259 | }
260 | }
261 |
262 | /*==============================================================================================
263 | ===================================ESC/POS PRINTER PART=========================================
264 | ==============================================================================================*/
265 |
266 | /**
267 | * Asynchronous printing
268 | */
269 | @SuppressLint("SimpleDateFormat")
270 | public AsyncEscPosPrinter getAsyncEscPosPrinter(DeviceConnection printerConnection) {
271 | SimpleDateFormat format = new SimpleDateFormat("'on' yyyy-MM-dd 'at' HH:mm:ss");
272 | AsyncEscPosPrinter printer = new AsyncEscPosPrinter(printerConnection, 203, 48f, 32);
273 | return printer.addTextToPrint(
274 | "[C]
" + PrinterTextParserImg.bitmapToHexadecimalString(printer, this.getApplicationContext().getResources().getDrawableForDensity(R.drawable.logo, DisplayMetrics.DENSITY_MEDIUM)) + "\n" +
275 | "[L]\n" +
276 | "[C]ORDER N°045\n" +
277 | "[L]\n" +
278 | "[C]" + format.format(new Date()) + "\n" +
279 | "[C]\n" +
280 | "[C]================================\n" +
281 | "[L]\n" +
282 | "[L]BEAUTIFUL SHIRT[R]9.99€\n" +
283 | "[L] + Size : S\n" +
284 | "[L]\n" +
285 | "[L]AWESOME HAT[R]24.99€\n" +
286 | "[L] + Size : 57/58\n" +
287 | "[L]\n" +
288 | "[C]--------------------------------\n" +
289 | "[R]TOTAL PRICE :[R]34.98€\n" +
290 | "[R]TAX :[R]4.23€\n" +
291 | "[L]\n" +
292 | "[C]================================\n" +
293 | "[L]\n" +
294 | "[L]Customer :\n" +
295 | "[L]Raymond DUPONT\n" +
296 | "[L]5 rue des girafes\n" +
297 | "[L]31547 PERPETES\n" +
298 | "[L]Tel : +33801201456\n" +
299 | "\n" +
300 | "[C]831254784551\n" +
301 | "[L]\n" +
302 | "[C]https://dantsu.com/\n"
303 | );
304 | }
305 | }
306 |
--------------------------------------------------------------------------------
/escposprinter/src/main/java/com/dantsu/escposprinter/textparser/PrinterTextParserColumn.java:
--------------------------------------------------------------------------------
1 | package com.dantsu.escposprinter.textparser;
2 |
3 | import java.util.Hashtable;
4 |
5 | import com.dantsu.escposprinter.EscPosPrinter;
6 | import com.dantsu.escposprinter.EscPosPrinterCommands;
7 | import com.dantsu.escposprinter.exceptions.EscPosBarcodeException;
8 | import com.dantsu.escposprinter.exceptions.EscPosEncodingException;
9 | import com.dantsu.escposprinter.exceptions.EscPosParserException;
10 |
11 | public class PrinterTextParserColumn {
12 |
13 | private static String generateSpace(int nbrSpace) {
14 | StringBuilder str = new StringBuilder();
15 | for (int i = 0; i < nbrSpace; i++) {
16 | str.append(" ");
17 | }
18 | return str.toString();
19 | }
20 |
21 |
22 | private PrinterTextParserLine textParserLine;
23 | private IPrinterTextParserElement[] elements = new IPrinterTextParserElement[0];
24 |
25 | /**
26 | * Create a new instance of PrinterTextParserColumn.
27 | *
28 | * @param textParserLine Parent PrinterTextParserLine instance
29 | * @param textColumn Text that the column contain
30 | */
31 | public PrinterTextParserColumn(PrinterTextParserLine textParserLine, String textColumn) throws EscPosParserException, EscPosBarcodeException, EscPosEncodingException {
32 | this.textParserLine = textParserLine;
33 | PrinterTextParser textParser = this.textParserLine.getTextParser();
34 | String textAlign = PrinterTextParser.TAGS_ALIGN_LEFT;
35 | byte[]
36 | textUnderlineStartColumn = textParser.getLastTextUnderline(),
37 | textDoubleStrikeStartColumn = textParser.getLastTextDoubleStrike(),
38 | textColorStartColumn = textParser.getLastTextColor(),
39 | textReverseColorStartColumn = textParser.getLastTextReverseColor();
40 |
41 |
42 | // =================================================================
43 | // Check the column alignment
44 | if(textColumn.length() > 2) {
45 | switch (textColumn.substring(0, 3).toUpperCase()) {
46 | case "[" + PrinterTextParser.TAGS_ALIGN_LEFT + "]":
47 | case "[" + PrinterTextParser.TAGS_ALIGN_CENTER + "]":
48 | case "[" + PrinterTextParser.TAGS_ALIGN_RIGHT + "]":
49 | textAlign = textColumn.substring(1, 2).toUpperCase();
50 | textColumn = textColumn.substring(3);
51 | break;
52 | }
53 | }
54 |
55 | String trimmedTextColumn = textColumn.trim();
56 | boolean isImgOrBarcodeLine = false;
57 |
58 | if (this.textParserLine.getNbrColumns() == 1 && trimmedTextColumn.indexOf("<") == 0) {
59 | // =================================================================
60 | // Image or Barcode Lines
61 | int openTagIndex = trimmedTextColumn.indexOf("<"),
62 | openTagEndIndex = trimmedTextColumn.indexOf(">", openTagIndex + 1) + 1;
63 |
64 | if (openTagIndex < openTagEndIndex) {
65 | PrinterTextParserTag textParserTag = new PrinterTextParserTag(trimmedTextColumn.substring(openTagIndex, openTagEndIndex));
66 |
67 | switch (textParserTag.getTagName()) {
68 | case PrinterTextParser.TAGS_IMAGE:
69 | case PrinterTextParser.TAGS_BARCODE:
70 | case PrinterTextParser.TAGS_QRCODE:
71 | String closeTag = "" + textParserTag.getTagName() + ">";
72 | int closeTagPosition = trimmedTextColumn.length() - closeTag.length();
73 |
74 | if (trimmedTextColumn.substring(closeTagPosition).equals(closeTag)) {
75 | switch (textParserTag.getTagName()) {
76 | case PrinterTextParser.TAGS_IMAGE:
77 | this.appendImage(textAlign, trimmedTextColumn.substring(openTagEndIndex, closeTagPosition));
78 | break;
79 | case PrinterTextParser.TAGS_BARCODE:
80 | this.appendBarcode(textAlign, textParserTag.getAttributes(), trimmedTextColumn.substring(openTagEndIndex, closeTagPosition));
81 | break;
82 | case PrinterTextParser.TAGS_QRCODE:
83 | this.appendQRCode(textAlign, textParserTag.getAttributes(), trimmedTextColumn.substring(openTagEndIndex, closeTagPosition));
84 | break;
85 | }
86 | isImgOrBarcodeLine = true;
87 | }
88 | break;
89 | }
90 | }
91 | }
92 |
93 | if (!isImgOrBarcodeLine) {
94 | // =================================================================
95 | // If the tag is for format text
96 |
97 | int offset = 0;
98 | while (true) {
99 | int openTagIndex = textColumn.indexOf("<", offset), closeTagIndex = -1;
100 |
101 | if (openTagIndex != -1) {
102 | closeTagIndex = textColumn.indexOf(">", openTagIndex);
103 | } else {
104 | openTagIndex = textColumn.length();
105 | }
106 |
107 | this.appendString(textColumn.substring(offset, openTagIndex));
108 |
109 | if (closeTagIndex == -1) {
110 | break;
111 | }
112 |
113 | closeTagIndex++;
114 | PrinterTextParserTag textParserTag = new PrinterTextParserTag(textColumn.substring(openTagIndex, closeTagIndex));
115 |
116 | if (PrinterTextParser.isTagTextFormat(textParserTag.getTagName())) {
117 | if (textParserTag.isCloseTag()) {
118 | switch (textParserTag.getTagName()) {
119 | case PrinterTextParser.TAGS_FORMAT_TEXT_BOLD:
120 | textParser.dropTextBold();
121 | break;
122 | case PrinterTextParser.TAGS_FORMAT_TEXT_UNDERLINE:
123 | textParser.dropLastTextUnderline();
124 | textParser.dropLastTextDoubleStrike();
125 | break;
126 | case PrinterTextParser.TAGS_FORMAT_TEXT_FONT:
127 | textParser.dropLastTextSize();
128 | textParser.dropLastTextColor();
129 | textParser.dropLastTextReverseColor();
130 | break;
131 | }
132 | } else {
133 | switch (textParserTag.getTagName()) {
134 | case PrinterTextParser.TAGS_FORMAT_TEXT_BOLD:
135 | textParser.addTextBold(EscPosPrinterCommands.TEXT_WEIGHT_BOLD);
136 | break;
137 | case PrinterTextParser.TAGS_FORMAT_TEXT_UNDERLINE:
138 | if (textParserTag.hasAttribute(PrinterTextParser.ATTR_FORMAT_TEXT_UNDERLINE_TYPE)) {
139 | switch (textParserTag.getAttribute(PrinterTextParser.ATTR_FORMAT_TEXT_UNDERLINE_TYPE)) {
140 | case PrinterTextParser.ATTR_FORMAT_TEXT_UNDERLINE_TYPE_NORMAL:
141 | textParser.addTextUnderline(EscPosPrinterCommands.TEXT_UNDERLINE_LARGE);
142 | textParser.addTextDoubleStrike(textParser.getLastTextDoubleStrike());
143 | break;
144 | case PrinterTextParser.ATTR_FORMAT_TEXT_UNDERLINE_TYPE_DOUBLE:
145 | textParser.addTextUnderline(textParser.getLastTextUnderline());
146 | textParser.addTextDoubleStrike(EscPosPrinterCommands.TEXT_DOUBLE_STRIKE_ON);
147 | break;
148 | }
149 | } else {
150 | textParser.addTextUnderline(EscPosPrinterCommands.TEXT_UNDERLINE_LARGE);
151 | textParser.addTextDoubleStrike(textParser.getLastTextDoubleStrike());
152 | }
153 | break;
154 | case PrinterTextParser.TAGS_FORMAT_TEXT_FONT:
155 | if (textParserTag.hasAttribute(PrinterTextParser.ATTR_FORMAT_TEXT_FONT_SIZE)) {
156 | switch (textParserTag.getAttribute(PrinterTextParser.ATTR_FORMAT_TEXT_FONT_SIZE)) {
157 | case PrinterTextParser.ATTR_FORMAT_TEXT_FONT_SIZE_NORMAL:
158 | default:
159 | textParser.addTextSize(EscPosPrinterCommands.TEXT_SIZE_NORMAL);
160 | break;
161 | case PrinterTextParser.ATTR_FORMAT_TEXT_FONT_SIZE_TALL:
162 | textParser.addTextSize(EscPosPrinterCommands.TEXT_SIZE_DOUBLE_HEIGHT);
163 | break;
164 | case PrinterTextParser.ATTR_FORMAT_TEXT_FONT_SIZE_WIDE:
165 | textParser.addTextSize(EscPosPrinterCommands.TEXT_SIZE_DOUBLE_WIDTH);
166 | break;
167 | case PrinterTextParser.ATTR_FORMAT_TEXT_FONT_SIZE_BIG:
168 | textParser.addTextSize(EscPosPrinterCommands.TEXT_SIZE_BIG);
169 | break;
170 | case PrinterTextParser.ATTR_FORMAT_TEXT_FONT_SIZE_BIG_2:
171 | textParser.addTextSize(EscPosPrinterCommands.TEXT_SIZE_BIG_2);
172 | break;
173 | case PrinterTextParser.ATTR_FORMAT_TEXT_FONT_SIZE_BIG_3:
174 | textParser.addTextSize(EscPosPrinterCommands.TEXT_SIZE_BIG_3);
175 | break;
176 | case PrinterTextParser.ATTR_FORMAT_TEXT_FONT_SIZE_BIG_4:
177 | textParser.addTextSize(EscPosPrinterCommands.TEXT_SIZE_BIG_4);
178 | break;
179 | case PrinterTextParser.ATTR_FORMAT_TEXT_FONT_SIZE_BIG_5:
180 | textParser.addTextSize(EscPosPrinterCommands.TEXT_SIZE_BIG_5);
181 | break;
182 | case PrinterTextParser.ATTR_FORMAT_TEXT_FONT_SIZE_BIG_6:
183 | textParser.addTextSize(EscPosPrinterCommands.TEXT_SIZE_BIG_6);
184 | break;
185 | }
186 | } else {
187 | textParser.addTextSize(textParser.getLastTextSize());
188 | }
189 |
190 | if (textParserTag.hasAttribute(PrinterTextParser.ATTR_FORMAT_TEXT_FONT_COLOR)) {
191 | switch (textParserTag.getAttribute(PrinterTextParser.ATTR_FORMAT_TEXT_FONT_COLOR)) {
192 | case PrinterTextParser.ATTR_FORMAT_TEXT_FONT_COLOR_BLACK:
193 | default:
194 | textParser.addTextColor(EscPosPrinterCommands.TEXT_COLOR_BLACK);
195 | textParser.addTextReverseColor(EscPosPrinterCommands.TEXT_COLOR_REVERSE_OFF);
196 | break;
197 | case PrinterTextParser.ATTR_FORMAT_TEXT_FONT_COLOR_BG_BLACK:
198 | textParser.addTextColor(EscPosPrinterCommands.TEXT_COLOR_BLACK);
199 | textParser.addTextReverseColor(EscPosPrinterCommands.TEXT_COLOR_REVERSE_ON);
200 | break;
201 | case PrinterTextParser.ATTR_FORMAT_TEXT_FONT_COLOR_RED:
202 | textParser.addTextColor(EscPosPrinterCommands.TEXT_COLOR_RED);
203 | textParser.addTextReverseColor(EscPosPrinterCommands.TEXT_COLOR_REVERSE_OFF);
204 | break;
205 | case PrinterTextParser.ATTR_FORMAT_TEXT_FONT_COLOR_BG_RED:
206 | textParser.addTextColor(EscPosPrinterCommands.TEXT_COLOR_RED);
207 | textParser.addTextReverseColor(EscPosPrinterCommands.TEXT_COLOR_REVERSE_ON);
208 | break;
209 | }
210 | } else {
211 | textParser.addTextColor(textParser.getLastTextColor());
212 | textParser.addTextReverseColor(textParser.getLastTextReverseColor());
213 | }
214 | break;
215 | }
216 | }
217 | offset = closeTagIndex;
218 | } else {
219 | this.appendString("<");
220 | offset = openTagIndex + 1;
221 | }
222 | }
223 |
224 | // =================================================================
225 | // Define the number of spaces required for the different alignments
226 |
227 | int nbrCharColumn = this.textParserLine.getNbrCharColumn(),
228 | nbrCharForgetted = this.textParserLine.getNbrCharForgetted(),
229 | nbrCharColumnExceeded = this.textParserLine.getNbrCharColumnExceeded(),
230 | nbrCharTextWithoutTag = 0,
231 | leftSpace = 0,
232 | rightSpace = 0;
233 |
234 | for (IPrinterTextParserElement textParserElement : this.elements) {
235 | nbrCharTextWithoutTag += textParserElement.length();
236 | }
237 |
238 | switch (textAlign) {
239 | case PrinterTextParser.TAGS_ALIGN_LEFT:
240 | rightSpace = nbrCharColumn - nbrCharTextWithoutTag;
241 | break;
242 | case PrinterTextParser.TAGS_ALIGN_CENTER:
243 | leftSpace = (int) Math.floor((((float) nbrCharColumn) - ((float) nbrCharTextWithoutTag)) / 2f);
244 | rightSpace = nbrCharColumn - nbrCharTextWithoutTag - leftSpace;
245 | break;
246 | case PrinterTextParser.TAGS_ALIGN_RIGHT:
247 | leftSpace = nbrCharColumn - nbrCharTextWithoutTag;
248 | break;
249 | }
250 |
251 | if (nbrCharForgetted > 0) {
252 | nbrCharForgetted -= 1;
253 | rightSpace++;
254 | }
255 |
256 | if (nbrCharColumnExceeded < 0) {
257 | leftSpace += nbrCharColumnExceeded;
258 | nbrCharColumnExceeded = 0;
259 | if (leftSpace < 1) {
260 | rightSpace += leftSpace - 1;
261 | leftSpace = 1;
262 | }
263 | }
264 |
265 | if (leftSpace < 0) {
266 | nbrCharColumnExceeded += leftSpace;
267 | leftSpace = 0;
268 | }
269 | if (rightSpace < 0) {
270 | nbrCharColumnExceeded += rightSpace;
271 | rightSpace = 0;
272 | }
273 |
274 | if (leftSpace > 0) {
275 | this.prependString(PrinterTextParserColumn.generateSpace(leftSpace), EscPosPrinterCommands.TEXT_SIZE_NORMAL, textColorStartColumn, textReverseColorStartColumn, EscPosPrinterCommands.TEXT_WEIGHT_NORMAL, textUnderlineStartColumn, textDoubleStrikeStartColumn);
276 | }
277 | if (rightSpace > 0) {
278 | this.appendString(PrinterTextParserColumn.generateSpace(rightSpace), EscPosPrinterCommands.TEXT_SIZE_NORMAL, textParser.getLastTextColor(), textParser.getLastTextReverseColor(), EscPosPrinterCommands.TEXT_WEIGHT_NORMAL, textParser.getLastTextUnderline(), textParser.getLastTextDoubleStrike());
279 | }
280 |
281 | // =================================================================================================
282 | // nbrCharForgetted and nbrCharColumnExceeded is use to define number of spaces for the next columns
283 |
284 | this.textParserLine
285 | .setNbrCharForgetted(nbrCharForgetted)
286 | .setNbrCharColumnExceeded(nbrCharColumnExceeded);
287 | }
288 | }
289 |
290 | private PrinterTextParserColumn prependString(String text) {
291 | PrinterTextParser textParser = this.textParserLine.getTextParser();
292 | return this.prependString(text, textParser.getLastTextSize(), textParser.getLastTextColor(), textParser.getLastTextReverseColor(), textParser.getLastTextBold(), textParser.getLastTextUnderline(), textParser.getLastTextDoubleStrike());
293 | }
294 |
295 | private PrinterTextParserColumn prependString(String text, byte[] textSize, byte[] textColor, byte[] textReverseColor, byte[] textBold, byte[] textUnderline, byte[] textDoubleStrike) {
296 | return this.prependElement(new PrinterTextParserString(this, text, textSize, textColor, textReverseColor, textBold, textUnderline, textDoubleStrike));
297 | }
298 |
299 | private PrinterTextParserColumn appendString(String text) {
300 | PrinterTextParser textParser = this.textParserLine.getTextParser();
301 | return this.appendString(text, textParser.getLastTextSize(), textParser.getLastTextColor(), textParser.getLastTextReverseColor(), textParser.getLastTextBold(), textParser.getLastTextUnderline(), textParser.getLastTextDoubleStrike());
302 | }
303 |
304 | private PrinterTextParserColumn appendString(String text, byte[] textSize, byte[] textColor, byte[] textReverseColor, byte[] textBold, byte[] textUnderline, byte[] textDoubleStrike) {
305 | EscPosPrinter printer = this.textParserLine.getTextParser().getPrinter();
306 | return this.appendElement(new PrinterTextParserString(this, text, textSize, textColor, textReverseColor, textBold, textUnderline, textDoubleStrike));
307 | }
308 |
309 | private PrinterTextParserColumn prependImage(String textAlign, String hexString) {
310 | return this.prependElement(new PrinterTextParserImg(this, textAlign, hexString));
311 | }
312 |
313 | private PrinterTextParserColumn appendImage(String textAlign, String hexString) {
314 | return this.appendElement(new PrinterTextParserImg(this, textAlign, hexString));
315 | }
316 |
317 | private PrinterTextParserColumn prependBarcode(String textAlign, Hashtable barcodeAttributes, String code) throws EscPosParserException, EscPosBarcodeException {
318 | return this.prependElement(new PrinterTextParserBarcode(this, textAlign, barcodeAttributes, code));
319 | }
320 |
321 | private PrinterTextParserColumn appendBarcode(String textAlign, Hashtable barcodeAttributes, String code) throws EscPosParserException, EscPosBarcodeException {
322 | return this.appendElement(new PrinterTextParserBarcode(this, textAlign, barcodeAttributes, code));
323 | }
324 |
325 | private PrinterTextParserColumn prependQRCode(String textAlign, Hashtable qrCodeAttributes, String data) throws EscPosParserException, EscPosBarcodeException {
326 | return this.prependElement(new PrinterTextParserBarcode(this, textAlign, qrCodeAttributes, data));
327 | }
328 |
329 | private PrinterTextParserColumn appendQRCode(String textAlign, Hashtable qrCodeAttributes, String data) throws EscPosParserException, EscPosBarcodeException {
330 | return this.appendElement(new PrinterTextParserQRCode(this, textAlign, qrCodeAttributes, data));
331 | }
332 |
333 | private PrinterTextParserColumn prependElement(IPrinterTextParserElement element) {
334 | IPrinterTextParserElement[] elementsTmp = new IPrinterTextParserElement[this.elements.length + 1];
335 | elementsTmp[0] = element;
336 | System.arraycopy(this.elements, 0, elementsTmp, 1, this.elements.length);
337 | this.elements = elementsTmp;
338 | return this;
339 | }
340 |
341 | private PrinterTextParserColumn appendElement(IPrinterTextParserElement element) {
342 | IPrinterTextParserElement[] elementsTmp = new IPrinterTextParserElement[this.elements.length + 1];
343 | System.arraycopy(this.elements, 0, elementsTmp, 0, this.elements.length);
344 | elementsTmp[this.elements.length] = element;
345 | this.elements = elementsTmp;
346 | return this;
347 | }
348 |
349 | public PrinterTextParserLine getLine() {
350 | return this.textParserLine;
351 | }
352 |
353 | public IPrinterTextParserElement[] getElements() {
354 | return this.elements;
355 | }
356 | }
357 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://jitpack.io/#DantSu/ESCPOS-ThermalPrinter-Android/3.3.0)
2 | [](https://jitpack.io/#DantSu/ESCPOS-ThermalPrinter-Android/3.3.0)
3 | [](https://jitpack.io/#DantSu/ESCPOS-ThermalPrinter-Android/3.3.0)
4 | [](https://opensource.org/licenses/MIT)
5 |
6 | # Android library for ESC/POS Thermal Printer
7 |
8 | Useful library to help Android developers to print with (Bluetooth, TCP, USB) ESC/POS thermal printers.
9 |
10 | ## ✨ Supporting
11 |
12 | ⭐ Star this repository to support this project. You will contribute to increase the visibility of this library 🙂
13 |
14 | ## Table of contents
15 |
16 | - [Android version](#android-version)
17 | - [Tested printers](#tested-printers)
18 | - [Test It !](#test-it-)
19 | - [Installation](#installation)
20 | - [Bluetooth](#bluetooth)
21 | - [Bluetooth permission](#bluetooth-permission)
22 | - [Bluetooth code example](#bluetooth-code-example)
23 | - [TCP](#tcp)
24 | - [TCP permission](#tcp-permission)
25 | - [TCP code example](#tcp-code-example)
26 | - [USB](#usb)
27 | - [USB permission](#usb-permission)
28 | - [USB code example](#usb-code-example)
29 | - [Charset encoding](#charset-encoding)
30 | - [Formatted text : syntax guide](#formatted-text--syntax-guide)
31 | - [Class list](#class-list)
32 | - [BluetoothPrintersConnections](#user-content-class--comdantsuescposprinterconnectionbluetoothbluetoothprintersconnections)
33 | - [UsbPrintersConnections](#user-content-class--comdantsuescposprinterconnectionusbusbprintersconnections)
34 | - [EscPosPrinter](#user-content-class--comdantsuescposprinterescposprinter)
35 | - [PrinterTextParserImg](#user-content-class--comdantsuescposprintertextparserprintertextparserimg)
36 | - [EscPosCharsetEncoding](#user-content-class--comdantsuescposprinterescposcharsetencoding)
37 | - [Projects using this library](#projects-using-this-library)
38 | - [Contributing](#contributing)
39 |
40 |
41 | ## Android version
42 |
43 | Developed for SDK version 16 (Android 4.1 Jelly Bean) and above.
44 |
45 |
46 | ## Tested printers
47 |
48 | 1. [HOIN HOP H58 Thermal Printer ESC/POS](https://www.gearbest.com/printers/pp_662658.html).
49 | 2. [XPRINTER XP-P300](https://xprinter.vn/xprinter-xp-p300-may-in-hoa-don-di-dong-bluetooth/).
50 | 3. [MUNBYN IMP001](https://www.munbyn.com/collections/portable-receipt-printer/products/58mm-bluetooth-thermal-printer-imp001).
51 | 4. [JP-Q2 POS Terminal PDA](https://www.aliexpress.com/item/32971775060.html) (Embedded printer is configured as Bluetooth device)
52 | 5. [MUNBYN ITPP047](https://www.munbyn.com/products/munbyn-itpp047-wifi-thermal-printer) (tested over USB)
53 |
54 | ## Test it !
55 |
56 | To test this library, it's pretty simple !
57 |
58 | - Create a directory and open a terminal inside
59 | - Run `git clone https://github.com/DantSu/ESCPOS-ThermalPrinter-Android.git .`
60 | - Open the directory with Android Studio
61 | - Test it !
62 |
63 | ## Installation
64 |
65 | **Step 1.** Add the [JitPack](https://jitpack.io/#DantSu/ESCPOS-ThermalPrinter-Android/3.3.0) repository to your build file. Add it in your root `/build.gradle` at the end of repositories:
66 |
67 | ```
68 | allprojects {
69 | repositories {
70 | ...
71 | maven { url 'https://jitpack.io' }
72 | }
73 | }
74 | ```
75 |
76 | **Step 2.** Add the dependency in `/app/build.gradle` :
77 |
78 | ```
79 | dependencies {
80 | ...
81 | implementation 'com.github.DantSu:ESCPOS-ThermalPrinter-Android:3.3.0'
82 | }
83 | ```
84 |
85 | ## Bluetooth
86 |
87 | ### Bluetooth permission
88 |
89 | Be sure to have ``, ``, ``, `` in your `AndroidManifest.xml`.
90 |
91 | Also, you have to check the bluetooth permission in your app like this :
92 |
93 | ```java
94 | if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.S && ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED) {
95 | ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH}, MainActivity.PERMISSION_BLUETOOTH);
96 | } else if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.S && ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_ADMIN) != PackageManager.PERMISSION_GRANTED) {
97 | ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_ADMIN}, MainActivity.PERMISSION_BLUETOOTH_ADMIN);
98 | } else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S && ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
99 | ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_CONNECT}, MainActivity.PERMISSION_BLUETOOTH_CONNECT);
100 | } else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S && ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
101 | ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_SCAN}, MainActivity.PERMISSION_BLUETOOTH_SCAN);
102 | } else {
103 | // Your code HERE
104 | }
105 | ```
106 |
107 | ### Bluetooth code example
108 |
109 | The code below is an example to write in your activity :
110 |
111 | ```java
112 | EscPosPrinter printer = new EscPosPrinter(BluetoothPrintersConnections.selectFirstPaired(), 203, 48f, 32);
113 | printer
114 | .printFormattedText(
115 | "[C]
" + PrinterTextParserImg.bitmapToHexadecimalString(printer, this.getApplicationContext().getResources().getDrawableForDensity(R.drawable.logo, DisplayMetrics.DENSITY_MEDIUM))+"\n" +
116 | "[L]\n" +
117 | "[C]ORDER N°045\n" +
118 | "[L]\n" +
119 | "[C]================================\n" +
120 | "[L]\n" +
121 | "[L]BEAUTIFUL SHIRT[R]9.99e\n" +
122 | "[L] + Size : S\n" +
123 | "[L]\n" +
124 | "[L]AWESOME HAT[R]24.99e\n" +
125 | "[L] + Size : 57/58\n" +
126 | "[L]\n" +
127 | "[C]--------------------------------\n" +
128 | "[R]TOTAL PRICE :[R]34.98e\n" +
129 | "[R]TAX :[R]4.23e\n" +
130 | "[L]\n" +
131 | "[C]================================\n" +
132 | "[L]\n" +
133 | "[L]Customer :\n" +
134 | "[L]Raymond DUPONT\n" +
135 | "[L]5 rue des girafes\n" +
136 | "[L]31547 PERPETES\n" +
137 | "[L]Tel : +33801201456\n" +
138 | "[L]\n" +
139 | "[C]831254784551\n" +
140 | "[C]https://dantsu.com/"
141 | );
142 | ```
143 |
144 | Below a picture of the receipt printed with the code above :
145 |
146 | 
147 |
148 | ## TCP
149 |
150 | ### TCP permission
151 |
152 | Be sure to have `` in your `AndroidManifest.xml`.
153 |
154 | ### TCP code example
155 |
156 | The code below is an example to write in your activity :
157 |
158 | ```java
159 | new Thread(new Runnable() {
160 | public void run() {
161 | try {
162 | EscPosPrinter printer = new EscPosPrinter(new TcpConnection("192.168.1.3", 9300, 15), 203, 48f, 32);
163 | printer
164 | .printFormattedText(
165 | "[C]
" + PrinterTextParserImg.bitmapToHexadecimalString(printer, getApplicationContext().getResources().getDrawableForDensity(R.drawable.logo, DisplayMetrics.DENSITY_MEDIUM)) + "\n" +
166 | "[L]\n" +
167 | "[C]ORDER N°045\n" +
168 | "[L]\n" +
169 | "[C]================================\n" +
170 | "[L]\n" +
171 | "[L]BEAUTIFUL SHIRT[R]9.99e\n" +
172 | "[L] + Size : S\n" +
173 | "[L]\n" +
174 | "[L]AWESOME HAT[R]24.99e\n" +
175 | "[L] + Size : 57/58\n" +
176 | "[L]\n" +
177 | "[C]--------------------------------\n" +
178 | "[R]TOTAL PRICE :[R]34.98e\n" +
179 | "[R]TAX :[R]4.23e\n" +
180 | "[L]\n" +
181 | "[C]================================\n" +
182 | "[L]\n" +
183 | "[L]Customer :\n" +
184 | "[L]Raymond DUPONT\n" +
185 | "[L]5 rue des girafes\n" +
186 | "[L]31547 PERPETES\n" +
187 | "[L]Tel : +33801201456\n" +
188 | "[L]\n" +
189 | "[C]831254784551\n" +
190 | "[C]https://dantsu.com/"
191 | );
192 | } catch (Exception e) {
193 | e.printStackTrace();
194 | }
195 | }
196 | }).start();
197 | ```
198 |
199 | ## USB
200 |
201 | ### USB permission
202 |
203 | Be sure to have `` in your `AndroidManifest.xml`.
204 |
205 | You have to check the USB permission in your app like this :
206 |
207 | ```java
208 | private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
209 | private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
210 | public void onReceive(Context context, Intent intent) {
211 | String action = intent.getAction();
212 | if (MainActivity.ACTION_USB_PERMISSION.equals(action)) {
213 | synchronized (this) {
214 | UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
215 | UsbDevice usbDevice = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
216 | if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
217 | if (usbManager != null && usbDevice != null) {
218 | // YOUR PRINT CODE HERE
219 | }
220 | }
221 | }
222 | }
223 | }
224 | };
225 |
226 | public void printUsb() {
227 | UsbConnection usbConnection = UsbPrintersConnections.selectFirstConnected(this);
228 | UsbManager usbManager = (UsbManager) this.getSystemService(Context.USB_SERVICE);
229 | if (usbConnection != null && usbManager != null) {
230 | PendingIntent permissionIntent = PendingIntent.getBroadcast(
231 | this,
232 | 0,
233 | new Intent(MainActivity.ACTION_USB_PERMISSION),
234 | android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S ? PendingIntent.FLAG_MUTABLE : 0
235 | );
236 | IntentFilter filter = new IntentFilter(MainActivity.ACTION_USB_PERMISSION);
237 | registerReceiver(this.usbReceiver, filter);
238 | usbManager.requestPermission(usbConnection.getDevice(), permissionIntent);
239 | }
240 | }
241 | ```
242 |
243 | ### USB code example
244 |
245 | The code below is an example to write in your activity :
246 |
247 | ```java
248 | EscPosPrinter printer = new EscPosPrinter(new UsbConnection(usbManager, usbDevice), 203, 48f, 32);
249 | printer
250 | .printFormattedText(
251 | "[C]
" + PrinterTextParserImg.bitmapToHexadecimalString(printer, this.getApplicationContext().getResources().getDrawableForDensity(R.drawable.logo, DisplayMetrics.DENSITY_MEDIUM))+"\n" +
252 | "[L]\n" +
253 | "[C]ORDER N°045\n" +
254 | "[L]\n" +
255 | "[C]================================\n" +
256 | "[L]\n" +
257 | "[L]BEAUTIFUL SHIRT[R]9.99e\n" +
258 | "[L] + Size : S\n" +
259 | "[L]\n" +
260 | "[L]AWESOME HAT[R]24.99e\n" +
261 | "[L] + Size : 57/58\n" +
262 | "[L]\n" +
263 | "[C]--------------------------------\n" +
264 | "[R]TOTAL PRICE :[R]34.98e\n" +
265 | "[R]TAX :[R]4.23e\n" +
266 | "[L]\n" +
267 | "[C]================================\n" +
268 | "[L]\n" +
269 | "[L]Customer :\n" +
270 | "[L]Raymond DUPONT\n" +
271 | "[L]5 rue des girafes\n" +
272 | "[L]31547 PERPETES\n" +
273 | "[L]Tel : +33801201456\n" +
274 | "[L]\n" +
275 | "[C]831254784551\n" +
276 | "[C]https://dantsu.com/"
277 | );
278 | ```
279 |
280 |
281 | ## Charset encoding
282 |
283 | To change charset encoding of the printer, use `EscPosCharsetEncoding` class :
284 |
285 | ```java
286 | EscPosPrinter printer = new EscPosPrinter(deviceConnection, 203, 48f, 32, new EscPosCharsetEncoding("windows-1252", 16));
287 | ```
288 |
289 | `escPosCharsetId` may change with printer model.
290 | [Follow this link to find `escPosCharsetId` that works with many printers](https://www.epson-biz.com/modules/ref_escpos/index.php?content_id=32)
291 |
292 | ## Formatted text : syntax guide
293 |
294 | ### New line
295 |
296 | Use `\n` to create a new line of text.
297 |
298 | ### Text alignment and column separation
299 |
300 | Add an alignment tag on a same line of text implicitly create a new column.
301 |
302 | Column alignment tags :
303 |
304 | - `[L]` : left side alignment
305 | - `[C]` : center alignment
306 | - `[R]` : right side alignment
307 |
308 | Example :
309 |
310 | - `[L]Some text` : One column aligned to left
311 | - `[C]Some text` : One column aligned to center
312 | - `[R]Some text` : One column aligned to right
313 | - `[L]Some text[L]Some other text` : Two columns aligned to left. `Some other text` starts in the center of the paper.
314 | - `[L]Some text[R]Some other text` : Two columns, first aligned to left, second aligned to right. `Some other text` is printed at the right of paper.
315 | - `[L]Some[R]text[R]here` : Three columns.
316 | - `[L][R]text[R]here` : Three columns. The first is empty but it takes a third of the available space.
317 |
318 | ### Font
319 |
320 | #### Size
321 |
322 | `` tag allows you to change the font size and color. Default size is `normal` / `black`.
323 |
324 | - `Some text` : Normal size
325 | - `Some text` : Double width of medium size
326 | - `Some text` : Double height of medium size
327 | - `Some text` : Double width and height of medium size
328 | - `Some text` : 3 x width and height
329 | - `Some text` : 4 x width and height
330 | - `Some text` : 5 x width and height
331 | - `Some text` : 6 x width and height
332 | - `Some text` : 7 x width and height
333 |
334 | - `Some text` : black text - white background
335 | - `Some text` : white text - black background
336 | - `Some text` : red text - white background (Not working on all printer)
337 | - `Some text` : white text - red background (Not working on all printer)
338 |
339 | #### Bold
340 |
341 | `` tag allows you to change the font weight.
342 |
343 | - `Some text`
344 |
345 | #### Underline
346 |
347 | `` tag allows you to underline the text.
348 |
349 | - `Some text` text underlined
350 | - `Some text` text double-strike (Not working on all printer)
351 |
352 | ### Image
353 |
354 | `
` tag allows you to print image. Inside the tag you need to write a hexadecimal string of an image.
355 |
356 | Use `PrinterTextParserImg.bitmapToHexadecimalString` to convert `Drawable`, `BitmapDrawable` or `Bitmap` to hexadecimal string.
357 |
358 | - `
`hexadecimal string of an image``
359 |
360 | **⚠ WARNING ⚠** : This tag has several constraints :
361 |
362 | - A line that contains `
` can have only one alignment tag and it must be at the beginning of the line.
363 | - `
` must be directly preceded by nothing or an alignment tag (`[L][C][R]`).
364 | - `` must be directly followed by a new line `\n`.
365 | - You can't write text on a line that contains `
`.
366 | - Maximum height of printed image is 256px, If you want to print larger bitmap. Please refer to this solution: [#70](https://github.com/DantSu/ESCPOS-ThermalPrinter-Android/issues/70#issuecomment-714390014)
367 |
368 | ### Barcode
369 |
370 | `` tag allows you to print a barcode. Inside the tag you need to write the code number to print.
371 |
372 | - `451278452159` : **(12 numbers)**
373 | Prints a EAN13 barcode (height: 10mm, width: ~70% printer width, text: displayed below).
374 | - `4512784` : **(7 numbers)**
375 | Prints a EAN8 barcode (height: 10mm, width: ~70% printer width, text: displayed below).
376 | - `4512784521` : **(11 numbers)**
377 | Prints a UPC-A barcode (height: 20mm, width: ~70% printer width, text: displayed below).
378 | - `512789` : **(6 numbers)**
379 | Prints a UPC-E barcode (height: 25mm, width: ~50mm, text: hidden).
380 | - `DantSu` : **(string)**
381 | Prints a barcode 128 (height: 10mm, width: ~40mm, text: displayed above).
382 |
383 | **⚠ WARNING ⚠** : This tag has several constraints :
384 |
385 | - A line that contains `` can have only one alignment tag and it must be at the beginning of the line.
386 | - `` must be directly preceded by nothing or an alignment tag (`[L][C][R]`).
387 | - `` must be directly followed by a new line `\n`.
388 | - You can't write text on a line that contains ``.
389 |
390 | ### QR Code
391 |
392 | `` tag allows you to print a QR code. Inside the tag you need to write the QR code data.
393 |
394 | - `https://dantsu.com/` :
395 | Prints a QR code with a width and height of 20 millimeters.
396 | - `123456789` :
397 | Prints a QR code with a width and height of 25 millimeters.
398 |
399 | **⚠ WARNING ⚠** : This tag has several constraints :
400 |
401 | - A line that contains `` can have only one alignment tag and it must be at the beginning of the line.
402 | - `` must be directly preceded by nothing or an alignment tag (`[L][C][R]`).
403 | - `` must be directly followed by a new line `\n`.
404 | - You can't write text on a line that contains ``.
405 |
406 | ## Class list
407 |
408 | ### Class : `com.dantsu.escposprinter.connection.bluetooth.BluetoothPrintersConnections`
409 |
410 | #### **Static** Method : `selectFirstPaired()`
411 | Easy way to get the first bluetooth printer paired / connected.
412 | - **return** `BluetoothConnection`
413 |
414 | #### Method : `getList()`
415 | Get a list of bluetooth printers.
416 | - **return** `BluetoothConnection[]`
417 |
418 | ⚠️ If the arrray returned by `getList()` does not contain you printer or if `selectFirstPaired()` does not return your printer. Read this issue : https://github.com/DantSu/ESCPOS-ThermalPrinter-Android/issues/80#issuecomment-729759832
419 |
420 | ### Class : `com.dantsu.escposprinter.connection.tcp.TcpConnection`
421 |
422 | #### Constructor : `TcpConnection(String address, int port[, int timeout])`
423 | - **param** `String address` : Targeted ip address
424 | - **param** `int port` : Targeted tcp port
425 | - **param** `int timeout` *(optional)* : Connection timeout (default : 30)
426 |
427 | ### Class : `com.dantsu.escposprinter.connection.usb.UsbPrintersConnections`
428 |
429 | #### **Static** Method : `selectFirstConnected()`
430 | Easy way to get the first USB printer connected.
431 | - **return** `UsbConnection`
432 |
433 | #### Method : `getList()`
434 | Get a list of USB printers.
435 | - **return** `UsbConnection[]`
436 |
437 | ### Class : `com.dantsu.escposprinter.EscPosPrinter`
438 |
439 | #### Constructor : `EscPosPrinter(DeviceConnection printer, int printerDpi, float printingWidthMM, int nbrCharactersPerLine [, EscPosCharsetEncoding charsetEncoding])`
440 | - **param** `DeviceConnection printer` : Instance of a connected printer
441 | - **param** `int printerDpi` : DPI of the connected printer
442 | - **param** `float printerWidthMM` : Printing width in millimeters
443 | - **param** `int printerNbrCharactersPerLine` : The maximum number of medium sized characters that can be printed on a line.
444 | - **param** `EscPosCharsetEncoding charsetEncoding` *(optional)* : Set the charset encoding.
445 |
446 | #### Method : `disconnectPrinter()`
447 | Close the connection with the printer.
448 | - **return** `Printer` : Fluent interface
449 |
450 | #### Method : `getNbrCharactersPerLine()`
451 | Get the maximum number of characters that can be printed on a line.
452 | - **return** `int`
453 |
454 | #### Method : `getPrinterWidthMM()`
455 | Get the printing width in millimeters
456 | - **return** `float`
457 |
458 | #### Method : `getPrinterDpi()`
459 | Get the printer DPI
460 | - **return** `int`
461 |
462 | #### Method : `getPrinterWidthPx()`
463 | Get the printing width in dot
464 | - **return** `int`
465 |
466 | #### Method : `getPrinterCharSizeWidthPx()`
467 | Get the number of dot that a printed character contain
468 | - **return** `int`
469 |
470 | #### Method : `mmToPx(float mmSize)`
471 | Convert the mmSize variable from millimeters to dot.
472 | - **param** `float mmSize` : Distance in millimeters to be converted
473 | - **return** `int` : Dot size of mmSize.
474 |
475 | #### Method : `useEscAsteriskCommand(boolean enable)`
476 | Active "ESC *" command for image printing.
477 | - **param** `boolean enable` : true to use "ESC *", false to use "GS v 0"
478 | - **return** `Printer` : Fluent interface
479 |
480 | #### Method : `printFormattedText(String text)`
481 | Print a formatted text and feed paper (20 millimeters). Read the ["Formatted Text : Syntax guide" section](#formatted-text--syntax-guide) for more information about text formatting options.
482 | - **param** `String text` : Formatted text to be printed.
483 | - **return** `Printer` : Fluent interface
484 |
485 | #### Method : `printFormattedTextAndCut(String text)`
486 | Print a formatted text, feed paper (20 millimeters) and cut the paper. Read the ["Formatted Text : Syntax guide" section](#formatted-text--syntax-guide) for more information about text formatting options.
487 | - **param** `String text` : Formatted text to be printed.
488 | - **return** `Printer` : Fluent interface
489 |
490 | #### Method : `printFormattedText(String text, float mmFeedPaper)`
491 | Print a formatted text and feed paper (`mmFeedPaper` millimeters). Read the ["Formatted Text : Syntax guide" section](#formatted-text--syntax-guide) for more information about text formatting options.
492 | - **param** `String text` : Formatted text to be printed.
493 | - **param** `float mmFeedPaper` : Millimeter distance feed paper at the end.
494 | - **return** `Printer` : Fluent interface
495 |
496 | #### Method : `printFormattedTextAndCut(String text, float mmFeedPaper)`
497 | Print a formatted text, feed paper (`mmFeedPaper` millimeters) and cut the paper. Read the ["Formatted Text : Syntax guide" section](#formatted-text--syntax-guide) for more information about text formatting options.
498 | - **param** `String text` : Formatted text to be printed.
499 | - **param** `float mmFeedPaper` : Millimeter distance feed paper at the end.
500 | - **return** `Printer` : Fluent interface
501 |
502 | #### Method : `printFormattedTextAndOpenCashBox(String text, float mmFeedPaper)`
503 | Print a formatted text, feed paper (`mmFeedPaper` millimeters), cut the paper and open the cash box. Read the ["Formatted Text : Syntax guide" section](#formatted-text--syntax-guide) for more information about text formatting options.
504 | - **param** `String text` : Formatted text to be printed.
505 | - **param** `float mmFeedPaper` : Millimeter distance feed paper at the end.
506 | - **return** `Printer` : Fluent interface
507 |
508 | #### Method : `printFormattedText(String text, int dotsFeedPaper)`
509 | Print a formatted text and feed paper (`dotsFeedPaper` dots). Read the ["Formatted Text : Syntax guide" section](#formatted-text--syntax-guide) for more information about text formatting options.
510 | - **param** `String text` : Formatted text to be printed.
511 | - **param** `int dotsFeedPaper` : Distance feed paper at the end.
512 | - **return** `Printer` : Fluent interface
513 |
514 | #### Method : `printFormattedTextAndCut(String text, int dotsFeedPaper)`
515 | Print a formatted text, feed paper (`dotsFeedPaper` dots) and cut the paper. Read the ["Formatted Text : Syntax guide" section](#formatted-text--syntax-guide) for more information about text formatting options.
516 | - **param** `String text` : Formatted text to be printed.
517 | - **param** `int dotsFeedPaper` : Distance feed paper at the end.
518 | - **return** `Printer` : Fluent interface
519 |
520 | #### Method : `printFormattedTextAndOpenCashBox(String text, int dotsFeedPaper)`
521 | Print a formatted text, feed paper (`dotsFeedPaper` dots), cut the paper and open the cash box. Read the ["Formatted Text : Syntax guide" section](#formatted-text--syntax-guide) for more information about text formatting options.
522 | - **param** `String text` : Formatted text to be printed.
523 | - **param** `int dotsFeedPaper` : Distance feed paper at the end.
524 | - **return** `Printer` : Fluent interface
525 |
526 | #### Method : `bitmapToBytes(Bitmap bitmap, boolean gradient)`
527 | Convert Bitmap object to ESC/POS image.
528 | - **param** `Bitmap bitmap` : Instance of Bitmap
529 | - **param** `boolean gradient` : `false` Black and white image, `true` Grayscale image
530 | - **return** `byte[]` : Bytes contain the image in ESC/POS command
531 |
532 | ### Class : `com.dantsu.escposprinter.textparser.PrinterTextParserImg`
533 |
534 | #### **Static** Method : `bitmapToHexadecimalString(Printer printer, Drawable drawable [, boolean gradient])`
535 | Convert Drawable instance to a hexadecimal string of the image data.
536 | - **param** `Printer printer` : A Printer instance that will print the image.
537 | - **param** `Drawable drawable` : Drawable instance to be converted.
538 | - **param** `boolean gradient` *(optional)* : `false` Black and white image, `true` Grayscale image (Default : `true`)
539 | - **return** `String` : A hexadecimal string of the image data. Empty string if Drawable cannot be cast to BitmapDrawable.
540 |
541 | #### **Static** Method : `bitmapToHexadecimalString(Printer printer, BitmapDrawable bitmapDrawable [, boolean gradient])`
542 | Convert BitmapDrawable instance to a hexadecimal string of the image data.
543 | - **param** `Printer printer` : A Printer instance that will print the image.
544 | - **param** `BitmapDrawable bitmapDrawable` : BitmapDrawable instance to be converted.
545 | - **param** `boolean gradient` *(optional)* : `false` Black and white image, `true` Grayscale image (Default : `true`)
546 | - **return** `String` : A hexadecimal string of the image data.
547 |
548 | #### **Static** Method : `bitmapToHexadecimalString(Printer printer, Bitmap bitmap [, boolean gradient])`
549 | Convert Bitmap instance to a hexadecimal string of the image data.
550 | - **param** `Printer printer` : A Printer instance that will print the image.
551 | - **param** `Bitmap bitmap` : Bitmap instance to be converted.
552 | - **param** `boolean gradient` *(optional)* : `false` Black and white image, `true` Grayscale image (Default : `true`)
553 | - **return** `String` : A hexadecimal string of the image data.
554 |
555 | #### **Static** Method : `bytesToHexadecimalString(byte[] bytes)`
556 | Convert byte array to a hexadecimal string of the image data.
557 | - **param** `byte[] bytes` : Bytes contain the image in ESC/POS command.
558 | - **return** `String` : A hexadecimal string of the image data.
559 |
560 | #### **Static** Method : `hexadecimalStringToBytes(String hexString)`
561 | Convert hexadecimal string of the image data to bytes ESC/POS command.
562 | - **param** `String hexString` : Hexadecimal string of the image data.
563 | - **return** `byte[]` : Bytes contain the image in ESC/POS command.
564 |
565 | ### Class : `com.dantsu.escposprinter.EscPosCharsetEncoding`
566 |
567 | #### Constructor : `EscPosCharsetEncoding(String charsetName, int escPosCharsetId)`
568 | - **param** `charsetName` Name of charset encoding (Ex: ISO-8859-1)
569 | - **param** `escPosCharsetId` Id of charset encoding for your printer (Ex: 6)
570 |
571 | ## Projects using this library
572 |
573 | - [AllInOneYT/react-native-thermal-printer : A React Native bridge](https://github.com/AllInOneYT/react-native-thermal-printer)
574 | - [paystory-de/thermal-printer-cordova-plugin : A Cordova / Ionic bridge](https://github.com/paystory-de/thermal-printer-cordova-plugin)
575 | - [asukiaaa/react-native-escpos-android : A React Native bridge](https://github.com/asukiaaa/react-native-escpos-android)
576 | - [android_bluetooth_printer : A Flutter bridge](https://pub.dev/packages/android_bluetooth_printer)
577 |
578 | ## Contributing
579 |
580 | Please fork this repository and contribute back using pull requests.
581 |
582 | Any contributions, large or small, major features, bug fixes, are welcomed and appreciated but will be thoroughly reviewed
583 |
--------------------------------------------------------------------------------