常州开发APP_常州APP制作公司_常州开发安卓手机APP_常州开发苹果手机APP公司_常州开发软件_常州物联网硬件开发公司_常州点个赞信息科技

Android蓝牙开发如何利用蓝牙BLE实现IBeacon技术

2020-08-08 18:55


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的目标设备。

开发流程

通过对开发需求、开发流程的精准把握及熟练操作,我们实现了一站式定制开发服务。

产品从0-1,必须严格遵循流程才能确保质量与工期!