蓝牙聊天 第4节 蓝牙连接模块

第4节 蓝牙连接模块

蓝牙连接的管理模块需要为ChatActivity提供于连接相关的所有功能,要设计的方便使用,并尽量隐藏连接的细节。

4.1 对外接口

我们首先来看看ConnectionManager需要向Chat Activity提供哪些接口。

  1. 监听。当应用运行起来后,聊天应用需要启动对其它蓝牙设备的监听,迎接随时可能到来的连接请求。所以ConnectionManager需要提供启动监听-startListen()停止监听-stopListen()的两个接口;

  2. 主动连接。应用搜索到可连接到设备后,可以主动的连接对方设备。假如正在连接,用户可能会取消连接;假如已经连接上,用户可能会想断开这个连接。所以ConnectionManager需要提供连接-connect()断开连接-disconnect()(包含取消连接的功能)两个接口;

  3. 主动查询当前连接状态。应用在采取某些操作的时候,可能需要知道当前的连接状态。所以需要提供主动查询当前连接状态的接口。

    连接的状态,我们可以把它分成两类,一个是监听的状态,一个是连接的状态。监听的状态表示当前是否在监听;连接的状态应该包括没有连接,正在连接和已经连接。

    所以接口应该有getCurrentListenState()getCurrentConnectState()

  4. 获取连接状态变化通知。应用界面需要根据连接的状态做出相应的变化,需要ConnectionManager能在连接状态发生变化的时候,主动把信息通知给ChatActivity。所以还要提供一个通知状态变化的接口。

  5. 接收数据。ConnectionManager收到数据以后,需要一个机制将数据通知给ChatActivity,这样ChatActivity才能显示接收到的内容。

  6. 发送数据。用户要发送数据给被连接的设备,所以ConnectionManager要提供一个发送数据的接口-sendData()

45都需要ConnectionManager主动向ChatActivity传递信息(收到的数据、状态改变),可以通过设计监听器来实现。因此需要设计安装监听器的方法:定义一个回调的接口-ConnectionListener;把监听器设置到ConnectioManager中。

综上所述,ConnectionManager大概应该是这个样子,

4.2 ConnectionManager的结构

我们已经明确了ConnectionManager对外的接口。接下来就需要来实现功能了。

由Android SDK提供的蓝牙连接接口函数,很多都是阻塞的(wifi连接也是如此),例如accept()connect()等等,所以就需要将这些操作放到单独的工作线程中进行。

因此,我们将会在ConnectionManager中设计两个工作线程,

  1. AcceptThread:负责监听别的蓝牙设备发起的连接;

  2. ConnectThread:用来维持与其它设备的连接。

主线程首先创建一个监听线程,用来接收其它设备可能发出的连接请求,当监听线程监听到了连接请求,就会得到一个Socket;然后我们再创建一个连接线程,将Socket交给连接线程,两个设备就可以通过这个Socket,在连接线程中进行消息的发送和接收了。

4.2.1 ConnectionManager

  • AcceptThread线程的工作状态,反应的就是监听状态。

    它包括LISTEN_STATE_IDLELISTEN_STATE_LISTENING。这个状态保存在mListenState变量中;

    当监听状态发生改变的时候,通过setListenState()设置状态的改变,并利用回调的方式,将改变的状态通知给关注者。

  • ConnectedThread线程的工作状态,反应的就是连接状态。

    它包括CONNECT_STATE_IDLE CONNECT_STATE_CONNECTINGCONNECT_STATE_CONNECTED;
    这个状态保存在mConnectState变量中;

    当连接状态发生改变的时候,通过setConnectState()设置状态的改变,并利用回调的方式,将改变的状态通知给关注者。

  • ConnectionManager对外提供的接口,实际上就是对这两个工作线程的控制;

通过这里,我们可以看出,为了能够取消正在运行的工作线程,在设计AcceptThreadConnectedThread的时候,我们需要给它们添加上取消的方法-cancel();为了在连接后能够发送数据,需要给ConnectedThread添加发送数据的方法-sendData()

4.2.2 监听线程

监听线程进行的工作有,

  1. 等待其它蓝牙设备发起的连接;

  2. 如果接收到连接的请求,就创建出一个Socket

  3. 之后继续等待其它设备可能发起的连接;

  4. 假如已经处于正在连接或者已经连接的状态,就断开最新收到的连接,因为我们假定了每次只能连接一个设备;

  5. 监听线程可以被取消,退出运行;

4.2.3 连接线程

连接线程的工作是,

  1. 假如是主动连接,连接线程要主动调用connect()方法;该方法是一个阻塞调用,在调用前,应该把ConnectionManager的连接状态,设置成CONNECT_STATE_CONNECTING;如果连接成功,就把状态设置成CONNECT_STATE_CONNECTED

  2. 假如是被动连接,那么从监听线程获取的Socket就已经是被连接上了的Socket,不需要进行connect()的操作了;

  3. 从已经连接的Socket当中,获取输入、输出的流接口,以后这个连接上的数据读取和写入,就是通过它们对应的流接口进行的;

  4. 连接线程进入循环,不断的尝试通过InputStreamread()方法,读取数据;

  5. 连接线程可以被取消,退出连接;

至此,ConnectionManager就设计好了。