本文主要介绍了Android蓝牙通信模式的详细说明总结。通过示例代码非常详细,对大家的学习或者工作都有一定的参考价值。有需要的朋友下面和边肖一起学习。
1.摘要
Android手机通过蓝牙通讯的方式有两种,一种是socket,另一种是通过GATT服务器(Android 5.0以后)。socket是最简单的,但是很多低功耗的蓝牙设备,比如单片机上的蓝牙模块,可能不支持。Gatt模式比较复杂。实际上,Android设备之间的蓝牙通信是一种C/S(客户端-服务器)模式,无论是socket模式还是Gatt模式。
基于两种交流方式,本文详细展开,并推荐开源项目,建议合作学习。
关键词
(1)蓝牙
蓝牙:蓝牙是一种无线电技术,支持设备之间的短距离通信(一般在10m以内)。它可以在许多设备之间交换无线信息,包括移动电话、PDA、无线耳机、笔记本电脑和相关外围设备。使用“蓝牙”技术可以有效地简化移动通信终端设备之间的通信,也成功地简化了设备与互联网之间的通信,从而使数据传输更加快速高效,为无线通信拓宽了道路。
(2) UUID
UUID (Universal Unique Identifier):用于标识蓝牙服务和访问通信功能的属性。不同的蓝牙服务和属性使用不同的访问方法。
(3)服务UUID
UUID(服务UUID:不同的服务应该有不同的号码(uuid)来区分不同的服务。
(4)特征值UUID
特色UUID(特色UUID):一个特色是附在一个服务上的。
(5)属性)(5.1)读取:读取属性
读取:读取属性。带有这个属性的特性是可读的,也就是说这个属性允许手机读取一些信息。移动电话可以发送指令以读取具有读取属性UUID的特定信息。
(5.2)通知:通知属性
通知:通知属性。具有该属性的功能可以发送通知,也就是说,具有该属性的功能可以主动向手机发送信息。
(5.3)写入:写入属性
Write:写属性,用它可以接收写数据。通常情况下,手机通过该属性向蓝色模块发送数据。该属性会在写入完成后向手机发送写入结果的反馈,然后手机可以写入下一个包或者处理后续业务。写入一包数据后,该属性需要等待应用层返回写入结果,速度较慢。
(5.4)无响应写入:写入属性
WriteWithout Response: Write属性,字面意思就是只写,不需要返回写出来的结果。该属性的特点是不需要应用层返回,完全依赖于协议层。速度很快,但是当写入速度超过协议处理速度时,就会出现丢包现象。
关贸总协定
GATT(Generic Attribute Profile):中文名为通用属性协议,定义了完成低功耗蓝牙设备之间数据传输的服务和特性。它基于通用数据协议属性协议(ATT)。ATT将服务和特性以及相关数据保存在一个简单的查找表中,该表使用16位id作为索引。
(7)简介
Profile可以理解为一种规范,一种标准的通信协议,存在于从机中。蓝牙组织规定了一些标准配置文件,如HID OVGATT、防丢失设备、心率计等。每个概要文件包含多个服务,并且每个服务代表从设备的一个能力。
2. Bluetooth Socket
推荐的开源项目:https://github.com/Zweo/Bluetooth(https://github.com/zolty-lionheart/Bluetooth)
以这个项目的demo为例。
蓝牙端口监听接口和传输控制协议(传输控制协议)端口类似:插座和服务器套接字类。在服务器端,使用蓝牙服务器插座类来创建一个监听服务端口。当一个连接被蓝牙服务器插座所接受,它会返回一个新的蓝牙插座来管理该连接。在客户端,使用一个单独的蓝牙插座类去初始化一个外接连接和管理该连接。
最通常使用的蓝牙端口是RFCOMM,它是被Android API支持的类型RFCOMM是一个面向连接,通过蓝牙模块进行的数据流传输方式,它也被称为串行端口规范(串行端口配置文件,SPP)。
为了创建一个蓝牙插座去连接到一个已知设备,使用方法蓝牙设备。createrfcomsockettoservicerecord()。然后调用连接()方法去尝试一个面向远程设备的连接。这个调用将被阻塞指导一个连接已经建立或者该链接失效。
为了创建一个蓝牙插座作为服务端(或者"主机"),查看蓝牙服务器插座文档。
每当该端口连接成功,无论它初始化为客户端,或者被接受作为服务器端,通过getInputStream()和getOutputStream()来打开超正析象管(图片Orthicon)流,从而获得各自的输入流和输出流对象
蓝牙插座类线程安全。特别的,关闭()方法总会马上放弃外界操作并关闭服务器端口。
注意:需要蓝牙技术权限。
2.1 Server端
私有静态最终字符串UUIDString=' 00001101-0000-1000-8000-00805 F9 b 34 FB ';
//开启服务器
私有类服务器线程扩展线程{
@覆盖
公共无效运行(){
尝试{
/* 创建一个蓝牙服务器
* 参数分别:服务器名称、UUID */
mServerSocket=蓝牙适配器。listenusingrfcommwithservicerecord(PROTOCOL _ SCHEME _ RFCOMM,uuid。from string(uuid字符串));
while (true){
Log.d('服务器','等待客户端连接.');
Message msg=new Message();
msg.obj='请稍候,正在等待客户端的连接.';
消息.什么=等待客户端;
linkdetectedhandler。发送消息(msg);
/* 接受客户端的连接请求*/
蓝牙socket socket=mserversocket。接受();
插座图。放(插座。getremote device().getAddress()、socket);
//远程设备映射。放(插座。getremote device().getAddress()、socket。get remote device());
Log.d('server ','接受成功!');
消息msg2=新消息();
字符串信息='客户端已经连接上!可以发送信息。';
味精2。obj=info
msg.what=连接的客户端
linkdetectedhandler。sendmessage(消息2);
//启动接受数据
读取线程mreadThread=新读取线程(套接字。getremote device().get address());
读取线程图。放(插座。getremote device().getAddress()、mreadThread);
mreadthread。start();
}
} catch (IOException e) {
e。printstacktrace();
}
}
}
2.2 Server
//开启客户端
私有类客户端线程扩展线程{
私有字符串远程地址
公共客户端线程(字符串remoteAddress) {
这个。远程地址=远程地址;
}
@覆盖
公共无效运行(){
尝试{
//创建一个(电源)插座连接:只需要服务器在注册时的UUID号
蓝牙设备设备=蓝牙适配器。getremote设备(远程地址);
蓝牙插座socket=设备。createrfcomsockettoservicerecord(uuid。from string(UUIDString));
//连接
消息msg2=新消息();
msg2.obj='请稍候,正在连接服务器:"远程地址
味精2。what=IS _ CONNECTING _ SERVER
linkdetectedhandler。sendmessage(消息2);
插座。connect();
socketMap.put(remoteAddress,socket);
Message msg=new Message();
msg.obj=remoteAddress
msg.what=CONNECTED _ SERVER
linkdetectedhandler。发送消息(msg);
//启动接受数据
读线程mreadThread=新读线程(远程地址);
读取线程图。put(远程地址,mreadThread);
mreadthread。start();
} catch (IOException e) {
e。printstacktrace();
插座图。删除(远程地址);
Log.e('connect ',e.getMessage(),e);
Message msg=new Message();
msg.obj='连接服务端异常!断开连接重新试一试e . getmessage();
msg.what=连接服务器错误
linkdetectedhandler。发送消息(msg);
}
}
}
3. Bluetooth GATT
推荐开源项目:https://github。com/ding pwen/bl _ communication(https://github . com/zolty-lionbheart/bl _ communication)
以该项目演示为例介绍
3.1 Server
私人趣味设置服务器(){
val GATT服务=蓝牙GATT服务(常量106 . BLE服务UUID,蓝牙服务。服务类型主要)
val character istic read=bluetooth GATT character istic(常量BLE _里德_UUID,蓝牙特性PROPERTY_READ,BluetoothGattCharacteristic .权限_读取)
val描述符=蓝牙GATT描述符(常量UUIDdescBLE蓝牙特性。权限_写)
字符式阅读。添加描述符(描述符)
gattservice。添加字符识别符(字符识别符读取)
val特性写入=蓝牙GattCharacteristic(常量BLE _写_UUID,蓝牙特性属性_写或
蓝牙关贸总协定特征属性_读取或蓝牙GATT特征.属性_通知,
蓝牙关贸总协定特征。权限_写)
gattservice。添加字符字符(字符字符书写)
Log.d('wenpd ',' startGattServer:stagattServicetus=$ gattService ')
mgattserver。addservice(gattService)
}
3.2 Client
私有类GattClientCallback扩展BluetoothGattCallback {
@覆盖
public void onConnectionStateChange(蓝牙关贸总协定关贸总协定,国际地位,国际新地位){
超级棒。onconnectionstatechange(GATT,status,new state);
if (status==BluetoothGatt .GATT_FAILURE) {
disconnectGattServer();
返回;
} else if(状态!=蓝牙关贸总协定.GATT_SUCCESS) {
disconnectGattServer();
返回;
}
if (newState==BluetoothProfile .STATE_CONNECTED) {
mConnected=true
关贸总协定。发现服务();
} else if(新状态==蓝牙配置文件.状态_断开){
disconnectGattServer();
}
}
@覆盖
服务公开无效(蓝牙关贸总协定关贸总协定国际地位){
超级棒。onservicesdiscovered(GATT,状态);
Log.d(标签,' onServicesDiscovered status:' status ');
如果(状态!=蓝牙关贸总协定.GATT_SUCCESS) {
返回;
}
蓝牙gattservice服务=GATT。获取服务(常量。服务_ UUID);
蓝牙GATT特性字符istic=服务。获得字符istic(常量。特色_ UUID);
性格主义。设置书写类型(蓝牙GATT字符集).写_类型_默认);
关贸总协定。setcharacteristinotification(character istic,true);
}
@覆盖
公众对人物性格的空虚感改变了(蓝牙关贸总协定,蓝牙关贸总协定字符字符字符)
super.onCharacteristicChanged(关贸总协定,特性);
byte[]消息字节=字符istic。getvalue();
/*for(int i=0,j=消息字节。长度-1;I j;I,- j) {
byte temp=消息字节[I];
消息字节[I]=消息字节[j];
消息字节[j]=temp;
}*/
字符串消息字符串=新字符串(消息字节,标准字符集.UTF _ 8);
Log.d(标签,'收到的消息:‘消息字符串’);
setReceivedData(消息字符串);
}
}
参考文献
1.安卓手机蓝牙通信方式总结(插座与关贸总协定)
2.蓝牙之蓝牙插座
3.全面而简单地介绍蓝牙服务和UUID
4.安卓BLE蓝牙开发-读写数据获取UUID
关于Android蓝牙通讯的详细讲解这篇文章到此为止。关于Android蓝牙通信的更多信息,请搜索我们之前的文章或继续浏览下面的相关文章。希望你以后能支持我们!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。