一、蓝牙版本介绍

蓝牙版本现在最新是蓝牙 5。在蓝牙4.0 提出了“低功耗蓝牙”、“经典蓝牙”和“高速蓝牙”三种。

低功耗蓝牙和经典蓝牙

Android 蓝牙开发-编程之家

现在的蓝牙实际上分为了三类:单模、双模和经典。那么,最官方的蓝牙版本称呼就是,单模蓝牙、双模蓝牙和经典蓝牙。

单模,也就是低功耗蓝牙,平常看到Bluetooth Smart、BLE就是指这个。
经典,就是经典蓝牙。
双模就是兼容低功耗蓝牙和经典蓝牙。平时看到的Bluetooth Smart Ready就是这个

Android 中的低功耗蓝牙

Android 4.3(API Level 18)开始引入Bluetooth Low Energy(BLE,低功耗蓝牙)的核心功能并提供了相应的API,应用程序通过这些api可以扫描设备、查询services,读写设备的characteristics(属性特征)。对比传统的蓝牙,BLE的设计能够显著减低功耗。这让Android应用程序与BLE设备之间的低功耗通讯成为可能,例如距离传感器、心率监视器、健身设备等等。

这个蓝牙标准和经典蓝牙区别极大,在最初甚至考虑过加入WIFI阵营,但是因为蓝牙阵营这边条件较为优厚(比如授权费用极低)才并入了蓝牙标准。

二、蓝牙开发:

低功耗蓝牙和经典蓝牙的区别究竟在哪里呢?
要是仅仅从两者的通信方式上来说,可以说除了名字叫蓝牙外,完全可以当做两个东西。这也就为很多搞过经典蓝牙以为就可以很轻松的接着搞低功耗蓝牙的人埋下了一个大坑。

不过,两者在总体上的流程却也是相似的,那就是:发现设备->建立连接->数据通信

下面分别介绍经典蓝牙和低功耗蓝牙的开发过程:

2.1、经典蓝牙

蓝牙官方文档

经典蓝牙设备发现其它经典蓝牙设备的方式是调用BluetoothAdapter的startDiscovery()方法,这个方法只能够发现经典蓝牙设备。

2.2、低功耗蓝牙

Android 4.3

针对具有低功耗要求的蓝牙设备,Android 4.3(API 级别 18)中引入了面向低功耗蓝牙的 API 支持。Android 4.3 支持扫描出低功耗的蓝牙,但是自身扫描使用的不是低功耗

Bluetooth Low Energy官方文档 的翻译:Android Bluetooth Low Energy(Android低功耗蓝牙)

BluetoothAdapter官方文档

Android 5.0

在Android 5.0 API 21 引入了BluetoothLeScanner,是用来进行自身的低功耗扫描,扫描出周围的低功耗蓝牙

Android 6.0

改进的蓝牙低功耗扫描,在android 5.0基础上对扫描周围低功耗蓝牙进行了改进。

如果您的应用执行蓝牙低功耗扫描,可以使用新增的 setCallbackType() 方法指定您只希望在下列条件下通知回调:首次找到与设置的 ScanFilter 匹配的播发数据包,或者已过很长时间后才再次看到该数据包。这种扫描方法与旧平台版本中提供的方法相比更加节能。

Android 6.0 API


这篇文章的实战型更强,Android 蓝牙4.0 BLE (onServicesDiscovered 返回 status 是 129,133时)

发现设备

低功耗蓝牙中则有一个主设备(Central)和从设备(Peripheral,也叫外围设备)的概念。

通过BluetoothAdapter的startLeScan()方法实现。从设备则作为被发现方,发出广播,以供发现。

同样,这个startLeScan()方法只能发现低功耗蓝牙从设备

不过,在Android系统蓝牙搜索界面,两种蓝牙设备都是可以被发现的。只有当蓝牙设备与某设备建立连接后,才不会再被扫描到。

三、蓝牙扫描问题

蓝牙扫描问题,在Android 6.0运行API 23的app

有的小伙伴遇到在Android 6.0搜索不到蓝牙设备,大多就是这个问题。

targetApi 为23的APP(及以上)运行在Android 6.0(及以上的)系统上,在扫描蓝牙的时候需要Location的权限。否则会报下面的警告,导致扫描不到周围的蓝牙设备:

W/Binder: Caught a RuntimeException from the binder stub implementation.java.lang.SecurityException: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to get scan resultsat android.os.Parcel.readException(Parcel.java:1684)at android.os.Parcel.readException(Parcel.java:1637)at android.bluetooth.IBluetoothGatt$Stub$Proxy.startScan(IBluetoothGatt.java:696)at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper.onClientRegistered(BluetoothLeScanner.java:374)at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:56)at android.os.Binder.execTransact(Binder.java:565)

三种解决办法:

1、赋予权限,android 6.0 需要AndroidManifest.xml中声明权限和动态申请权限(如果权限是危险权限)
2、更改targetApi 小于23
3、运行在Android 6.0 以下系统

参考:

蓝牙

Android6.0以上系统搜索不到 蓝牙BLE 设备问题

Android中经典蓝牙与低功耗蓝牙的简单对比分析

android 蓝牙5.0初探之低功耗扫描
这篇文章中的瑕疵:1、低功耗扫描不是蓝牙5的特性,是Android 5.0的特性。2、更准确一点说是蓝牙5,而不是蓝牙5.0

蓝牙协议详解

关注我的公众号,轻松了解和学习更多技术
Android 蓝牙开发-编程之家