import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
- Created by Huanglinqing on 2018/9/4/004.
*/
public class ScanRecordUtil {
/**
- Returns a string composed from a {@link SparseArray}.
*/
static String toString(SparseArray<byte[]> array) {
if (array == null) {
return “null”;
}
if (array.size() == 0) {
return “{}”;
}
StringBuilder buffer = new StringBuilder();
buffer.append(‘{’);
for (int i = 0; i < array.size(); ++i) {
buffer.append(array.keyAt(i)).append(“=”).append(Arrays.toString(array.valueAt(i)));
}
buffer.append(‘}’);
return buffer.toString();
}
/**
- Returns a string composed from a {@link Map}.
*/
static String toString(Map<T, byte[]> map) {
if (map == null) {
return “null”;
}
if (map.isEmpty()) {
return “{}”;
}
StringBuilder buffer = new StringBuilder();
buffer.append(‘{’);
Iterator<Map.Entry<T, byte[]>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<T, byte[]> entry = it.next();
Object key = entry.getKey();
buffer.append(key).append(“=”).append(Arrays.toString(map.get(key)));
if (it.hasNext()) {
buffer.append(", ");
}
}
buffer.append(‘}’);
return buffer.toString();
}
private static final String TAG = “ScanRecordUtil”;
// The following data type values are assigned by Bluetooth SIG.
// For more details refer to Bluetooth 4.1 specification, Volume 3, Part C, Section 18.
private static final int DATA_TYPE_FLAGS = 0x01;
private static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL = 0x02;
private static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE = 0x03;
private static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL = 0x04;
private static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE = 0x05;
private static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL = 0x06;
private static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE = 0x07;
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_SERVICE_DATA = 0x16;
private static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF;
// Flags of the advertising data.
private final int mAdvertiseFlags;
@Nullable
private final List mServiceUuids;
private final SparseArray<byte[]> mManufacturerSpecificData;
private final Map<ParcelUuid, byte[]> mServiceData;
// 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;
/**
-
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 a list of service UUIDs within the advertisement that are used to identify the
-
bluetooth GATT services.
*/
public List getServiceUuids() {
return mServiceUuids;
}
/**
-
Returns a sparse array of manufacturer identifier and its corresponding manufacturer specific
-
data.
*/
public SparseArray<byte[]> getManufacturerSpecificData() {
return mManufacturerSpecificData;
}
/**
-
Returns the manufacturer specific data associated with the manufacturer id. Returns
-
{@code null} if the {@code manufacturerId} is not found.
*/
@Nullable
public byte[] getManufacturerSpecificData(int manufacturerId) {
return mManufacturerSpecificData.get(manufacturerId);
}
/**
- Returns a map of service UUID and its corresponding service data.
*/
public Map<ParcelUuid, byte[]> getServiceData() {
return mServiceData;
}
/**
-
Returns the service data byte array associated with the {@code serviceUuid}. Returns
-
{@code null} if the {@code serviceDataUuid} is not found.
*/
@Nullable
public byte[] getServiceData(ParcelUuid serviceDataUuid) {
if (serviceDataUuid == null) {
return null;
}
return mServiceData.get(serviceDataUuid);
}
/**
-
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 serviceUuids,
SparseArray<byte[]> manufacturerData,
Map<ParcelUuid, byte[]> serviceData,
int advertiseFlags, int txPowerLevel,
String localName, byte[] bytes) {
mServiceUuids = serviceUuids;
mManufacturerSpecificData = manufacturerData;
mServiceData = serviceData;
mDeviceName = localName;
mAdvertiseFlags = advertiseFlags;
mTxPowerLevel = txPowerLevel;
mBytes = bytes;
}
/**
-
Parse scan record bytes to {@link ScanRecord}.
-
-
The format is defined in Bluetooth 4.1 specification, Volume 3, Part C, Section 11 and 18.
-
-
All numerical multi-byte entities and values shall use little-endian byte
-
order.
-
@param scanRecord The scan record of Bluetooth LE advertisement and/or scan response.
-
@hide
*/
public static ScanRecordUtil parseFromBytes(byte[] scanRecord) {
if (scanRecord == null) {
return null;
}
Log.e(TAG + “MYX23P”, “进入parseFromBytes”);
int currentPos = 0;
int advertiseFlag = -1;
List serviceUuids = new ArrayList();
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_SERVICE_UUIDS_16_BIT_PARTIAL:
case DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE:
parseServiceUuid(scanRecord, currentPos,
dataLength,16, serviceUuids);
break;
case DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL:
case DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE:
parseServiceUuid(scanRecord, currentPos, dataLength,
32, serviceUuids);
break;
case DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL:
case DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE:
parseServiceUuid(scanRecord, currentPos, dataLength,
128, serviceUuids);
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_SERVICE_DATA:
// The first two bytes of the service data are service data UUID in little
// endian. The rest bytes are service data.
int serviceUuidLength = 16;
byte[] serviceDataUuidBytes = extractBytes(scanRecord, currentPos,
serviceUuidLength);
ParcelUuid serviceDataUuid = parseUuidFrom(
serviceDataUuidBytes);
byte[] serviceDataArray = extractBytes(scanRecord,
currentPos + serviceUuidLength, dataLength - serviceUuidLength);
serviceData.put(serviceDataUuid, serviceDataArray);
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) +
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
花板技术停滞不前!**
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-8eQW0OZb-1714957442510)]
[外链图片转存中…(img-DmZklhz4-1714957442510)]
[外链图片转存中…(img-7vkcEQvs-1714957442511)]
[外链图片转存中…(img-MJSjncLf-1714957442511)]
[外链图片转存中…(img-HY2DtOn0-1714957442511)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!