Reputation: 186
I am developing an Android app that communicates with a Bluetooth device.
The device continuously sends information to the phone, but I chose to only read the data when the user wants to: by pressing a start/stop button. A reading service is started/stopped every time, but the connection stays open.
The connection to the device works well, no matter how many times the start/stop button is pressed, but only as long the user doesn't let the app in a "stop" state more than 5 seconds.
If the user lets the app in "stop" state more than 5 seconds, the program will get stuck in inputstream.read() the next time "start" is pressed.
I have checked that the socket is still open. I know that read() is a blocking function, but in this case it should not block as the device is continuously sending data.
Has anyone encountered a similar problem? Is it possible that the problem really comes from the fact that the socket is not used during a few seconds?
Here is the bit of code that I use for acquiring the data:
public void start() {
if (isStarted()) {
return;
}
task = taskService.submit(new Runnable() {
@Override
public void run() {
int value;
channel.reset();
try {
while ((value = in.read()) != -1 && !Thread.currentThread().isInterrupted()) {
channel.put((byte) (value & 0xFF));
}
} catch (IOException e) {
Log.d("STRS", "IO error : " + e.getMessage(), e);
}
}
});
}
public void stop() {
if (!isStarted()) {
return;
}
task.cancel();
}
public boolean isStarted() {
return task != null && !task.isDone();
}
Upvotes: 3
Views: 1225
Reputation: 291
I've had a similar problem with blocking read() from a Bluetooth socket and fixed the issue by spawning a new thread and calling read() in a tight loop, reading the data into a circular buffer. The thread you're currently calling read() on now reads data from the circular buffer so is non blocking e.g.
private class ReceiveThread extends Thread {
private boolean running = true;
public void stopThread() {
running = false;
}
@Override
public void run() {
byte[] readBuffer = new byte[4 * 1024];
while (running) {
try {
// write bytes directly into a circular buffer
int numBytes = socket.read(readBuffer);
if (numBytes > 0) {
circularBuffer.put(readBuffer, 0, numBytes);
}
} catch (InterruptedIOException e) {
running = false;
} catch (Exception e) {
// swallow
}
}
}
}
You can then read directly from the circular buffer
circularBuffer.get(buffer, 0, bytesToRead);
Google for circular buffer implementations in Java, there are many. Just make sure it's thread safe.
Upvotes: 1