本文旨在于解析出16位UUID,对于128位的UUID应该方法大同小异,没测试过的不贴出来
16bit UUID:
128位的UUID相当长,设备间为了识别数据的类型需要发送长达16字节的数据。为了提高传输效率,蓝牙技术联盟(SIG)定义了一个称为“UUID基数”的128位通用唯一识别码,结合一个较短的16位数使用。二者仍然遵循通用唯一识别码的分配规则,只不过在设备间传输常用的UUID时,只发送较短的16位版本,接收方收到后补上蓝牙UUID基数即可。
蓝牙UUID基数如下:
00000000 – 0000 – 1000 – 8000 – 008059B34FB
如要发送的16位UUID为0x2A01,完整的128的UUID便是:
00002A01 – 0000 – 1000 – 8000 – 008059B34FB
如果需要其他位的UUID自己去试验,欢迎把实验结果告诉我,不扯太多,还是扯代码:
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
final ScanRecordUtil scanRecordUtil = ScanRecordUtil.parseFromBytes(scanRecord);
Logger.e(TAG, "scanRecordUtil" + scanRecordUtil.getUuids16S());
}
};
这是我实验的扫描函数
接下来是ScanRecordUtil这个类,这个类主要用来处理广播包的数据
/** * 我只把我能用的写了出来,没用的我没看懂 */ public class ScanRecordUtil { private static final String TAG = "---ScanRecordUtil"; private static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE = 0x03; private static final int DATA_TYPE_LOCAL_NAME_COMPLETE = 0x09; // Flags of the advertising data. private final int mAdvertiseFlags; // Transmission power level(in dB). private final int mTxPowerLevel; // Local name of the Bluetooth LE device. private final String mDeviceName; //Raw bytes of scan record. private final byte[] mBytes; private ListmUuids16S; //16位UUID,之前有其他的UUID占着名称我就取的这名称 /** * Returns the advertising flags indicating the discoverable mode and capability of the device. * Returns -1 if the flag field is not set. */ public int getAdvertiseFlags() { return mAdvertiseFlags; } /** * Returns the transmission power level of the packet in dBm. Returns {@link Integer#MIN_VALUE} * if the field is not set. This value can be used to calculate the path loss of a received * packet using the following equation: * * pathloss = txPowerLevel - rssi */ public int getTxPowerLevel() { return mTxPowerLevel; } /** * Returns the local name of the BLE device. The is a UTF-8 encoded string. * 拿到设备的名称 */ @Nullable public String getDeviceName() { return mDeviceName; } /** * Returns raw bytes of scan record. */ public byte[] getBytes() { return mBytes; } private ScanRecordUtil( List
mUuids16S, int advertiseFlags, int txPowerLevel, String localName, byte[] bytes) { mDeviceName = localName; mAdvertiseFlags = advertiseFlags; mTxPowerLevel = txPowerLevel; mBytes = bytes; this.mUuids16S = mUuids16S; } /** * 获取16位UUID * @return */ public List getUuids16S() { return mUuids16S; } /** * 得到ScanRecordUtil 对象,主要逻辑 * @param scanRecord * @return */ public static ScanRecordUtil parseFromBytes(byte[] scanRecord) { if (scanRecord == null) { return null; } int currentPos = 0; int advertiseFlag = -1; List uuids16 = new ArrayList<>(); String localName = null; int txPowerLevel = Integer.MIN_VALUE; try { while (currentPos < scanRecord.length) { // length is unsigned int. int length = scanRecord[currentPos++] & 0xFF; if (length == 0) { break; } // / Note the length includes the length of the field type itself. int dataLength = length - 1; // fieldType is unsigned int. // 获取广播AD type int fieldType = scanRecord[currentPos++] & 0xFF; switch (fieldType) { case DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE: parseServiceUuid16(scanRecord, currentPos, dataLength, uuids16); break; case DATA_TYPE_LOCAL_NAME_COMPLETE: localName = new String(extractBytes(scanRecord, currentPos, dataLength)); break; default: break; } currentPos += dataLength; } if (uuids_16.isEmpty()){ uuids_16 = null; } return new ScanRecordUtil(uuids16, advertiseFlag, txPowerLevel, localName, scanRecord); } catch (Exception e) { Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord)); // As the record is invalid, ignore all the parsed results for this packet // and return an empty record with raw scanRecord bytes in results return new ScanRecordUtil( null, -1, Integer.MIN_VALUE, null, scanRecord); } } /** * byte数组转16进制 * @param bytes * @return */ public static String bytesToHexFun3(byte[] bytes) { StringBuilder buf = new StringBuilder(bytes.length * 2); for (byte b : bytes) { // 使用String的format方法进行转换 buf.append(String.format("%02x", new Integer(b & 0xff))); } return buf.toString(); } // 16位UUID private static int parseServiceUuid16(byte[] scanRecord, int currentPos, int dataLength, List serviceUuids) { while (dataLength > 0) { byte[] uuidBytes = extractBytes(scanRecord, currentPos, dataLength); final byte[] bytes = new byte[uuidBytes.length]; Logger.e(TAG, "dataLength==uuidBytes.length" + (dataLength == uuidBytes.length)); for (int i = 0; i < uuidBytes.length; i++) { bytes[i] = uuidBytes[uuidBytes.length - 1 - i]; } serviceUuids.add(bytesToHexFun3(bytes)); dataLength -= dataLength; currentPos += dataLength; } return currentPos; } // Helper method to extract bytes from byte array. //b帮助我们解析byte数组 private static byte[] extractBytes(byte[] scanRecord, int start, int length) { byte[] bytes = new byte[length]; System.arraycopy(scanRecord, start, bytes, 0, length); return bytes; } }
用这些代码就能得到16位的UUID,这是我的项目里面的东西,对于你们能不能用我就不清楚了,既然我用了网上的资源解决了自己的问题,
我也要把我的知识贡献出来,开源才能使社会发展更快!