Android蓝牙:从UI线程启动的线程阻止UI线程

时间:2016-05-18 06:45:14

标签: android bluetooth

我正在学习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;
            }
        }
    }
}

2 个答案:

答案 0 :(得分:0)

我遇到了同样的问题。我的理解是,每次你进行硬件调用,在这种情况下,蓝牙,你应该在另一个线程中进行。我将isEnabled()调用移动到其他线程,它解决了问题。

答案 1 :(得分:0)

您正在主线程上调用listen.run(),使其在主线程上运行。你应该调用listen.start(),它将产生一个单独的线程,在那里将执行run()方法。

给予处理程序的Runnable将在主线程上执行,但Handler用于主线程。