1.IBeacon是个啥
IBeacon是由苹果公司推出的一项技术,目的是为了弥补GPS无法覆盖室内定位的这种场景。通常,我们说的蓝牙定位利用的信号强度与距离有关(距离越远,接收者接收到的信号强度越小)来实现的。
在蓝牙SPC V5.1版本提出了基于出发角和到达角的厘米级定位。如果对无线定位技术感兴趣,可以自行百度学习一下,这里就不深入了。
我们看一下IBeacon广播包的结构,如下图所示。IBeacon广播包由30字节固定长度的前缀和最长31个字节的有效负载构成。
看一下IBeacon的前缀的结构:
腾讯公司利用IBeacon实现了微信摇一摇的功能,这一功能在O2O领域得到广泛应用。
2.如何实现Advertiser
2.1申请必要的权限
AndroidManifest.xml中添加:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-feature android:name="android.hardware.bluetooth_le"
android:required="true" />
动态申请位置权限:
private void requestPermissions() {
if (Build.VERSION.SDK_INT < 23){return;}
//判断是否有权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
//请求权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
}
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
//请求权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
}
}
2.2设置广播格式
//设置广播
AdvertiseSettings settings = new AdvertiseSettings.Builder()
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) //设置广播模式
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) //设置发送功率
.setConnectable(false) //能否连接,广播分为可连接广播和不可连接广播
.build();
在这里,我们设置了广播模式为低延迟模式,除此模式外,还有均衡模式和低功耗模式,低延迟模式下更容易被其他设备扫描到。
设置发射功率为高,除此之后,发射功率还有极低、低、中等三种。
/**
* Advertise using the lowest transmission (TX) power level. Low transmission power can be used
* to restrict the visibility range of advertising packets.
*/
public static final int ADVERTISE_TX_POWER_ULTRA_LOW = 0;
/**
* Advertise using low TX power level.
*/
public static final int ADVERTISE_TX_POWER_LOW = 1;
/**
* Advertise using medium TX power level.
*/
public static final int ADVERTISE_TX_POWER_MEDIUM = 2;
通过setConnectable(false)来设置广播为不可连接。因为我们这里是仅仅做个Advertiser功能,所以不用设置可连接。下一小节中,我们会用微信小程序测试一下,我们这样设备后的设备是否可以连接成功,预期是不能的。
2.3设置广播数据
//设置广播内容
AdvertiseData advertiseData = new AdvertiseData.Builder()
.setIncludeDeviceName(true) //包含蓝牙名称
.setIncludeTxPowerLevel(true) //包含发射功率级别
.addManufacturerData(1, new byte[]{1, 2, 3}) //设备厂商数据,可以作为设备过滤条件
.build();
设置广播数据中包含本地蓝牙设备的名称。
设置广播数据中包含发射功率等级,发射功率等级就是上面提到的:极低、低、中等、高四个等级。
设备厂商数据,我们这里设置为“1,2,3”,这个字段可以作为扫描端(即client 端)进行设备过滤或者传递信息的字段。
除此之外,我们在广播数据中添加一个service,并且将该service绑定一定的数据。使用的方法如下:
/**
* Add a service UUID to advertise data.
*
* @param serviceUuid A service UUID to be advertised.
* @throws IllegalArgumentException If the {@code serviceUuids} are null.
*/
public Builder addServiceUuid(ParcelUuid serviceUuid) {
if (serviceUuid == null) {
throw new IllegalArgumentException("serivceUuids are null");
}
mServiceUuids.add(serviceUuid);
return this;
}
/**
* Add service data to advertise data.
*
* @param serviceDataUuid 16-bit UUID of the service the data is associated with
* @param serviceData Service data
* @throws IllegalArgumentException If the {@code serviceDataUuid} or {@code serviceData} is
* empty.
*/
public Builder addServiceData(ParcelUuid serviceDataUuid, byte[] serviceData) {
if (serviceDataUuid == null || serviceData == null) {
throw new IllegalArgumentException(
"serviceDataUuid or serviceDataUuid is null");
}
mServiceData.put(serviceDataUuid, serviceData);
return this;
}
2.4设置扫描响应数据
在扫描端搜索到我们的Advertiser后,会对Advertiser发起主动扫描请求,这个时候,我们可以给出一个响应来。如何进行这个响应数据的设置呢?可以通过如下的方式:
//设置扫描响应数据,作为客户端扫描(连接前)的响应
AdvertiseData scanResponse = new AdvertiseData.Builder()
.addManufacturerData(2, new byte[]{4, 5, 6}) //设备厂商数据,自定义
.addServiceUuid(new ParcelUuid(TEMPERATURE_SERVICE_UUID)) //服务UUID
.build();
我们添加了一个自定义的service,其UUID为:
public static final UUID TEMPERATURE_SERVICE_UUID = UUID.fromString("10000000-0000-1000-8000-00805f9b34fb"); //service uuid
3.Demo验证
完成上一小节描述的步骤,我们其实已经完成demo的编码。怎么来验证我
们的功能呢?我们可以分两个步骤来完成,
(1)利用demo看是否可以正常扫描到我的Observer,广播数据是否可以正常搜索到。 (2)利用BLE蓝牙开发助手测试是否可以正常搜索到Advertiser,
是否可以正常建立gatt连接。3.1验证是否可以被搜索到
修改搜索支持"10000000-0000-1000-8000-00805f9b34fb"UUID的目标设备。