FastBle
FastBle copied to clipboard
what to get manufacturerSpecificData in onLeScan(BleDevice bleDevice) method?
I can find bleDevice.getScanRecord(),but did not found : SparseArray<byte[]> mandufacturerData = scanRecord.getManufacturerSpecificData(); for eg: ble外围设备可以在广播的时候设定AdvertiseData的magic number【manufacturerId 和 manufacturerSpecificData】。这样即使定义service uuid跟别人的有冲突,也可以在中心过滤该magic number来找到符合自己需求的外围设备
外围构建AdvertiseData
AdvertiseData.Builder() .setIncludeDeviceName(true) .addServiceUuid(ParcelUuid.fromString("00007777-0000-1000-8000-00805f9b34fb")) .addManufacturerData(0x7777, new byte[]{0x07, 0x07}) .build();
中心处理AdvertiseData中的
final ScanCallback scanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); ScanRecord scanRecord = result.getScanRecord(); SparseArray<byte[]> mandufacturerData = scanRecord.getManufacturerSpecificData();
此时可以根据mandufacturerData来匹配自己设定的外围设备
作者:RDuwan 链接:https://www.jianshu.com/p/2fd90849d8e0 。
同问,有些厂商设备数据是通过ScanRecord的manufacturerSpecificData传递的,但是没有找到获取的方法
同问,有些厂商设备数据是通过ScanRecord的manufacturerSpecificData传递的,但是没有找到获取的方法
其实收到了,只是我没找到数据位,不好意思
基于sdk32,也就是Android13源码的 android.bluetooth.le.ScanRecord.java这个类的parseFromBytes(byte[] scanRecord)方法,搞出来一个解析字节数组,可以拿到manufacturerData的字节数组
public class ScanRecordUtil {
private static final int DATA_TYPE_FLAGS = 0x01;
private static final int DATA_TYPE_LOCAL_NAME_SHORT = 0x08;
private static final int DATA_TYPE_LOCAL_NAME_COMPLETE = 0x09;
private static final int DATA_TYPE_TX_POWER_LEVEL = 0x0A;
private static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF;
....
public static SparseArray<byte[]> parseManufactureFromScanRecordBytes(byte[] scanRecord) {
if (scanRecord == null) {
return null;
}
int currentPos = 0;
int advertiseFlag = -1;
List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>();
List<ParcelUuid> serviceSolicitationUuids = new ArrayList<ParcelUuid>();
String localName = null;
int txPowerLevel = Integer.MIN_VALUE;
SparseArray<byte[]> manufacturerData = new SparseArray<byte[]>();
Map<ParcelUuid, byte[]> serviceData = new ArrayMap<ParcelUuid, byte[]>();
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.
int fieldType = scanRecord[currentPos++] & 0xFF;
switch (fieldType) {
case DATA_TYPE_FLAGS:
advertiseFlag = scanRecord[currentPos] & 0xFF;
break;
case DATA_TYPE_LOCAL_NAME_SHORT:
case DATA_TYPE_LOCAL_NAME_COMPLETE:
localName = new String(
extractBytes(scanRecord, currentPos, dataLength));
break;
case DATA_TYPE_TX_POWER_LEVEL:
txPowerLevel = scanRecord[currentPos];
break;
case DATA_TYPE_MANUFACTURER_SPECIFIC_DATA:
// The first two bytes of the manufacturer specific data are
// manufacturer ids in little endian.
int manufacturerId = ((scanRecord[currentPos + 1] & 0xFF) << 8)
+ (scanRecord[currentPos] & 0xFF);
byte[] manufacturerDataBytes = extractBytes(scanRecord, currentPos + 2,
dataLength - 2);
manufacturerData.put(manufacturerId, manufacturerDataBytes);
break;
default:
// Just ignore, we don't handle such data type.
break;
}
currentPos += dataLength;
}
if (serviceUuids.isEmpty()) {
serviceUuids = null;
}
return manufacturerData;
} catch (Exception e) {
Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord));
return manufacturerData;
}
}
}
...
// Helper method to extract bytes from byte array.
private static byte[] extractBytes(byte[] scanRecord, int start, int length) {
byte[] bytes = new byte[length];
System.arraycopy(scanRecord, start, bytes, 0, length);
return bytes;
}
在Fastble这个库使用 BleManager.getInstance().scan()扫描回调的方法中拿到了字节数组,进行遍历即可
@Override
public void onScanFinished(List<BleDevice> scanResultList) {
for (int i = 0; i < scanResultList.size(); i++) {
byte[] scanRecordByte = targetBleDevice.getScanRecord();
SparseArray<byte[]> manufactureSparseArray = ScanRecordUtil.parseManufactureFromScanRecordBytes(scanRecordByte);
Log.d(TAG, "man:" + manufactureSparseArray.toString());
for(int j = 0; j < manufactureSparseArray .size(); j++){
int manufacturerId = manufactureSparseArray.keyAt(j);
byte[] nima = manufactureSparseArray.get(manufacturerId);
Log.d(TAG,"这个是什么玩意:manufacturerId:"+manufacturerId+"<----->"+ new String(nima));
}
}
}
这个方法已经在基于Android10的设备上通过验证,正确拿到从机(也就是外围设备,也就是服务器)自己定义的Manufacture,注意,服务器这个自定义不要超过31个字节,否则传输不过来. 顺便其他localName,advertiseFlag等属性,如法炮制即可