Reputation: 7343
I have an application that prints data (text and image) to a thermal printer.
My problem is that whenever I print lengthy data, the printout gets cut and and I get an IOException: Socket Closed
thrown in the try catch statement where I print.
Here is the part where I print my data:
protected void simpleComm(Integer port){
//InputStream tmpIn = null;
byte[] buffer = new byte[3]; //{65,65,53,53,49,52,65,66,67,68};
buffer[0] = (byte) 0x08;
buffer[1] = (byte) 0x99;
buffer[2] = (byte) 0x04;
OutputStream tmpOut;// = null;
bluetoothAdapter.cancelDiscovery();
Log.d(this.toString(), "Port = " + port);
try {
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
Method m = blueToothDevice.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
socket = (BluetoothSocket) m.invoke(blueToothDevice, port);
//socket = mmDevice.createRfcommSocketToServiceRecord(uuid);
// assert (socket != null) : "Socket is Null";
socket.connect();
try {
Log.d(this.toString(),"************ CONNECTION SUCCEES! *************");
try{
//tmpIn=socket.getInputStream();
tmpOut = socket.getOutputStream();
//mmInStream = tmpIn;
mmOutStream = tmpOut;
}
catch(Exception ex){
Log.e(this.toString(), "Exception " + ex.getMessage());
}
//TODO print sequence starts here
image = "logo";
print_image(Environment.getExternalStorageDirectory().toString() + "/LOGO.png");
byte[] arrayOfByte1 = { 27, 33, 0 };
byte[] format = { 27, 33, 0 };
mmOutStream.write((newline).getBytes("US-ASCII"));
//bold
format[2] = ((byte)(0x0 | arrayOfByte1[2]));
//width
format[2] = ((byte)(0x12 | arrayOfByte1[2]));
//height
format[2] = ((byte)(0x8 | arrayOfByte1[2]));
mmOutStream.write(format);
for(int i = 0 ; i < orderListForPrinting.size(); i++ ){
mmOutStream.write(((List.get(i)).getBytes("US-ASCII")));
}
//bold
format[2] = ((byte)(0x8 | arrayOfByte1[2]));
//width
format[2] = ((byte)(0x8 | arrayOfByte1[2]));
//height
format[2] = ((byte)(0x8 | arrayOfByte1[2]));
mmOutStream.write(format);
mmOutStream.write((newline).getBytes("US-ASCII"));
printSignature();
//bold
format[2] = ((byte)(0x8 | arrayOfByte1[2]));
//width
format[2] = ((byte)(0x8 | arrayOfByte1[2]));
//height
format[2] = ((byte)(0x8 | arrayOfByte1[2]));
mmOutStream.write(format);
mmOutStream.write(( name + " " + newline + newline).getBytes("US-ASCII"));
}
finally{
orderList = new ArrayList<TotalOrderClass>();
orderListForPrinting = new ArrayList<String>();
socket.close();
mmOutStream.flush();
}
}
catch (IOException ex){
Log.e(this.toString(), "IOException: " + ex.getMessage());
}
catch (NoSuchMethodException ex){
Log.e(this.toString(), "NoSuchMethodException: " + ex.getMessage());
}
catch (IllegalAccessException ex){
Log.e(this.toString(), "IllegalAccessException: " + ex.getMessage());
}
catch (InvocationTargetException ex){
Log.e(this.toString(),"InvocationTargetException: " + ex.getMessage());
}
}
Here is my print Signature function, which is similar to the function I use to print the logo.
private void printSignature() {
//TODO print signature here
convertBitmap(signature);
try{
mmOutStream.write(PrinterCommands.SET_LINE_SPACING_24);
int offset = 0;
while (offset < signature.getHeight()) {
mmOutStream.write(PrinterCommands.SELECT_BIT_IMAGE_MODE_SIGNATURE);
for (int x = 0; x < signature.getWidth(); ++x) {
for (int k = 0; k < 3; ++k) {
byte slice = 0;
for (int b = 0; b < 8; ++b) {
int y = (((offset / 8) + k) * 8) + b;
int i = (y * signature.getWidth()) + x;
boolean v = false;
if (i < dots.length()) {
v = dots.get(i);
}
slice |= (byte) ((v ? 1 : 0) << (7 - b));
}
mmOutStream.write(slice);
}
}
offset += 24;
mmOutStream.write(PrinterCommands.FEED_LINE);
}
mmOutStream.write(PrinterCommands.SET_LINE_SPACING_30);
}
catch (IOException e) {
Toast.makeText(getApplicationContext(), "Catch on to print signature stuff", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
ConvertBitmap function:
public String convertBitmap(Bitmap inputBitmap) {
int mWidth = inputBitmap.getWidth();
int mHeight = inputBitmap.getHeight();
convertArgbToGrayscale(inputBitmap, mWidth, mHeight);
String mStatus = "ok";
return mStatus;
}
convertArgbToGrayScale function:
private void convertArgbToGrayscale(Bitmap bmpOriginal, int width,
int height) {
int pixel;
int k = 0;
int B = 0, G = 0, R = 0;
dots = new BitSet();
try {
for (int x = 0; x < height; x++) {
for (int y = 0; y < width; y++) {
// get one pixel color
pixel = bmpOriginal.getPixel(y, x);
// retrieve color of all channels
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
// take conversion up to one single value by calculating
// pixel intensity.
R = G = B = (int) (0.299 * R + 0.587 * G + 0.114 * B);
// set bit into bitset, by calculating the pixel's luma
if (R < 55) {
dots.set(k);//this is the bitset that i'm printing
}
k++;
}
}
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "Catch on to Grayscale stuff", Toast.LENGTH_LONG).show();
}
}
My issue right now is that after calling the printSignature() function, the printer stops printing and the socket is closed, which is why I am getting the IOException: Socket Closed error.
I've run through this functions a handful of times and I don't know why the socket is closing since I only close the socket at the finally clause of the try-catch.
Any ideas?
Upvotes: 0
Views: 2735
Reputation: 13
What I do, is that I put a Thread.sleep(x)
, after every .Write()
, where x, is the amount of characters in my output string, that can differ in your code, but the amount of waiting that the program has to do before closing, is proportional, to the amount of chars (or lines) printing.
Upvotes: 0
Reputation: 682
What happpend if you put a Thread.sleep(2000)
right before the socket.close()
?
I work on bluetooth SPP and I had the same issue (Socket close before the end of data transfer). I think that the broadcast of socket.close()
is faster than the transmission of the data, then all the data are not analyze by the BT printer when the close request is send
Upvotes: 2