Skip to content

Instantly share code, notes, and snippets.

@putraxor
Created September 15, 2017 06:43
Show Gist options
  • Save putraxor/cc16afd6be8650995dc34c4ead2f4d35 to your computer and use it in GitHub Desktop.
Save putraxor/cc16afd6be8650995dc34c4ead2f4d35 to your computer and use it in GitHub Desktop.
Utilitas untuk printer thermal bluetooth
package id.bitcase.ocafe.utility;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.util.Log;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
/**
* Utilitas untuk printer thermal bluetooth
* Created by putraxor on 05/07/17.
* <p>
* Penggunaan:
* BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
* BluetoothDevice mBtDevice = btAdapter.getBondedDevices().iterator().next(); // Get first paired device
* <p>
* final BluetoothPrinter mPrinter = new BluetoothPrinter(mBtDevice);
* mPrinter.connectPrinter(new BluetoothPrinter.PrinterConnectListener() {
*
* @Override public void onConnected() {
* mPrinter.setAlign(BluetoothPrinter.ALIGN_CENTER);
* mPrinter.printText("Hello World!");
* mPrinter.addNewLine();
* <p>
* mPrinter.finish();
* }
* @Overide public void onFailed() {
* Log.d("BluetoothPrinter", "Conection failed");
* }
* <p>
* });
* <p>
*/
public class BluetoothPrinter {
private String TAG = BluetoothPrinter.class.getName();
public static final int ALIGN_CENTER = 100;
public static final int ALIGN_RIGHT = 101;
public static final int ALIGN_LEFT = 102;
private static final byte[] NEW_LINE = {10};
private static final byte[] ESC_ALIGN_CENTER = new byte[]{0x1b, 'a', 0x01};
private static final byte[] ESC_ALIGN_RIGHT = new byte[]{0x1b, 'a', 0x02};
private static final byte[] ESC_ALIGN_LEFT = new byte[]{0x1b, 'a', 0x00};
private BluetoothDevice printer;
private BluetoothSocket btSocket = null;
private OutputStream btOutputStream = null;
public BluetoothPrinter() {
}
public BluetoothPrinter(BluetoothDevice printer) {
this.printer = printer;
}
/**
* Koneksikan ke perangkat printer bluetooth
*
* @param listener PrinterConnectionListener
*/
public void connectPrinter(final PrinterConnectListener listener) {
new ConnectTask(new ConnectTask.BtConnectListener() {
@Override
public void onConnected(BluetoothSocket socket) {
btSocket = socket;
try {
btOutputStream = socket.getOutputStream();
listener.onConnected();
} catch (IOException e) {
listener.onFailed();
}
}
@Override
public void onFailed() {
listener.onFailed();
}
}).execute(printer);
}
/**
* Cek apakah perangkat sedang terhubung
*
* @return status koneksi boolean
*/
public boolean isConnected() {
return btSocket != null && btSocket.isConnected();
}
public void finish() {
if (btSocket != null) {
try {
Thread.sleep(2000);
btOutputStream.close();
btSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
btSocket = null;
}
}
/**
* Cetak teks ke printer
*
* @param text paymentSuggestion
* @return status berhasil atau gagal: boolean
*/
public boolean printText(String text) {
try {
btOutputStream.write(encodeNonAscii(text).getBytes());
Thread.sleep(80);
return true;
} catch (Exception e) {
Log.e(TAG, "Print text error", e);
return false;
}
}
/**
* Fungsi untuk membuka cash drawer dengan ESC/POS command
* Lihat: http://keyhut.com/popopen.htm
*
* @return open status
*/
public boolean openCashDrawer() {
try {
byte[] bytes = intArrayToByteArray(new int[]{27, 112, 0, 50, 250});
btOutputStream.write(bytes);
return true;
} catch (IOException e) {
Log.e(TAG, "Open drawer error", e);
return false;
}
}
private byte[] intArrayToByteArray(int[] Iarr) {
byte[] bytes = new byte[Iarr.length];
for (int i = 0; i < Iarr.length; i++) {
bytes[i] = (byte) (Iarr[i] & 0xFF);
}
return bytes;
}
/**
* Cetak kode unicode
*
* @param data byte array
* @return status berhasil atau gagal: boolean
*/
public boolean printUnicode(byte[] data) {
try {
btOutputStream.write(data);
Thread.sleep(50);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* Cetak baris ke printer
*
* @return status berhasil atau gagal: boolean
*/
public boolean printLine() {
return printText("________________________________");
}
public boolean addNewLine() {
return printUnicode(NEW_LINE);
}
public int addNewLines(int count) {
int success = 0;
for (int i = 0; i < count; i++) {
if (addNewLine()) success++;
}
return success;
}
/**
* Cetak gambar ke kertas thermal
*
* @param bitmap
* @return
*/
public boolean printImage(Bitmap bitmap) {
byte[] command = decodeBitmap(bitmap);
return printUnicode(command);
}
/**
* Atur perataan teks
*
* @param alignType
*/
public void setAlign(int alignType) {
byte[] d;
switch (alignType) {
case ALIGN_CENTER:
d = ESC_ALIGN_CENTER;
break;
case ALIGN_LEFT:
d = ESC_ALIGN_LEFT;
break;
case ALIGN_RIGHT:
d = ESC_ALIGN_RIGHT;
break;
default:
d = ESC_ALIGN_LEFT;
break;
}
try {
btOutputStream.write(d);
} catch (IOException e) {
e.printStackTrace();
}
}
public void setLineSpacing(int lineSpacing) {
byte[] cmd = new byte[]{0x1B, 0x33, (byte) lineSpacing};
printUnicode(cmd);
}
public void setBold(boolean bold) {
byte[] cmd = new byte[]{0x1B, 0x45, bold ? (byte) 1 : 0};
printUnicode(cmd);
}
/**
* Feeding kertas 3 baris
*/
public void feedPaper() {
addNewLine();
addNewLine();
addNewLine();
//addNewLine();
}
private static class ConnectTask extends AsyncTask<BluetoothDevice, Void, BluetoothSocket> {
private BtConnectListener listener;
private ConnectTask(BtConnectListener listener) {
this.listener = listener;
}
@Override
protected BluetoothSocket doInBackground(BluetoothDevice... bluetoothDevices) {
BluetoothDevice device = bluetoothDevices[0];
UUID uuid = device.getUuids()[0].getUuid();
BluetoothSocket socket = null;
boolean connected = true;
try {
socket = device.createRfcommSocketToServiceRecord(uuid);
} catch (IOException e) {
Log.e(getClass().getName(), "Gagal menghubungkan socket", e);
}
try {
socket.connect();
} catch (IOException e) {
try {
socket = (BluetoothSocket) device.getClass().getMethod("createRfcommSocket", new Class[]{int.class})
.invoke(device, 1);
socket.connect();
} catch (Exception e2) {
connected = false;
}
}
return connected ? socket : null;
}
@Override
protected void onPostExecute(BluetoothSocket bluetoothSocket) {
if (listener != null) {
if (bluetoothSocket != null) listener.onConnected(bluetoothSocket);
else listener.onFailed();
}
}
private interface BtConnectListener {
void onConnected(BluetoothSocket socket);
void onFailed();
}
}
public interface PrinterConnectListener {
void onConnected();
void onFailed();
}
private static String encodeNonAscii(String text) {
return text.replace('á', 'a')
.replace('č', 'c')
.replace('ď', 'd')
.replace('é', 'e')
.replace('ě', 'e')
.replace('í', 'i')
.replace('ň', 'n')
.replace('ó', 'o')
.replace('ř', 'r')
.replace('š', 's')
.replace('ť', 't')
.replace('ú', 'u')
.replace('ů', 'u')
.replace('ý', 'y')
.replace('ž', 'z')
.replace('Á', 'A')
.replace('Č', 'C')
.replace('Ď', 'D')
.replace('É', 'E')
.replace('Ě', 'E')
.replace('Í', 'I')
.replace('Ň', 'N')
.replace('Ó', 'O')
.replace('Ř', 'R')
.replace('Š', 'S')
.replace('Ť', 'T')
.replace('Ú', 'U')
.replace('Ů', 'U')
.replace('Ý', 'Y')
.replace('Ž', 'Z');
}
public static byte[] decodeBitmap(Bitmap bmp) {
int bmpWidth = bmp.getWidth();
int bmpHeight = bmp.getHeight();
List<String> list = new ArrayList<>();
StringBuffer sb;
int zeroCount = bmpWidth % 8;
String zeroStr = "";
if (zeroCount > 0) {
for (int i = 0; i < (8 - zeroCount); i++) zeroStr = zeroStr + "0";
}
for (int i = 0; i < bmpHeight; i++) {
sb = new StringBuffer();
for (int j = 0; j < bmpWidth; j++) {
int color = bmp.getPixel(j, i);
int r = (color >> 16) & 0xff;
int g = (color >> 8) & 0xff;
int b = color & 0xff;
if (r > 160 && g > 160 && b > 160) sb.append("0");
else sb.append("1");
}
if (zeroCount > 0) sb.append(zeroStr);
list.add(sb.toString());
}
List<String> bmpHexList = binaryListToHexStringList(list);
String commandHexString = "1D763000";
String widthHexString = Integer
.toHexString(bmpWidth % 8 == 0 ? bmpWidth / 8 : (bmpWidth / 8 + 1));
if (widthHexString.length() > 2) {
return null;
} else if (widthHexString.length() == 1) {
widthHexString = "0" + widthHexString;
}
widthHexString = widthHexString + "00";
String heightHexString = Integer.toHexString(bmpHeight);
if (heightHexString.length() > 2) {
return null;
} else if (heightHexString.length() == 1) {
heightHexString = "0" + heightHexString;
}
heightHexString = heightHexString + "00";
List<String> commandList = new ArrayList<>();
commandList.add(commandHexString + widthHexString + heightHexString);
commandList.addAll(bmpHexList);
return hexList2Byte(commandList);
}
private static List<String> binaryListToHexStringList(List<String> list) {
List<String> hexList = new ArrayList<>();
for (String binaryStr : list) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < binaryStr.length(); i += 8) {
String str = binaryStr.substring(i, i + 8);
String hexString = strToHexString(str);
sb.append(hexString);
}
hexList.add(sb.toString());
}
return hexList;
}
private static String hexStr = "0123456789ABCDEF";
private static String[] binaryArray = {"0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111"};
private static String strToHexString(String binaryStr) {
String hex = "";
String f4 = binaryStr.substring(0, 4);
String b4 = binaryStr.substring(4, 8);
for (int i = 0; i < binaryArray.length; i++) {
if (f4.equals(binaryArray[i]))
hex += hexStr.substring(i, i + 1);
}
for (int i = 0; i < binaryArray.length; i++) {
if (b4.equals(binaryArray[i]))
hex += hexStr.substring(i, i + 1);
}
return hex;
}
private static byte[] hexList2Byte(List<String> list) {
List<byte[]> commandList = new ArrayList<>();
for (String hexStr : list) commandList.add(hexStringToBytes(hexStr));
return sysCopy(commandList);
}
private static byte[] hexStringToBytes(String hexString) {
if (hexString == null || hexString.equals("")) return null;
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
private static byte[] sysCopy(List<byte[]> srcArrays) {
int len = 0;
for (byte[] srcArray : srcArrays) {
len += srcArray.length;
}
byte[] destArray = new byte[len];
int destLen = 0;
for (byte[] srcArray : srcArrays) {
System.arraycopy(srcArray, 0, destArray, destLen, srcArray.length);
destLen += srcArray.length;
}
return destArray;
}
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
public BluetoothSocket getSocket() {
return btSocket;
}
public BluetoothDevice getDevice() {
return printer;
}
public Set<BluetoothDevice> getDevices() {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter != null) {
return adapter.getBondedDevices();
}
return null;
}
public void setDevice(BluetoothDevice device) {
this.printer = device;
}
}
@ExcaCambo
Copy link

Hi, sir. What is 'String commandHexString = "1D763000";' meant ?

@ExcaCambo
Copy link

How to calculate value "1D763000"?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment