我一直在研究一款适用于Android的蓝牙应用程序,我刚刚发现了这个问题。当我在我的蓝牙服务类中预先形成mySocket.connect();
时,它偶尔会无限期地阻塞。我阅读了BluetoothSocket.close()
的文档,并说明了以下内容:
立即关闭此套接字,并释放所有相关资源。
立即在其他线程中阻止对此套接字的调用 抛出IOException。
但是,这对我来说似乎不起作用。这是我设置计时器然后尝试连接的代码。
//code for starting timer and connecting
MyRunnable runner = new MyRunnable(mySocket);
Thread countThread = new Thread(runner);
countThread.start();
mySocket.connect();
runner.setSocketConnected();
//code for MyRunnable
private class MyRunnable implements Runnable{
private boolean didSocketConnect = false;
private boolean socketConnectFailed = false;
private BluetoothSocket socket;
public MyRunnable(BluetoothSocket socket){
this.socket = socket;
}
public void run() {
long start = System.currentTimeMillis();
while(ESTABLISH_TIMEOUT + start >= System.currentTimeMillis() && !didSocketConnect && !socketConnectFailed){
}
if(!didSocketConnect && !socketConnectFailed){
Log.v(TAG,"Reached Timeout and socket not open. Look for #");
try {
socket.close();
Log.v(TAG,"#THIS CALL SHOULD BE MADE AFTER REACHED TIMEOUT AND SOCKET NOT OPEN");
} catch (IOException e) {
Log.v(TAG,"Closing the socket connection fail--", e);
}
}else{
Log.v(TAG, "Connected or Failed Before Timeout Thread Hit");
}
}
public void setSocketConnected(){
didSocketConnect = true;
}
public void setSocketFailed(){
socketConnectFailed= true;
}
}
当我调用close()时,它也会无限期地阻塞,并且connect()调用永远不会抛出IOException,尽管有BluetoothSocket.close()文档。使它工作的最佳方法是什么,以便connect()和close()不会无限期地阻塞?
注意:我在这个项目中使用Android 2.2。
答案 0 :(得分:2)
BluetoothSocket.connect() - 来自documentation:
尝试连接到远程设备。此方法将阻止直到a 建立连接或连接失败。如果此方法返回 没有例外,此套接字现已连接。
为了让您对BluetoothSocket.connect()的调用退出阻止,它需要建立连接。这是设计的,如果您考虑它,获取我们想要连接的蓝牙设备的地址,调用.connect(),并阻止它连接,这是有道理的。这就是你想要单独的线程的原因。
至于你调用.close(),如果你解决了.connect()的问题,那么.close()应该就位。
请阅读this。它基本上说你想要一个名为“连接”(.connect())和“连接”(InputStream.read())的独立线程。这样您的UI就不会被阻止。
示例(来自上面的链接)。 ConnectThread启动连接。 ConnectedThread管理连接(读/写数据等)。
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
mBluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
}
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(mmSocket);
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
break;
}
}
}
/* Call this from the main Activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
/* Call this from the main Activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}