Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

BleBroadcastUtils.java 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. package com.elinkthings.ailinksecrettooldemo;
  2. import android.os.ParcelUuid;
  3. import java.util.ArrayList;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7. /**
  8. * xing<br>
  9. * 2019/3/7<br>
  10. * 广播解析工具类
  11. */
  12. public class BleBroadcastUtils {
  13. private static final int DATA_TYPE_FLAGS = 0x01;
  14. private static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL = 0x02;
  15. private static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE = 0x03;
  16. private static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL = 0x04;
  17. private static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE = 0x05;
  18. private static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL = 0x06;
  19. private static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE = 0x07;
  20. private static final int DATA_TYPE_LOCAL_NAME_SHORT = 0x08;
  21. private static final int DATA_TYPE_LOCAL_NAME_COMPLETE = 0x09;
  22. private static final int DATA_TYPE_TX_POWER_LEVEL = 0x0A;
  23. private static final int DATA_TYPE_SERVICE_DATA_16_BIT = 0x16;
  24. private static final int DATA_TYPE_SERVICE_DATA_32_BIT = 0x20;
  25. private static final int DATA_TYPE_SERVICE_DATA_128_BIT = 0x21;
  26. private static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF;
  27. private static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA_MOVE = 0xFE;
  28. private List<byte[]> mManufacturerByte;
  29. private byte[] mManufacturerByteMove;
  30. private List<ParcelUuid> mServiceUuids;
  31. private int mAdvertiseFlag = -1;
  32. private Map<ParcelUuid, byte[]> mServiceData;
  33. private String mDeviceName;
  34. public BleBroadcastUtils(byte[] scanRecord) {
  35. this(scanRecord, -1);
  36. }
  37. public BleBroadcastUtils(byte[] scanRecord, int manufacturerId) {
  38. mManufacturerByte=new ArrayList<>();
  39. getBleData(scanRecord, manufacturerId);
  40. }
  41. // Helper method to extract bytes from byte array.
  42. private static byte[] extractBytes(byte[] scanRecord, int start, int length) {
  43. byte[] bytes = new byte[length];
  44. System.arraycopy(scanRecord, start, bytes, 0, length);
  45. return bytes;
  46. }
  47. public List<byte[]> getManufacturerSpecificData() {
  48. return mManufacturerByte;
  49. }
  50. public byte[] getManufacturerByteMove() {
  51. return mManufacturerByteMove;
  52. }
  53. /**
  54. * 服务uuid
  55. *
  56. * @return {@link List}<{@link ParcelUuid}>
  57. */
  58. public List<ParcelUuid> getServiceUuids() {
  59. return mServiceUuids;
  60. }
  61. /**
  62. * 广告标志
  63. *
  64. * @return int
  65. */
  66. public int getAdvertiseFlag() {
  67. return mAdvertiseFlag;
  68. }
  69. public String getDeviceName() {
  70. return mDeviceName;
  71. }
  72. /**
  73. * 服务数据
  74. *
  75. * @return {@link Map}<{@link ParcelUuid}, {@link byte[]}>
  76. */
  77. public Map<ParcelUuid, byte[]> getServiceData() {
  78. return mServiceData;
  79. }
  80. /**
  81. * 服务数据
  82. *
  83. * @param serviceDataUuid 服务数据uuid
  84. * @return {@link byte[]}
  85. */
  86. public byte[] getServiceData(final ParcelUuid serviceDataUuid) {
  87. //noinspection ConstantConditions
  88. if (serviceDataUuid == null || mServiceData == null) {
  89. return null;
  90. }
  91. return mServiceData.get(serviceDataUuid);
  92. }
  93. private void getBleData(byte[] scanRecord, int id) {
  94. int currentPos = 0;
  95. mServiceUuids = new ArrayList<>();
  96. try {
  97. while (currentPos < scanRecord.length) {
  98. int length = scanRecord[currentPos++] & 0xFF;
  99. if (length == 0)
  100. break;
  101. int dataLength = length - 1;
  102. int fieldType = scanRecord[currentPos++] & 0xFF;
  103. switch (fieldType) {
  104. case DATA_TYPE_FLAGS:
  105. mAdvertiseFlag = scanRecord[currentPos] & 0xFF;
  106. break;
  107. case DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL:
  108. case DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE:
  109. parseServiceUuid(scanRecord, currentPos, dataLength, BluetoothUuid.UUID_BYTES_16_BIT, mServiceUuids);
  110. break;
  111. case DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL:
  112. case DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE:
  113. parseServiceUuid(scanRecord, currentPos, dataLength, BluetoothUuid.UUID_BYTES_32_BIT, mServiceUuids);
  114. break;
  115. case DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL:
  116. case DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE:
  117. parseServiceUuid(scanRecord, currentPos, dataLength, BluetoothUuid.UUID_BYTES_128_BIT, mServiceUuids);
  118. break;
  119. case DATA_TYPE_SERVICE_DATA_16_BIT:
  120. case DATA_TYPE_SERVICE_DATA_32_BIT:
  121. case DATA_TYPE_SERVICE_DATA_128_BIT:
  122. int serviceUuidLength = BluetoothUuid.UUID_BYTES_16_BIT;
  123. if (fieldType == DATA_TYPE_SERVICE_DATA_32_BIT) {
  124. serviceUuidLength = BluetoothUuid.UUID_BYTES_32_BIT;
  125. } else if (fieldType == DATA_TYPE_SERVICE_DATA_128_BIT) {
  126. serviceUuidLength = BluetoothUuid.UUID_BYTES_128_BIT;
  127. }
  128. final byte[] serviceDataUuidBytes = extractBytes(scanRecord, currentPos,
  129. serviceUuidLength);
  130. final ParcelUuid serviceDataUuid = BluetoothUuid.parseUuidFrom(
  131. serviceDataUuidBytes);
  132. final byte[] serviceDataArray = extractBytes(scanRecord,
  133. currentPos + serviceUuidLength, dataLength - serviceUuidLength);
  134. if (mServiceData == null)
  135. mServiceData = new HashMap<>();
  136. mServiceData.put(serviceDataUuid, serviceDataArray);
  137. break;
  138. case DATA_TYPE_LOCAL_NAME_SHORT:
  139. case DATA_TYPE_LOCAL_NAME_COMPLETE:
  140. mDeviceName = new String(extractBytes(scanRecord, currentPos, dataLength));
  141. break;
  142. case DATA_TYPE_MANUFACTURER_SPECIFIC_DATA:
  143. if (id == -1) {
  144. byte[] bytes = extractBytes(scanRecord, currentPos, dataLength);
  145. mManufacturerByte.add(bytes);
  146. } else {
  147. int manufacturerId = ((scanRecord[currentPos + 1] & 0xFF) << 8) + (scanRecord[currentPos] & 0xFF);
  148. if (manufacturerId == id) {
  149. byte[] bytes = extractBytes(scanRecord, currentPos, dataLength);
  150. mManufacturerByte.add(bytes);
  151. } else {
  152. currentPos += dataLength;
  153. }
  154. }
  155. break;
  156. case DATA_TYPE_MANUFACTURER_SPECIFIC_DATA_MOVE:
  157. mManufacturerByteMove = extractBytes(scanRecord, currentPos, dataLength);
  158. break;
  159. default:
  160. break;
  161. }
  162. currentPos += dataLength;
  163. }
  164. } catch (Exception e) {
  165. mServiceUuids = null;
  166. mManufacturerByte = null;
  167. e.printStackTrace();
  168. }
  169. if (mServiceUuids!=null&&mServiceUuids.isEmpty()) {
  170. mServiceUuids = null;
  171. }
  172. }
  173. // Parse service UUIDs.
  174. private static int parseServiceUuid(byte[] scanRecord, int currentPos, int dataLength, int uuidLength, List<ParcelUuid> serviceUuids) {
  175. while (dataLength > 0) {
  176. byte[] uuidBytes = extractBytes(scanRecord, currentPos, uuidLength);
  177. serviceUuids.add(BluetoothUuid.parseUuidFrom(uuidBytes));
  178. dataLength -= uuidLength;
  179. currentPos += uuidLength;
  180. }
  181. return currentPos;
  182. }
  183. }