我已经编写了一个用于连接外部配件的蓝牙 API。
API 的设计方式是有一堆阻塞调用,例如 getTime
、setTime
、getVolume
、setVolume
等
这些工作的方式是它们创建一个有效负载来发送和调用一个名为 sendAndReceive()
的方法,该方法会做一些准备工作并最终执行以下操作:
byte[] retVal = null;
BluetoothSocket socket = getSocket();
// write
socket.getOutputStream().write(payload);
// read response
if(responseExpected){
byte[] buffer = new byte[1024]; // buffer store for the stream
int readbytes = socket.getInputStream().read(buffer);
retVal = new byte[readbytes];
System.arraycopy(buffer, 0, retVal, 0, readbytes);
}
return retVal;
问题是有时此设备会变慢或无响应,因此我想在此调用上设置超时。 我尝试了几种将此代码放入线程\ future 任务并超时运行的方法,例如:
FutureTask<byte[]> theTask = null;
// create new task
theTask = new FutureTask<byte[]>(
new Callable<byte[]>() {
@Override
public byte[] call() {
byte[] retVal = null;
BluetoothSocket socket = getSocket();
// write
socket.getOutputStream().write(payload);
// read response
if(responseExpected){
byte[] buffer = new byte[1024]; // buffer store for the stream
int readbytes = socket.getInputStream().read(buffer);
retVal = new byte[readbytes];
System.arraycopy(buffer, 0, retVal, 0, readbytes);
}
return retVal;
}
});
// start task in a new thread
new Thread(theTask).start();
// wait for the execution to finish, timeout after 6 secs
byte[] response;
try {
response = theTask.get(6L, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new CbtException(e);
} catch (ExecutionException e) {
throw new CbtException(e);
} catch (TimeoutException e) {
throw new CbtCallTimedOutException(e);
}
return response;
}
这种方法的问题是我不能在调用方法中重新抛出异常,并且由于某些方法抛出异常我想转发回 API 的客户端,所以我不能使用这种方法。
你能推荐一些其他的选择吗? 谢谢!
最佳答案
你正在保存你不能使用 Future<> 方法,因为你想重新抛出异常,但实际上这是可能的。
大多数在线示例确实使用原型(prototype) public 实现了 Callable ? call()
但只是将其更改为 public ? call() 抛出异常
,一切都会好起来的:您将在 theTask.get() 调用中得到异常,您可以将其重新抛给调用者。
我个人使用 Executors 来处理 android 上的蓝牙套接字超时:
protected static String readAnswer(...)
throws Exception {
String timeoutMessage = "timeout";
ExecutorService executor = Executors.newCachedThreadPool();
Callable<String> task = new Callable<String>() {
public String call() throws Exception {
return readAnswerNoTimeout(...);
}
};
Future<String> future = executor.submit(task);
try {
return future.get(SOCKET_TIMEOUT_MS, TimeUnit.MILLISECONDS);
} catch (TimeoutException ex) {
future.cancel(true);
throw new Exception(timeoutMessage);
}
}
关于java - Android BluetoothSocket - 超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6346649/