package com.hairysoft.bt;
import com.hairysoft.util.Log;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* This thread handles the sending of messages from the application to the device.
* If there is no current active connections, it stores them internally for sending them out later
*/
public class Dispatcher extends Thread {
private final static String TAG = "Dispatcher";
private final static int RETRY_COUNT = 3;
// Providing a static reference for the dispatcher, as it is supposed to exist only one at a given time
private static Dispatcher instance;
// Using this type of queue as it ditches the need to use 'wait' and 'notify', while proving to be more efficient
private final BlockingQueue<String> queue;
public static void init() {
instance = new Dispatcher();
instance.start();
}
public static void queueMessage(String msg) {
try {
Log.d(TAG, "Queueing: " + msg);
instance.queue.offer(msg, 100, TimeUnit.MILLISECONDS);
} catch(InterruptedException ex) {
Log.e(TAG, "Message queue timed out: " + msg);
}
}
private Dispatcher() {
queue = new LinkedBlockingQueue<>();
}
private void sendMessage(String msg) throws Exception {
while(!ConnectThread.isConnected()) {
try {
Thread.sleep(500);
} catch(Exception ex) { }
}
ConnectThread.getInstance().write(msg.getBytes());
}
@Override
public void run() {
int retries = 0;
String msg = null, retry = null;
while(true) {
try {
if(retry != null) {
sendMessage(retry);
retries = 0;
retry = null;
}
msg = queue.take();
sendMessage(msg);
} catch(Exception ex) {
Log.e(TAG, "Sending exception", ex);
if(retries++ < RETRY_COUNT) {
retry = retry == null ? msg : retry;
} else {
retries = 0;
retry = null;
}
try {
Thread.sleep(500);
} catch(InterruptedException ex2) { }
}
}
}
}