十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
通过蓝牙传输数据与Socket类似。在网络中使用Socket和ServerSocket控制客户端和服务端的数据读写。而蓝牙通讯也由客户端和服务端Socket来完成。蓝牙客户端Socket是BluetoothSocket,蓝牙服务端Socket是BluetoothServerSocket。这两个类都在android.bluetooth包中。
创新互联公司长期为近1000家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为沭阳企业提供专业的网站设计、网站制作,沭阳网站改版等技术服务。拥有十余年丰富建站经验和众多成功案例,为您定制开发。
如果打算建议两个蓝牙设备之间的连接,则必须实现服务器端与客户端的机制。当两个设备在同一个RFCOMM channel下分别拥有一个连接的BluetoothSocket,这两个设备才可以说是建立了连接。
服务器设备与客户端设备获取BluetoothSocket的途径是不同的。服务器设备是通过accepted一个incoming connection来获取的,而客户端设备则是通过打开一个到服务器的RFCOMMchannel来获取的。
通过调用BluetoothAdapter的listenUsingRfcommWithServiceRecord(String, UUID) 方法来获取
BluetoothServerSocket(UUID用于客户端与服务器端之间的配对)调用BluetoothServerSocket的 accept() 方法监听连接请求,如果收到请求,则返回一个BluetoothSocket实例。
如果不想在accept其他的连接,则调用BluetoothServerSocket的 close() 方法释放资源(调用该方法后,之前获得的BluetoothSocket实例并没有close。但由于RFCOMM一个时刻只允许在一条channel中有一个连接,则一般在accept一个连接后,便close掉BluetoothServerSocket)
通过搜索得到服务器端的BluetoothService,调用BluetoothService的listenUsingRfcommWithServiceRecord(String, UUID)方法获取BluetoothSocket(该UUID应该同于服务器端的UUID)。
调用BluetoothSocket的 connect() 方法(该方法为block方法),如果UUID同服务器端的UUID匹配,并且连接被服务器端accept,则 connect() 方法返回。
蓝牙设备在连接前,会先检查设备是否已经配对过,如果没有则先配对,配对完成后,再开始连接。
蓝牙连接开始于设备列表 DeviceListPreferenceFragment的onPreferenceTreeClick方法。
DeviceListPreferenceFragment是蓝牙设备列表,点击其中一个蓝牙设备,开始蓝牙的连接过程。
调用onDevicePreferenceClick方法,接着调用BluetoothDevicePreference的onClicked方法,开始连接,以及连接前的状态检测。
获取mCachedDevice的绑定状态,
pair方法会调用CachedBluetoothDevice.startPairing,启动配对
createBond调用BluetoothDevice.createBond方法,BluetoothDevice.createBond接着调用IBluetooth.createBond方法,下面会调用蓝牙远程服务。
和蓝牙扫描一样,实现IBluetooth接口的类是AdapterServiceBinder,
AdapterServiceBinder实现IBluetooth.Stub接口,并且是AdapterService的私有内部类, AdapterServiceBinder接受事件,都会转交AdapterService处理 ,所以IBluetooth.createBond方法会调用AdapterService.createBond方法。
createBond方法会检查一下远程设备属性信息,再次取消蓝牙扫描任务,将配对任务转交mBondStateMachine,由状态机处理该信息。
BondStateMachine状态机的初始状态是StableState,所以BondStateMachine.CREATE_BOND由StableState处理,StableState在processMessage中调用BondStateMachine.createBond方法
createBondNative方法实现com_android_bluetooth_btservice_AdapterService.cpp中
普通蓝牙设备官方文档
Android 平台包含蓝牙网络堆栈支持 ,凭借此支持,设备能以无线方式与其他蓝牙设备交换数据。应用框架提供了通过 Android Bluetooth API 访问蓝牙功能的途径。使用 Bluetooth API Android 应用可以执行下面的操作:
传统蓝牙适用于电池使用强度较大的操作,例如 Android 设备之间的流传输和通信等。针对具有低功耗要求的蓝牙设备,Android 4.3(API 18)中引入了面向低功耗蓝牙的 API 支持。
使用 Android Bluetooth API 来完成使用蓝牙进行通信的四项主要任务: 设置蓝牙 、 查找局部区域内的配对设备或可用设备 、 连接设备 ,以及在 设备之间传输数据 。
关于蓝牙的 API 在 android.bluetooth 包中,下面介绍一下和蓝牙相关的主要类:
在 BluetoothProfile IPC 客户端连接到服务(即,运行特定配置文件的内部服务)或断开服务连接时向其发送通知的接口。
使用蓝牙必须声明权限 BLUETOOTH 才可以执行蓝牙通信。
1、获取蓝牙适配器
例如:我们可以查询所有已配对的设备,然后使用 ArrayAdapter 向用户显示每台设备的名称:
要发起连接仅需要知道目标蓝牙设备的 Mac 地址就可以了。
注意 执行 discovery 对于蓝牙适配器来说是一个非常繁重的过程,并且会消耗大量资源。在找到要连接的设备后, 要确保使用 cancelDiscovery() 来停止发现,然后尝试连接 。如果您已经和某台设备进行连接,那么这个时候执行发现操作会大幅度的减少此连接可用的带宽!因此不应该在处于连接状态的时候执行发现操作!
例如:
在连接之前如果两个设备没有配对,则系统会自动发出配对请求。
服务器套接字接受连接的基本过程
放在子线程中去执行。
例子:
客户端连接的基本过程
调用 connect() 的时候要确保客户端没有执行发现操作。如果执行了会大幅度降低连接的速度,增加失败的可能。
例子
在连接之前调用 cancleDiscovery() 在进行连接之前应该始终调用这个方法,而且调用的时候无需检测是否正在扫描。
过程:
从 Android 3.0 开始, Bluetooth API 便支持使用蓝牙配置文件。蓝牙配置文件是适用于设备间蓝牙通信的无线接口规范。
1、蓝牙配置文件就是设备间通信(蓝牙设备)的一种规范
免提配置文件便是一个示例,对于连接到无线耳机的手机,两台设备都必须支持免提配置文件。我们也可以通过实现接口 BluetoothProfile 来写入自己的类来支持特定的蓝牙配置文件。Android API 提供了以下的几种蓝牙配置文件的实现:
2、使用配置文件的基本步骤
创建 HDP 应用:
关于普通蓝牙设备和普通蓝牙设备之间的连接通信
关于蓝牙设备和蓝牙仪器(蓝牙耳机、电子秤等等类似产品)
这种之间的通信是通过配置文件代理来实现的。
都有一个对应的配置文件代理类。具体的操作是通过这个对象来完成。
参考: ;mid=2247484128idx=1sn=9d59b9ad66fb68b9569c29566103c009scene=21#wechat_redirect
前面的两篇文章,主要是在 Android 官网关于蓝牙介绍的基础上加上自己的理解完成的。主要针对的是 Android 开发中的一些 API 的使用。
第一篇文章 Android 蓝牙开发(一) 主要是介绍了普通的蓝牙在 Android 开发中的运用。
第二篇文章 Android 蓝牙开发(二) 主要是介绍了低功耗蓝牙的开发。
这篇文章主要介绍的是蓝牙的历史和一些关于蓝牙的通用知识,还有广播包的知识。要想彻底了解蓝牙开发,这些基础的知识也是需要的,就像网络协议一样,这些都是基础的内容。我们的 API 的调用都是以这个为基础的,了解这些,开发过程中遇到问题,才可以知道什么怎么一回事。
下篇文章主要讲的就是实际开发中的一些坑。
蓝牙其实就是一种近距离无线通信技术。
从下到上分别为:控制器(Controller)--主机(host)--应用(Application)
详细介绍各个层的含义:
BLE 应用可以分为两大类:基于非连接的和基于连接的
意思就是外设和周边设备不发生连接,主要靠扫描到的广播来获取信息。发送广播的一方叫做 broadcaster 监听广播的一方叫做 oberver 在 GAP 层有对应的角色定义。
网络拓扑图:
这种方式就是广播设备不断的向外发送广播(含有特定的信息),然后观察者接受到广播按照两者之间约定好的协议进行解析拿到有用的信息。例如:iBeacon,通过这种设备我们可以实现室内定位。
其实这些设备的角色可以即使广播者又是观察者。接收到广播后作出了处理,然后又发送广播。这样就形成了双向的网络,类似于因特网,这就是蓝牙 Mesh 组网。
广播数据包格式:
每个广播数据包由 31 byte 组成。分为有效数据和无效数据两部分。
例子:
这里是扫描的数据包(转换成了 16 进制,两个代表一个字节),第一个字节是 02 表示后面的两个字节是数据部分,然后第二个字节是 01 表示了数据的类型。后面一个字节就是真正的数据了。这个广播数据单元就分析完了。下面就是另一个数据单元了。依次类推,关于数据类型的解释,官网有。
这是数据类型对应的含义表。
网络拓扑图:
一个中心设备可连接多个外设,但是一个外设只能连接一个中心(外设连接成功后就会停止对外广播,别人就发现不了它了)。其中一个中心设备的连接外设的数量也是有限的。
链接: ;mid=2247484141idx=1sn=fd7e71864189b3631ce529afeb4cf669scene=21#wechat_redirect
若使用的是vivo手机,进入手机设置--(其他网络与连接/更多设置)--蓝牙--开启蓝牙,开启后手机会自动搜索附近的设备,点击设备名就可以配对了,配对成功之后,进入文件管理中找到需要传输的文件长按,选择使用“蓝牙”分享即可。
在上一篇中有介绍了Wifi与网络连接处理
Android开发之WiFi与网络连接处理
下面,来继续说说Android中蓝牙的基本使用。
Bluetooth是目前使用的最广泛的无线通讯协议之一,主要针对短距离设备通讯(10米),常用于连接耳机、鼠标和移动通讯设备等。
值得一提的是:
android4.2新增了部分新功能,但是对于Bluetooth熟悉的人或许开始头疼了,那就是Android4.2引入了一个新的蓝牙协议栈针BLE。谷歌和Broadcom之间的合作,开发新的蓝牙协议栈,取代了基于堆栈的Bluez。因此市场上出现了老设备的兼容问题,很多蓝牙设备在android4.2手机上不能正常使用。
BluetoothAdapter简单点来说就是代表了本设备(手机、电脑等)的蓝牙适配器对象。
first:we need permission
要操作蓝牙,先要在AndroidManifest.xml里加入权限
**下面来看看如何使用蓝牙。 **↓↓↓****
Demo已就绪:
返回值:如果设备具备蓝牙功能,返回BluetoothAdapter 实例;否则,返回null对象。
打开蓝牙设备的方式:
1.直接调用函数enable()去打开蓝牙设备 ;
2.系统API去打开蓝牙设备,该方式会弹出一个对话框样式的Activity供用户选择是否打开蓝牙设备。
注意: 1.如果蓝牙已经开启,不会弹出该Activity界面。2.在目前大多数Android手机中,是不支持在飞行模式下开启蓝牙的。如果蓝牙已经开启,那么蓝牙的开关 ,状态会随着飞行模式的状态而发生改变。
1. 搜索蓝牙设备
使用BluetoothAdapter的startDiscovery()方法来搜索蓝牙设备
startDiscovery()方法是一个异步方法,调用后会立即返回。该方法会进行对其他蓝牙设备的搜索,该过程会持续12秒。该方法调用后,搜索过程实际上是在一个System Service中进行的,所以可以调用cancelDiscovery()方法来停止搜索(该方法可以在未执行discovery请求时调用)。
系统开始搜索蓝牙设备
^( *  ̄(oo) ̄ ) ^ 系统会发送以下三个广播:
2.扫描设备
3.定义广播接收器接收搜索结果
4.注册广播
获取附近的蓝牙设备
第一步建立连接:首先Android sdk(2.0以上版本)支持的蓝牙连接是通过BluetoothSocket建立连接,服务端BluetoothServerSocket和客户端(BluetoothSocket)需指定同样的UUID,才能建立连接,因为建立连接的方法会阻塞线程,所以服务器端和客户端都应启动新线程连接。
(这里的服务端和客户端是相对来说的)
两个蓝牙设备之间的连接,则必须实现服务端与客户端的机制。
当两个设备在同一个RFCOMM channel下分别拥有一个连接的BluetoothSocket,这两个设备才可以说是建立了连接。
服务端设备与客户端设备获取BluetoothSocket的途径是不同的。
1,服务端设备是通过accepted一个incoming connection来获取的,
2,客户端设备则是通过打开一个到服务端的RFCOMM channel来获取的。
服务端
通过调用BluetoothAdapter的listenUsingRfcommWithServiceRecord(String, UUID)方法来获取BluetoothServerSocket(UUID用于客户端与服务端之间的配对)
客户端
调用BluetoothService的createRfcommSocketToServiceRecord(UUID)方法获取BluetoothSocket(该UUID应该同于服务端的UUID)。
调用BluetoothSocket的connect()方法(该方法为block方法),如果UUID同服务端的UUID匹配,并且连接被服务端accept,则connect()方法返回。
数据传递,通过以上操作,就已经建立的BluetoothSocket连接了,数据传递无非是通过流的形式
获取流
该类就是关于远程蓝牙设备的一个描述。通过它可以和本地蓝牙设备---BluetoothAdapter连接通信。
好多东西我也不知道怎么描述,下面给出Demo:
刚好有刚学习的小伙伴问我ListView怎么用,那我就用ListView。
源码:
RairDemo
GitHub:
Coding: