赵敏涯
(苏州市职业大学 计算机工程学院,江苏 苏州 215104)
蓝牙技术有效地简化了移动通信终端设备之间的无线短距离通信问题,使得数据传输更加迅速高效。蓝牙技术工作在全球通用的2.4 GHz的ISM频段,使用无须申请许可证,不需要支付任何费用,同时具备小体积、低功耗、低成本、高传输速率、抗干扰强、组网简单等特点。因此,蓝牙技术被广泛应用于手机、电脑、汽车医疗等智能电子产品终端设备中[1-2]。
蓝牙技术发展至今已有20余年,早期的传统经典蓝牙BR/EDR的设计意图是打电话时播放音乐,功耗高、数据量大、传输距离短,主要应用于早期的蓝牙耳机和蓝牙音箱等。随着蓝牙4.0技术的出现,低功耗蓝牙BLE成为主流,它更省电、低延迟、传输距离更长,区别于BR/EDR,BLE分为单模和双模两种设备。单模蓝牙称为Bluetooth Smart,有专有的logo,应用于功耗要求低的手表、共享单车锁、防丢器等小型传感器穿戴设备中。双模蓝牙称为Bluetooth Smart Ready,也有专有的logo,支持BR/EDR和BLE,应用于智能手机、降噪耳机、智能电视遥控器等供电稳定的移动设备中。
蓝牙技术建立了一个通用的无线电空中连接平台级数据通信的公共标准,大大促进了计算机技术和无线通信技术的融合,让不同的电子设备之间可以进行近距离连接与数据传输,而不再需要通信电缆就可实现互联互通功能。
蓝牙通信采用时分全双工传输技术,可以实现点对点或点对多点的无线交互功能。
一个蓝牙终端理论上可以同时连接最多7个蓝牙设备。要在支持蓝牙技术的设备之间进行通信,基本的工作流程如图1所示。
图1 蓝牙设备之间的基本通信流程
任何无线通信技术都存在被监听和破解的可能,因此在进行通信之前,设备之间需要进行配对和连接。配对是两个蓝牙设备之间的首次通信认证,而配对成功之后的通信则不再需要每次确认。
各蓝牙设备开启蓝牙功能,对于没有配对的设备,先进行两两配对。已经配对成功的设备可以作为服务器开启服务端线程,监听一个或多个客户端设备的连接请求,连接成功后可以作为服务端进行消息的发送和接收。同时,配对成功的设备也可以作为客户端向指定服务端设备发送连接请求,连接成功后可以作为客户端进行消息的发送和接收。对于同一个设备,可以同时扮演客户端和服务端的角色。基本通信流程如图2所示。一个设备作为客户端只能同时连接一个服务端,作为服务端则可以同时连接多个客户端。
图2 蓝牙通信流程
其中,蓝牙的开关、扫描发现、配对和连接状态通过Android组件的广播接收器Broadcast Receiver来注册监听。
主界面如图3所示。蓝牙开关、扫描、服务端开启、消息发送通过按钮单击事件设计实现,发送双方的消息显示在界面中部,所有已配对的、扫描到的未配对设备显示在列表控件ListView中,列表项的长按事件改变设备的配对状态,短按即单击事件用于当前设备作为客户端向列表中设备发送连接请求。
图3 应用主界面
蓝牙设备两两配对以后就可以进行连接通信了。
Android的蓝牙通信系统和Socket套接字密切相关,蓝牙端的监听接口和TCP的端口类似,都是使用了Socket和ServerSocket类。在服务端使用Bluetooth ServerSocket类来创建一个开放式监听服务接口,在客户端使用一个单独的BluetoothSocket类去初始化一个连接并管理该连接。当一个BluetoothSocket类的连接对象被BluetoothServerSocket类接收,则返回一个新的BluetoothSocket连接并管理该连接。
连接都是阻塞式的,所以要放在线程里去执行。连接成功后,两台设备在相同的串行端口规范RFCOMM通道通过各自的BluetoothSocket对象中的输入、输出流进行数据传输[3]。
2.3.1 消息发送与接收控制
不管是作为服务端还是客户端进行消息发送与接收,基本的处理机制是一样的,文章提供两个通用的类方法分别完成消息内容的发送和接收。
消息的基本处理步骤如下:
通用消息收发工具类MsgUtil{
void sendMsg(String 消息字符串msg){//发送消息方法头
开启线程Thread{
获取输出流getOutputStream();
调用输出流方法write(msg);
调用输出流方法flush()提交数据;
Android子线程不能直接更新UI,所以返回主线程runOnUiThread(){
在当前设备界面上显示发送的msg;
}
}
}
void getMsg(){//接收消息方法头
开启线程Thread{
获取输入流getInputStream();
循环读取输入字节流并保存于StringBuffer容器对象中;
Android子线程不能直接更新UI,所以返回主线程runOnUiThread(){
在当前设备界面上显示接收到的msg;
}
}
}
}
2.3.2 服务端设计
作为服务端主要是监听客户端连接请求,连接成功后接收来自客户端的数据,需要在线程中进行。基本处理步骤如下:
线程类{
构造方法{
初始化BluetoothAdapter对象;
获取BluetoothServerSocket对象;
}
run方法{
监听连接请求accept(),返回BluetoothSocket对象;
调用MsgUtil类方法getMsg()方法接收客户端数据
}
cancel方法{
图4 设备A和设备C之间的消息收发
资源释放;
}
}
2.3.3 客户端设计
作为客户端主要是向服务端发送连接请求,连接成功后接收来自服务端的数据,需要在线程中进行。基本处理步骤如下:
线程类{
构造方法{
获取服务端设备BluetoothDevice对象
获取BluetoothSocket对象;
}
run方法{
发送连接请求connect();
调用MsgUtil类方法getMsg()方法接收服务端数据}
cancel方法{
资源释放;
}
}
笔者使用一台Android 11系统的vivo X60手机作为设备A,一台HarmonyOS 2.0.0系统的华为平板电脑M6作为设备C进行通信测试。
两台设备都可以具备服务端和客户端双重角色。如图4所示,任何一台设备都可以作为服务端或者客户端发送和接收消息,并能正确地显示在界面上,从而实现了双向全双工数据通信,而且即使设备没有互联网连接,也可以进行消息收发。
蓝牙作为短距离无线传输技术之一,有其自己的优势和应用领域,如无需互联网连接实现数据交换,支持较大的文件传输,成本低,安全性高等。Android系统从4.3开始支持低功耗蓝牙,有完备的协议栈和应用程序框架层的SDK包,使得基于Android蓝牙技术的开发越来越便捷。文章就是在此基础上设计实现了具备一定社交功能的蓝牙全双工通信功能模块,并尽可能简化代码,提高程序复用性,实践结果表明效果良好,在缺乏网络等情况下有一定的应用价值。