最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

当前速递!Android BLE 广播定制

来源:博客园


(相关资料图)

近期项目中用到蓝牙BLE,需要区分设备及显示蓝牙名。对于蓝牙BLE广播,发送字节数超过31会广播失败(原因之一是蓝牙名称太长),再者蓝牙mac地址是动态的无法区分设备。和同事交流后,采用他的项目中的方法。

名称太长问题

  1. 广播时,不添加Service UUID,采用2个字节表示服务。
  2. 蓝牙名字符长度超过10则截取前十个字符,并发送表示名称不完整的字节。

设备唯一性

随机两个数字保存在本地,广播时作为设备码(占用2个字节)发送。

代码实现

广播数据部分

private AdvertiseData buildAdvertiseData(boolean includeDeviceName) {                SharedPreferences sharedPreferences = mContext.getSharedPreferences("config_ble", Context.MODE_PRIVATE);        int key1 = sharedPreferences.getInt("key1", 0);        int key2 = sharedPreferences.getInt("key2", 0);        if (key1 == 0 || key2 == 0) {            Random random = new Random();            key1 = 10 + random.nextInt(89);            key2 = 10 + random.nextInt(89);            sharedPreferences.edit().putInt("key1", key1).putInt("key2", key2).apply();        }        String name = mBluetoothAdapter.getName();        boolean isFullName = true;        int maxNameLength = 10;        if (TextUtils.isEmpty(name)) {            name = String.format("BLE-%s%s", key1, key2);        } else {            if (name.length() > maxNameLength) {                name = name.substring(0, maxNameLength);                isFullName = false;            }        }        byte[] bytes = name.getBytes(StandardCharsets.UTF_8);        byte[] nameBytes = new byte[bytes.length + 1];        nameBytes[0] = (byte) (isFullName ? 1 : 0);        System.arraycopy(bytes, 0, nameBytes, 1, bytes.length);        String realName = isFullName ? name : (name + "...");        return                new AdvertiseData.Builder()                .setIncludeDeviceName(false) //包含蓝牙名称,不能传送名字(太长超过31字节),会广播不成功                .addManufacturerData(0, new byte[]{0x6A, 0x7E}) //标识该服务                .addManufacturerData(1, new byte[]{(byte) key1, (byte) key2})//设备码                .addManufacturerData(2, nameBytes)//蓝牙名                .build();    }

蓝牙扫描过滤

private fun buildScanFilter(): List {        val scanFilters = ArrayList()        val filter = ScanFilter.Builder()            .setManufacturerData(0, new byte[]{0x6A, 0x7E})            .build()        scanFilters.add(filter)        return scanFilters    }

蓝牙数据ScanResult解析

val scanRecord = scanResult?.scanRecord        val deviceCode: Int =            scanRecord?.getManufacturerSpecificData(1)?.let { 100 * it[0] + it[1] } ?: 0        val deviceName = scanRecord?.getManufacturerSpecificData(2)?.let { bytes ->            val name = String(bytes.sliceArray(1 until bytes.size))            if (bytes[0].toInt() == 0) {                "$name..."            } else {                name            }        } ?: "null"

关键词: