Hello I am new to android I have spent so much time on trying to print a receipt in my app. I use a Zicox XT4131 thermal printer which connects via bluetooth to my tablet running the Android 4.4 OS.
SO far I have successfully been able to print only text on my receipt, now my next hurdle is trying to print barcodes, qrcodes and logos on my receipt, I have spent many hours on the internet trying to find a solution for this but nothing seems to work.
What I have learned however is that to print a bitmap image, i first need to convert it to a byte array (which I did) and write it to the output stream (which I also did), all I got after that was either a long blank space on the printer or some weird characters.
Right now I'm refusing to believe in 2016 printing from a tablet to a printer has no simple solution so I only assume I am going about all this the wrong way.
The way my app works is simple, in my activity where I have a preview of the purchase there is a button which upon being clicked sends a command to the bluetooth printer to print. That is all, no converting to pdf and what not and having to select a printer.
So what I would like to know is what exactly is the way for me to correctly print a receipt from my tablet to my bluetooth printer and how exactly would I use such method to print a barcode, qrcode or logo along with the text on the receipt?
I do not want this to be voted as off topic as that may require me abandon this project (all because of printing) I just want one workable efficient solution that can help me do what I want to do.
This is my code for printing right now:
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Handler;
import android.view.View;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.EnumMap;
import java.util.GregorianCalendar;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
These are the functions for it:
// this will find a bluetooth printer device
void findBT() {
try {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if(mBluetoothAdapter == null) {
Toast.makeText(PurchaseSummaryActivity.this, "No bluetooth adapter available", Toast.LENGTH_SHORT).show();
}
if(!mBluetoothAdapter.isEnabled()) {
Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBluetooth, 0);
}
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if(pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
// RPP300 is the name of the bluetooth printer device
// we got this name from the list of paired devices
if (device.getName().equals("XT4131A")) {
mDevice = device;
break;
}
}
}
Toast.makeText(PurchaseSummaryActivity.this, "Bluetooth device found.", Toast.LENGTH_SHORT).show();
}catch(Exception e){
e.printStackTrace();
}
}
// tries to open a connection to the bluetooth printer device
void openBT() throws IOException {
try {
// Standard SerialPortService ID
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
mSocket = mDevice.createRfcommSocketToServiceRecord(uuid);
mSocket.connect();
mOutputStream = mSocket.getOutputStream();
mInputStream = mSocket.getInputStream();
beginListenForData();
Toast.makeText(PurchaseSummaryActivity.this, "Bluetooth Connection Opened", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* after opening a connection to bluetooth printer device,
* we have to listen and check if a data were sent to be printed.
*/
void beginListenForData() {
try {
final Handler handler = new Handler();
// this is the ASCII code for a newline character
final byte delimiter = 10;
stopWorker = false;
readBufferPosition = 0;
readBuffer = new byte[1024];
workerThread = new Thread(new Runnable() {
public void run() {
while (!Thread.currentThread().isInterrupted() && !stopWorker) {
try {
int bytesAvailable = mInputStream.available();
if (bytesAvailable > 0) {
byte[] packetBytes = new byte[bytesAvailable];
mInputStream.read(packetBytes);
for (int i = 0; i < bytesAvailable; i++) {
byte b = packetBytes[i];
if (b == delimiter) {
byte[] encodedBytes = new byte[readBufferPosition];
System.arraycopy(
readBuffer, 0,
encodedBytes, 0,
encodedBytes.length
);
// specify US-ASCII encoding
final String data = new String(encodedBytes, "US-ASCII");
readBufferPosition = 0;
// tell the user data were sent to bluetooth printer device
handler.post(new Runnable() {
public void run() {
Toast.makeText(PurchaseSummaryActivity.this, data, Toast.LENGTH_SHORT).show();
}
});
} else {
readBuffer[readBufferPosition++] = b;
}
}
}
} catch (IOException ex) {
stopWorker = true;
}
}
}
});
workerThread.start();
} catch (Exception e) {
e.printStackTrace();
}
}
// this will send text data to be printed by the bluetooth printer
void printTickets(Event eo, Cart.Ticket to) throws IOException {
try {
byte[] arrayOfByte1 = { 27, 33, 0 };
byte[] format = { 27, 33, 0 };
// Bold
format[2] = ((byte)(0x8 | arrayOfByte1[2]));
// Height
format[2] = ((byte)(0x10 | arrayOfByte1[2]));
// Width
format[2] = ((byte) (0x20 | arrayOfByte1[2]));
byte[] center = new byte[]{ 0x1b, 0x61, 0x01 };
// the text typed by the user
StringBuilder msg = new StringBuilder();
msg.append("\n");
msg.append("\n");
msg.append("\n myTicketGH");
mOutputStream.write(center);
mOutputStream.write(format);
mOutputStream.write(msg.toString().getBytes());
// Bold
format[2] = ((byte)(0x8 | arrayOfByte1[2]));
msg = new StringBuilder();
msg.append("\n Address: No 10, Otublohum street");
msg.append("\n North Industrial Area");
msg.append("\n Tel.: 0266 8888 64");
msg.append("\n");
msg.append("\n");
msg.append("\n");
mOutputStream.write(center);
mOutputStream.write(format);
mOutputStream.write(msg.toString().getBytes());
// Bold
format[2] = ((byte)(0x8 | arrayOfByte1[2]));
byte[] left = new byte[]{ 0x1b, 0x61, 0x00 };
msg = new StringBuilder();
msg.append("\n Event");
mOutputStream.write(format);
mOutputStream.write(left);
mOutputStream.write(msg.toString().getBytes());
mOutputStream.write(arrayOfByte1);
left = new byte[]{ 0x1b, 0x61, 0x00 };
msg = new StringBuilder();
msg.append("\n Name : " + eo.getName());
msg.append("\n Date : " + eo.getDate());
msg.append("\n Time : " + eo.getTime());
msg.append("\n Venue : " + eo.getVenue());
msg.append("\n");
msg.append("\n");
mOutputStream.write(arrayOfByte1);
mOutputStream.write(left);
mOutputStream.write(msg.toString().getBytes());
// Bold
format[2] = ((byte)(0x8 | arrayOfByte1[2]));
msg = new StringBuilder();
msg.append("\n Ticket");
mOutputStream.write(format);
mOutputStream.write(left);
mOutputStream.write(msg.toString().getBytes());
mOutputStream.write(arrayOfByte1);
left = new byte[]{ 0x1b, 0x61, 0x00 };
msg = new StringBuilder();
msg.append("\n Code : " + to.getCode());
msg.append("\n Class : " + to.getTclass() );
msg.append("\n Fee : " + to.getPrice());
msg.append("\n Seat : " + "N / A");
msg.append("\n Date of Purchase : " + Calendar.getInstance().getTime().toString());
msg.append("\n");
msg.append("\n");
msg.append("\n");
msg.append("\n");
msg.append("\n");
mOutputStream.write(arrayOfByte1);
mOutputStream.write(left);
mOutputStream.write(msg.toString().getBytes());
// barcode data
String barcode_data = "123456";
// barcode image
byte[] barCodeBytes;
String barCodeHex = "";
try {
barCode = encodeAsBitmap(barcode_data, BarcodeFormat.CODE_128, 300, 40);
barCode = bitmapToGrayscale(barCode);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
barCodeBytes = stream.toByteArray();
mOutputStream.write(barCodeBytes);
} catch (WriterException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
// close the connection to bluetooth printer.
void closeBT() throws IOException {
try {
stopWorker = true;
mOutputStream.close();
mInputStream.close();
mSocket.close();
// myLabel.setText("Bluetooth Closed");
} catch (Exception e) {
e.printStackTrace();
}
}
This is my onClickEvent handler:
this.buttonNextView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
findBT();
openBT();
for (int i = 0; i < ta.length(); i++)
{
try {
printTickets(eo, new Cart(). new Ticket(
ta.getJSONObject(i).getInt("id"),
ta.getJSONObject(i).getString("code"),
ta.getJSONObject(i).getString("class"),
ta.getJSONObject(i).getString("description"),
Float.parseFloat(ta.getJSONObject(i).getString("price")),
ta.getJSONObject(i).getInt("quantity")
));
} catch (JSONException e) {
e.printStackTrace();
}
}
closeBT();
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
And yes the printer I use is capable of printing barcodes and qr codes.