我正在学习Android蓝牙编程。我从Google的Android开发者网站上复制了大部分代码供学习。想法是在新线程中监听服务器上的连接而不阻塞UI线程。当收到连接请求时,则在另一个线程上完成连接,最后在另一个线程上完成通信。
问题是当我从UI线程启动监听线程时,它会自动阻塞并且不显示任何UI(冻结)。以下是示例代码:
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
setContentView(R.layout.activity_main);
...
badapter = BluetoothAdapter.getDefaultAdapter();
if (badapter == null) {
Toast.makeText(this, "No bluetooth device.", Toast.LENGTH_SHORT).show();
return;
}
if (!badapter.isEnabled()) {
Toast.makeText(this, "Bluetooth is disabled.", Toast.LENGTH_SHORT).show();
return;
}
pairedDevices = new HashMap<String, String>();
discoveredDevices = new HashMap<String, String>();
showDevices();
registerBroadcastReceiver();
//this thread blocks UI thread
ListenThread listen = new ListenThread();
listen.run();
}
和听线程:
public class ListenThread extends Thread {
MainActivity main;
CommunicateThread communicateThread;
private final BluetoothServerSocket serverSocket;
public ListenThread() {
main = MainActivity.getInstance();
BluetoothServerSocket tmp = null;
try {
tmp = main.badapter.listenUsingRfcommWithServiceRecord(main.NAME, main.MYUUID);
} catch (final IOException e) {
main.handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(main, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
serverSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
//keep listening until exception occurs or a socket is returned
while (true) {
try {
socket = serverSocket.accept();
} catch (final IOException e) {
main.handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(main, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
});
break;
}
// If a connection was accepted
if (socket != null) {
//call communication thread once connection is established
communicateThread = new CommunicateThread(socket);
communicateThread.run();
try {
serverSocket.close();
} catch (final IOException e) {
main.handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(main, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
break;
}
}
}
}
答案 0 :(得分:0)
我遇到了同样的问题。我的理解是,每次你进行硬件调用,在这种情况下,蓝牙,你应该在另一个线程中进行。我将isEnabled()调用移动到其他线程,它解决了问题。
答案 1 :(得分:0)
您正在主线程上调用listen.run(),使其在主线程上运行。你应该调用listen.start(),它将产生一个单独的线程,在那里将执行run()方法。
给予处理程序的Runnable将在主线程上执行,但Handler用于主线程。