Bluetooth printing throws an IOException from the Socket across different devices - java

I am trying to print to a thermal printer via Bluetooth.
I was able to successfully print before on a Nexus 7 Device (both the first and second generations). However, when I copy pasted the exact same code on a different application and deployed it on an Asus Tablet, I suddenly got an IOException that tells me that my socket might be closed.
Here is my code:
public void onPrintReceipt(){
Toast.makeText(getApplicationContext(), "Printing", Toast.LENGTH_LONG).show();
try{
Set<BluetoothDevice> bdevices = bluetoothAdapter.getBondedDevices();
blueToothDevice = bluetoothAdapter.getRemoteDevice("00:01:90:EE:B2:52");
simpleComm(1);
}
catch(Exception ex){
Log.e("", "simpleComm() Catch Statement Entered");
}
}
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.e(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);
// assert (socket != null) : "Socket is Null";
if(socket.isConnected()){
socket.close();
}
socket.connect();
try {
Log.e(this.toString(), "************ CONNECTION SUCCEES! *************");
try{
//tmpIn=socket.getInputStream();
tmpOut = socket.getOutputStream();
//mmInStream = tmpIn;
mmOutStream = tmpOut;
out = new BufferedWriter(new OutputStreamWriter(mmOutStream));
}
catch(Exception ex){
Log.e(this.toString(), "Exception " + ex.getMessage());
}
//TODO print sequence starts here
//....snip snip a LOT of code
}
finally{
mmOutStream.flush();
mmOutStream.close();
socket.close();
}
}
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());
}
}
And here is the error from the try-catch block:
IOException: read failed, socket might closed or timeout, read ret: -1
And now I am confused as to why there's suddenly an error when all I did was to deploy the code on a different device.
How can I proceed?

I see you use reflection to create your RFCOMM connection. This is pretty dangerous, I recently answered a question in that regard: How do Bluetooth SDP and UUIDs work? (specifically for Android)
Tl;dr: You are bypassing the SDP lookup mechanism that maps an UUID to an appropriate Bluetooth channel on the device you connect to. Your code ALWAYS connects to bluetooth channel 1. That might work initially/some cases - but could also be your problem. It depends on the receiving device.
You are creating an UUID. I guess (hope) you have it from the printer's documentation? But if you check your code, you will see that you are not using it to connect to the printer - which you absolutely should do (refer to the linked answer, for the whole story). Use createRfcommSocketToServiceRecord(uuid) to open your socket.
Since you are using the Nexus 7: I used two Nexus 7, a Nexus 4 and 10 other devices to test a bluetooth middleware for android I wrote. Especially the Nexus devices were pretty sensitive when the bluetooth was stressed by many concurrent calls leading to a completely useless bluetooth adapter until I power cycled them. Additionally I think to remember there was a bug in cases when I used this hacky reflection snippet that filled up the bt-adapter's channels until no one was left resulting in total bluetooth failure (I wasn't able to find the link to the related official android bug report, but there is one for the Nexus devices).

Related

creating a delay until a certain number of messages have been received

I am using socket protocol to send messages between a server program and some client programs
I wish to add code to the server program such that it waits until it has received a certain number of messages (namely, one from each client) before it proceeds
How do I code this?
some client code:-
String message_string = Integer.toString(message_code);
// send details of prospective trade to the Server
try {
InetAddress host = InetAddress.getLocalHost();
Socket socket = new Socket(host.getHostName(), 7001);
ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
outputStream.writeObject(name + " " + message_string);
ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
String message = (String) inputStream.readObject();
myConsole.getOut().println("Message: " + message);
inputStream.close();
outputStream.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// now wait until the list of optimized trades is received back from the Server
I can see the various clients' messages arriving at the server.
Once the number of messages reaches a certain number (i.e. no. of clients) I wish the server code to continue BUT if not I wish the server to 'wait'
Just to be clear
The server receives a prospective trade from each client
Once all prospective trades are in, the server does some calculations and then returns the list of optimized trades to all clients
So, I actually have two 'wait' periods required
One with the server, and one with each client

Bluetooth Connectivity Issues in Post ICS Versions

I am able to connect to an external paired bluetooth hardware first time. After that if i repeat connect/disconect procedures sometimes getting exception.
Exception = read failed, socket might closed or timeout, read ret: -1
and after many trials able to connect again.Sometimes second trial itself is successful
The issue is observed with Devices:Nexux7(version 4.3) and MotoG(Kitkat)
Code for connection:
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(devAddress);
socket = device.createRfcommSocketToServiceRecord(MY_UUID);
and calling socket.connect() from asynctask
Code for closing socket:Subject
if (in != null) {
Logger.loge(CLASS_NAME + "." + "resetConnection", "in != null");
try {
in.close();
} catch (Exception e) {
// Log.d(TAG,"exception in closing inputstream - " + e.getMessage());
}
in = null;
}
if (out != null) {
Logger.loge(CLASS_NAME + "." + "resetConnection", "out != null");
try {
out.close();
} catch (Exception e) {
// Log.d(TAG,"exception in closing outputstream - " + e.getMessage());
}
out = null;
}
if (socket != null) {
Logger.loge(CLASS_NAME + "." + "resetConnection", "socket != null");
try {
socket.close();
} catch (Exception e) {
//Log.d(TAG,"exception in closing socket - " + e.getMessage());
}
socket = null;
}
I have followed the links
https://groups.google.com/forum/#!topic/android-developers/UxY5xME6V5s
Android Bluetooth: java.io.IOException: Service discovery failed
Disconnect a bluetooth socket in Android
android bluetooth can't connect
None of the solution provided help me to solve the issue.
Any help will be appreciated...
Thanks
I had encountered a similar problem when I built an app involving bluetooth connectivity. After searching for a long time, I found this solution.
The Actual problem is once both the device the is connected, the socket will be open. When either one of the socket is closed, other one is not closed.When you try to reconnect the other device ll not accept the new Socket.
The solution is when any one gets disconnect you need to re-initialize the connection service on both the side,ie you need to close the socket properly on both the side. and go back to the listen mode. then only the new socket connection will accept.click Here code reference using AndroiddChat example.

Socket connection refused in Client Code

The below program causes this issue
EDITED:
import java.io.*;
import java.net.*;
public class smtpClient {
public static void main(String[] args) {
// declaration section:
// smtpClient: our client socket
// os: output stream
// is: input stream
Socket smtpSocket = null;
DataOutputStream os = null;
DataInputStream is = null;
// Initialization section:
// Try to open a socket on port 25 : step 1
// Try to open input and output streams: step 2
try {
smtpSocket = new Socket("192.168.1.2", 1024);
os = new DataOutputStream(smtpSocket.getOutputStream());
is = new DataInputStream(smtpSocket.getInputStream());
} catch (UnknownHostException e) {
System.err.println("Don't know about host: hostname");
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: hostname");
}
// If everything has been initialized then we want to write some data
// to the socket we have opened a connection to on port 25
if (smtpSocket != null && os != null && is != null) {
try {
// The capital string before each colon has a special meaning to SMTP
// you may want to read the SMTP specification, RFC1822/3
os.writeBytes("HELO\n");
os.writeBytes("MAIL From: k3is#fundy.csd.unbsj.ca\n");
os.writeBytes("RCPT To: k3is#fundy.csd.unbsj.ca\n");
os.writeBytes("DATA\n");
os.writeBytes("From: k3is#fundy.csd.unbsj.ca\n");
os.writeBytes("Subject: testing\n");
os.writeBytes("Hi there\n"); // message body
os.writeBytes("\n.\n");
os.writeBytes("QUIT");
// keep on reading from/to the socket till we receive the "Ok" from SMTP,
// once we received that then we want to break.
String responseLine;
while ((responseLine = is.readLine()) != null) {
System.out.println("Server: " + responseLine);
if (responseLine.indexOf("Ok") != -1) {
break;
}
}
// clean up:
// close the output stream
// close the input stream
// close the socket
os.close();
is.close();
smtpSocket.close();
} catch (UnknownHostException e) {
System.err.println("Trying to connect to unknown host: " + e);
} catch (IOException e) {
System.err.println("IOException: " + e);
}
}
}
}
Console Log :
Couldn't get I/O for the connection to: hostname
The program I took is from :
http://www.javaworld.com/jw-12-1996/jw-12-sockets.html?page=4
I have already tried modifying the port from 25 to 1024
I am running it on my local PC, so I am admin on this system, but not sure if there is any default firewall issue(running this in eclipse on windows 7)
As per your comments below : DO I need to make a listner, which mean to say a Server Socket, which will listen to smtp client requests
Answer is: according to details what you have provided, there is no listener running or machine with specified IP and port number.
UPD: then you are trying to connect to somewhere you do have to be sure that there is something which listens on other side, either writing your own server code or by using a 3rd party server/code to provide certain service on a port number you are trying to reach.
Why would you expect that there is a mail server running on machine with an address you've provided?
It sounds like some other program is using port 1024.
Try a different port.

Android reading from Socket hangs on second read loop

I got to implement a chat in my application. Connection to a server is made using sockets. I should register to that server and the server will aknowledge that with a reply.
I have implemented this in a single method where I send the command using a BufferedWriter, and then start reading from the input stream until it tells me there is no more data.
I read properly the server reply. However, I never get the negative value from the second in.read call and thus my method stays blocked in the while loop (in the conditionnal statement where I make that call).
How should this be done with sockets? I usually do that with files or other input streams without problem.
If I should read only the bytes I am supposed to read, does that mean that I either have to:
Know in advance the length of the server response?
or make the server send a code to notify it has finished to send its response?
Currently I am doing the following:
private String sendSocketRequest(String request, boolean skipResponse) throws ChatException {
if (!isConnected()) openConnection();
try {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream()), 2048);
out.append(request);
out.flush();
out = null;
} catch (IOException e) {
LogHelper.error("Unable to send socket request: " + request, e);
throw new ChatException("Unable to send socket request: " + request, e);
}
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()), 2048);
StringBuffer response = new StringBuffer();
char[] buffer = new char[2048];
int charsRead = -1;
// >>>>>>>> This is where it gets blocked <<<<<<<<<
while ((charsRead = in.read(buffer)) >= 0) {
if (charsRead > 0) response.append(new String(buffer, 0, charsRead));
}
return response.toString();
} catch (IOException e) {
LogHelper.error("Unable to read socket response: " + request, e);
throw new ChatException("Unable to read socket response: " + request, e);
}
}
Connection to the server is made with the following method:
public synchronized void openConnection() throws ChatException {
try {
socket = new Socket(Constants.API_CHAT_SERVER_ADDRESS, Constants.API_CHAT_SERVER_PORT);
socket.setKeepAlive(true);
LogHelper.debug("CHAT >> Connected to the chat server: " + Constants.API_CHAT_SERVER_ADDRESS);
} catch (UnknownHostException e) {
LogHelper.error("Unable to open chat connection", e);
throw new ChatException("Unable to open chat connection", e);
} catch (IOException e) {
LogHelper.error("Unable to open chat connection", e);
throw new ChatException("Unable to open chat connection", e);
}
}
The amount of data to be sent/received over a socket based connection is protocol dependend and not known to the TCP/IP stack, but only to the application layer.
The protocol used is developer dependend ... ;-) so coming to your questions:
If I should read only the bytes I am supposed to read, does that mean that I either have to:
Know in advance the length of the server response?
Yes, this is one possibility.
or make the server send a code to notify it has finished to send its response?
Also yes, as this is another possibility. Common markers are \n or \r\n. The NUL/'\0' character also might make sense.
A third option is to prefix each data chunk with a constant number of bytes describing the amount of bytes to come.
Instead of dealing with bytes, maybe it's simpler handling instances of ad-hoc classes, like - for instance - a Message class:
The server:
// Streams
protected ObjectInputStream fromBuffer = null;
protected ObjectOutputStream toBuffer = null;
// Listening for a new connection
ServerSocket serverConn = new ServerSocket(TCP_PORT);
socket = serverConn.accept();
toBuffer = new ObjectOutputStream(socket.getOutputStream());
fromBuffer = new ObjectInputStream(socket.getInputStream());
// Receiving a new Message object
Message data = (Message)fromBuffer.readObject();
The client then sends a message by simply:
// Sending a message
Message data = new Message("Hello");
toBuffer.writeObject(data);
Message can be as complex as needed as long as its members implement Serializable interface.

java.io.IOException: Connection reset by peer

I'm trying to manage a connection between my phone and another bluetooth device. I'm doing all this using java Android. This is the code I used for connecting the socket using my device:
First I find the Bluetooth device and I create the socket:
BluetoothDevice btNonin = null;
for (BluetoothDevice device : pairedDevices)
{
if (device.getName().contains("Nonin"))
{
// We found the device
exito = true;
try
{
// We create the socket
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
socket = (BluetoothSocket) m.invoke(device, 1);
socket.connect();
}
catch (Exception e)
{
Dialogs.showInfoDialog(NONIN_OFF, this);
}
}
}
Afther that I create the data bytes I want the remote bluetooth to receive using some code to convert ASCII to byte:
String[] parts = mensaje.split(" ");
String res = "";
if(parts != null && parts.length > 0)
{
for (String s : parts)
{
if (s.length() != 2)
break;
byte izq, der;
izq = (byte)char2ascii(s.charAt(0));
der = (byte)char2ascii(s.charAt(1));
byte aux2 = (byte)((izq << 4) + der);
res += (char)aux2;
}
}
And then I send the data to the bluetooth device:
// We send the data bytes
DataOutputStream dOut = new DataOutputStream(socket.getOutputStream());
dOut.writeBytes(res);
dOut.flush();
Until here it works fine. It sends the data bytes to my device. But then I want to wait for any response from my device, and then I try this:
//Waiting for response
DataInputStream dIn = new DataInputStream(socket.getInputStream());
try
{
byte response = '\u0000';
while (dIn.readByte() == '\u0000')
{
response = dIn.readByte();
}
Dialogs.showInfoDialog("Response: " + response, this);
}
catch (Exception e)
{
Dialogs.showInfoDialog("No se ha recibido respuesta: " + e.toString(), this);
}
But then, on the line where I make dIn.readByte it shows the message Error:
java.io.IOException: Connection reset by peer
And I don't know why the connection is reset or what happens, as I can debug the line:
DataInputStream dIn = new DataInputStream(socket.getInputStream());
With no mistakes, so I guess the socket is still opened... What is happening here?
Thank you so much for your help!
There are several causes of this problem. The typical cause is that you have written to a connection which has already been closed by the peer. In other words, an application protocol error.
Also your exception handling needs work. If you get any IOException on a socket other than a timeout you must close it, it is dead.
Ok, I tried adding some wait() functions and it seems it works... As it was a problem between timeouts of reading and writing. I think this post should work...
remove the line dOut.flush(); this is causing the connection reset.

Categories