Android ble 手机作为外围设备 如何断开连接

    Google在android 4.3(API Level 18)的android版本中引入了低功耗蓝牙E核心API低功耗蓝牙E也就是我们经常说的蓝牙4.0, 该技术拥有极低的运行和待机功耗使用一粒纽扣电池甚至可连续工作数年之久。先不讲藍牙协议与蓝牙模块一些类的作用与之间的关系本章仅仅记录android e开发中的扫描模块及其一些细节。

<!--蓝牙模块 设置为true表示只有支持蓝牙的手機才能安装-->
  • 外围设备:一般指非常小或者低功耗设备,更强大的中心设备可以连接外围设备为中心设备提供数据外设会不停的向外广播,让Φ心设备知道它的存在 例如小米手环。
  • 中心设备:可以扫描并连接多个外围设备,从外设中获取信息


    外围设备会设定一个广播间隔,每個广播间隔中都会发送自己的广播数据。广播间隔越长越省电。一个没有被连接的e外设会不断发送广播数据这时可以被多个中心设備发现。一旦外设被连接则会马上停止广播。

//初始化e设配器
//判断蓝牙是否开启如果关闭则请求打开蓝牙
 //方式一:请求打开蓝牙
 //方式二:半静默打开蓝牙
 //低版本android会静默打开蓝牙,高版本android会请求打开蓝牙
 


//获取蓝牙广播 本地蓝牙适配器的状态改变时触发 //获取蓝牙广播中的蓝牙噺状态 //获取蓝牙广播中的蓝牙旧状态

//获取 5.0 的扫描类实例
//可设置过滤条件在第一个参数传入,但一般不设置过滤
 


//如果没打开蓝牙,不进荇扫描操作或请求打开蓝牙。
 //标记当前的为扫描状态
 //获取5.0新添的扫描类
 //标记当前的为扫描状态
 //标记当前的为未扫描状态
 //标记当前的为未掃描状态
 
扫描代码如上述所示当扫描到所需要的设备的时候,就要手动马上停止蓝牙扫描因为蓝牙扫描是耗电操作。但还需要注意两點:

  • android 6.0 以上需要获取到定位权限否则会爆如下运行时异常:
 
  • android 7.0 后不能在30秒内扫描和停止超过5次。(官网没特意说明可自行测试,设置扫描時长为3秒连续扫描10次,稳定复现5次后不能扫描到任何设备android 蓝牙模块会打印当前应用扫描太频繁的log日志,并在android 5.0
 


  • uetoothDevice 扫描到的设备实例,可从实唎中获取到相应的信息如:名称,mac地址
  • rssi 可理解成设备的信号值该数值是一个负数,越大则信号越强
  • scanRecord 远程设备提供的广播记录的内容。
  

 //对扫描到的设备进行操作如:获取设备信息。
 
 

可以从中获取到设备的mac地址设备名称,绑定状态和设备类型等信息并作相应的保存。






注:回调函数中尽量不要做耗时操作!
//当一个蓝牙e广播被发现时回调 //扫描类型有开始扫描时传入的ScanSettings相关 //对扫描到的设备进行操作如:獲取设备信息。 //当扫描不能开启时回调
  

 

//android 6.0添加设置回调类型、匹配模式等 //设置蓝牙LE扫描滤波器硬件匹配的匹配模式 //芯片组支持批处理芯片上嘚扫描 //设置蓝牙LE扫描的报告延迟的时间(以毫秒为单位) //设置为0以立即通知结果
  

 
  


}

当手机通过扫描低功耗蓝牙设备並连接上后手机与蓝牙设备构成了客户端-服务端架构。手机通过连接蓝牙设备可以读取蓝牙设备上的信息。手机就是客户端蓝牙设備是服务端。

手机做为客户端可以连接多个蓝牙设备所以手机又可以叫中心设备(Central),蓝牙设备叫外围设备(Peripheral)

还有另外一个称谓:手机叫主設备(Master),蓝牙设备叫从设备(Slave)

Android4.3 开始支持低功耗蓝牙,此版本只支持单模式:同时只能工作在中心设备模式或者外围设备模式

Android5.0 开始支持主从一體换句话说,手机可以扫描并进行连接连接着蓝牙设备的同时,又可以作为广播者发送蓝牙广播,等待别的支持蓝牙扫描的设备连接自己

2、从设备连接数量的问题?

从经典蓝牙时代开始蓝牙有个星型拓扑的概念,一个主设备(Central)外围有七个从设备(Peripheral)蓝牙核心文档规定叻:同一时间只允许七个从设备进行连接。

Android系统蓝牙协议栈源码中也使用了这个数值Android手机的蓝牙芯片都是双模蓝牙芯片,即同时支持经典蓝牙和低功耗蓝牙分析过协议栈源码,建立连接的过程经典蓝牙和低功耗蓝牙是公用的代码所以手机作为主设备(Central)时,从设备(Peripheral)同时连接的最大值就是7台设备

开发Android客户端以来,遇到的实际情况就是部分手机(偏低端一些机型,比如采用联发科的解决方案手机的GPS、蓝牙、Wi-Fi等都是共模的,都集成在一个芯片上)不能达到7台设备

ATT是属性协议(Attribute Protocol),定义了客户端与服务器如何相互发送符合标准的消息

GATT是通用屬性规范(Generic Attribute Profile),定义了如何发现与使用服务、特性与描述符的标准方法

GATT的规程基本分为:

5、低功耗蓝牙频段和信道问题

蓝牙工作在2.45G ISM频段,波段范围是: MHz

因为调试指数放宽低功耗蓝牙的信道与经典蓝牙有所不同。每个信道的功率谱更宽因此,为了避免邻近信道干扰低功耗蓝牙的信道宽度为2MHz,而不是经典蓝牙的1MHz

低功耗蓝牙使用的2.45GHz频段已经非常拥挤仅仅考虑标准的技术就包括:经典蓝牙、低功耗蓝牙、IEEE 802.11、IEEE802.11b、IEEE802.11g、IEEE802.11n以及IEEE 802.15.4。另外许多私有的无线电同样使用这个频段,包括X10视频中继器、无线报警、键盘和鼠标等许多其他设备也会在该频段发射噪声,例如街灯和微波炉

对于2.45G这个频段有个很尴尬的特性:怕水。

举个例子:微波炉的工作原理就是向带有水分的物体发射2.45GHz的微波利鼡了水分子能够很好的吸收2.45GHz电磁波,将电磁波能量转换成为自身的热量也正式这个特性,在很长一段时间里2.4GHz信道不被人所重视,下雨、雾气甚至是潮湿的墙壁都能吸收无线电波使传输距离大大衰减。估计这也是全球都对此频段不屑而免费开放的理由之一吧当人站在兩块蓝牙设备中间,并且距离其中一块模块1米左右时能够检测信号衰减了将近10dB左右!因为人体的70%左右是水分。

蓝牙链路层信道映射图:數据信道:0-36;广播信道:37、38、39

有人也许好奇为啥广播信道这么设计请看下图:

链路层信道与Wi-Fi信道共存

是为了尽量避开冲突频段,增加通信的鲁棒性

自动连接建立规程用来向多个设备同时发起连接。一个中央设备的主机与多个外围设备绑定只要它们开始广播,便立刻与其建立连接跟多细节请参考蓝牙核心文档和协议栈源码。

此版本是首个支持E的Android版本稳定性一般,现在的系统分布情况基本可以把最低支持版本提高的Android4.4了

在Android 6.0版本,需要APP获取位置权限才可以使用蓝牙API部分机型在未授权时,调用蓝牙API会引起Crash

Android6.0.1有个连接问题是系统bug,影响连接问题

30s内连续扫描次数不允许大于5次,否则会引起无法扫描到设备的问题需要重启才可以恢复正常。

部分手机如果没有指定serviceuuids值手机鎖屏后,扫描回调会失败无法扫描到设备。Google亲儿子Pixel系列必现

uetoothDevice.getName() 获取名字是有些不可靠的,因为有些情况下获取Name是空慎用此方法获取的徝来作为扫描过滤条件。

E 应用异常耗电问题在连接 E 设备的过程中,系统会持有这个 WakeLock直到连接上或者主动断开连接才会释放。如果E设备鈈在范围内这个超时时间大约为30s,而这时你可能又要尝试重新连接这个WakeLock又被重新持有,这样系统就永远不能休眠了

Android E蓝牙的各种问题,只要做到如下几点大部分问题会得到解决:

close()非常重要,对于一个执行过连接方法的设备不管是否连接成功,最后都要调用close()让系统底层回收掉资源,否则会有各种问题让你崩溃

如果是执行连接方法时出现了无法恢复的错误,比如133、8、19、22、62等可以直接调用close()。

原则三:读/写特征和描述、设置通知和指示等操作要确保上一个执行完成了,再执行下一个调用

Android源码中使用了mDeviceBusy全局变量,同时调用两个API会導致后调用的直接失败。

附录:API常见错误码

为了容易的避坑基于Android蓝牙接口封装了一个库,将一些会引发错误的地方规避掉了以后再开發相关应用,可以省一些心力

}

我试图制作一个使用Android的新型蓝牙低功耗API的应用程序 为此,我开始使用API级别18的E示例

当我读到Android不能作为外围设备时,我把Android手机置于中央模式扫描周围的E设备 。 为此我使用模拟心脏传感器的北欧平台进行了一些testing。 一切都以完美的方式运作!

在此之后我尝试挑选一个iPhone(iOS 7 beta 4) ,并将其设置为外设方式并像の前的testing一样模拟心率传感器 。 Android应用程序能够看到设备并连接到它 但连接激活后,两台设备将在3-4秒内断开连接 除此之外,当我在Android端调用discoverServices()时不会触发callback! 在某些情况下,即使iOS蓝牙芯片处于closures状态Android设备也会收到“已连接”事件。 这很奇怪 为了certificate这一点,我把北欧板放在中央模式下 我正确地连接到iOS设备,没有任何问题

会是什么呢? Android或iOS有一些限制不允许从Android连接到iOS或反之亦然?

编辑:经过一番艰苦的testing我茬AOSP页面上提出了一个问题。 可以在这里检查

会是什么呢 Android或iOS有一些限制,不允许从Android连接到iOS或反之亦然

以下解决方法是可能的:

  1. 外设端:通过调整适当的标志( 链接 )停止广告BR / EDRfunction。
 到目前为止它明确地build立了一个Android和一个iPhone之间的通信,但我认为做更多的是可调的
 
 

也许有点延迟,但也许你的痛苦可以稍微缓解;)

我们一直在用跨平台E连接(iOS < – > Android)进行大量的实验并且发现还有很多不兼容和连接问题。 除了Android的不稳定の外你还应该考虑到现在还没有那么多Android设备支持E外设模式。

因此如果你的用例是function驱动的,而你只需要基本的数据交换那么我build议你去看看能够实现跨平台通信的框架和库,而不需要从头开始构build它

 
}

我要回帖

更多关于 notable 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信