我试图获得uUID的ble设备。我正在关注Android开发人员指南,到目前为止我只能得到设备名称和rssi。我试图得到Uuid的设备,扫描方法看起来像这样:
public void onLeScan(final BluetoothDevice device, int rssi,byte[] scanRecord) {
ParcelUuid[] myUUid =device.getUuids();
for(ParcelUuid a :myUUid){
Log.d("UUID",a.getUuid().toString());
}
String s = new String(scanRecord);
int len = scanRecord.length;
String scanRecords =new String(scanRecord) ;
deviceMap.put(device.getName().toString(), rssi);
Message msg = MainActivity.myHandler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putCharSequence("dev_name", device.getName().toString());
bundle.putCharSequence("rssi", Integer.toString(rssi));
msg.setData(bundle);
MainActivity.myHandler.sendMessage(msg);
}
返回 - btif_gattc_upstreams_evt:事件4096
如果你想获得UUID /任何其他数据,例如制造商数据在BLE Scan之后的scanRec []字节之外,首先需要了解那些广告数据包的数据格式。
来自Bluetooth.org:
理论太多了,想看一些代码片段?下面的这个函数将直接打印解析的原始数据字节。现在,您需要知道每种类型的代码,以了解哪些数据包引用了哪些信息。例如键入:0x09,表示BLE设备名称,类型:0x07,表示UUID。
public void printScanRecord (byte[] scanRecord) {
// Simply print all raw bytes
try {
String decodedRecord = new String(scanRecord,"UTF-8");
Log.d("DEBUG","decoded String : " + ByteArrayToString(scanRecord));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// Parse data bytes into individual records
List<AdRecord> records = AdRecord.parseScanRecord(scanRecord);
// Print individual records
if (records.size() == 0) {
Log.i("DEBUG", "Scan Record Empty");
} else {
Log.i("DEBUG", "Scan Record: " + TextUtils.join(",", records));
}
}
public static String ByteArrayToString(byte[] ba)
{
StringBuilder hex = new StringBuilder(ba.length * 2);
for (byte b : ba)
hex.append(b + " ");
return hex.toString();
}
public static class AdRecord {
public AdRecord(int length, int type, byte[] data) {
String decodedRecord = "";
try {
decodedRecord = new String(data,"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Log.d("DEBUG", "Length: " + length + " Type : " + type + " Data : " + ByteArrayToString(data));
}
// ...
public static List<AdRecord> parseScanRecord(byte[] scanRecord) {
List<AdRecord> records = new ArrayList<AdRecord>();
int index = 0;
while (index < scanRecord.length) {
int length = scanRecord[index++];
//Done once we run out of records
if (length == 0) break;
int type = scanRecord[index];
//Done if our record isn't a valid type
if (type == 0) break;
byte[] data = Arrays.copyOfRange(scanRecord, index+1, index+length);
records.add(new AdRecord(length, type, data));
//Advance
index += length;
}
return records;
}
// ...
}
在解析之后,这些数据字节会更有意义,您可以找出下一级解码。
正如评论中所提到的,BLE设备并不真正具有特定的UUID(但对于所包含的服务而言,其实很多)。然而,诸如iBeacon的一些方案在广告包中的制造商特定数据记录中编码唯一标识符。
这是一个非常低效但概念上简单的方法,将整个scanRecord转换为十六进制字符串表示以进行调试打印:
String msg = "payload = ";
for (byte b : scanRecord)
msg += String.format("%02x ", b);
注意,这将包括实际广告包和许多无意义的尾随字节,在解析广告包本身中包含的结构(长度字段)之后应该忽略这些字节。
我在开发我的应用程序时遇到了同样的问题,但在阅读了以下链接的文档后:https://developer.android.com/reference/android/bluetooth/le/ScanResult.html
关于UUID(取决于您正在开发的API)的重要类是:
AdvertiseData AdvertiseData.Builder ScanRecord ScanResult
在阅读了这些类的文档之后,这是我编写的代码,用于获取正在扫描的任何设备的UUID:
//对于API <21:
private BluetoothAdapter.LeScanCallback scanCallBackLe =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, final byte[] scanRecord) {
final int RSSI = rssi;
if (RSSI >= signalThreshold){
scanHandler.post(new Runnable() {
@Override
public void run() {
AdvertiseData data = new AdvertiseData.Builder()
.addServiceUuid(ParcelUuid
.fromString(UUID
.nameUUIDFromBytes(scanRecord).toString())).build();
scannerActivity.addDevice(device, RSSI, getUUID(data));
}
});
}
}
};
//For APIs less than 21, Returns Device UUID
public String getUUID(AdvertiseData data){
List<ParcelUuid> UUIDs = data.getServiceUuids();
//ToastMakers.message(scannerActivity.getApplicationContext(), UUIDs.toString());
String UUIDx = UUIDs.get(0).getUuid().toString();
Log.e("UUID", " as list ->" + UUIDx);
return UUIDx;
}
对于API> 21:
private ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, final ScanResult result) {
Log.i("callbackType", String.valueOf(callbackType));
Log.i("result", result.toString());
final int RSSI = result.getRssi();
if (RSSI>=signalThreshold) {
scanHandler.post(
new Runnable() {
@Override
public void run() {
BluetoothDevice device = result.getDevice();
scannerActivity.addDevice(device, result.getRssi(), getUUID(result));
}
});
}
} ...}
//For APIs greater than 21, Returns Device UUID
public String getUUID(ScanResult result){
String UUIDx = UUID
.nameUUIDFromBytes(result.getScanRecord().getBytes()).toString();
ToastMakers.message(scannerActivity.getApplicationContext(), UUIDx);
Log.e("UUID", " as String ->>" + UUIDx);
return UUIDx;
}
我能够使用此代码获取任何设备的128位UUID。 :)
我找到了一个解析广告包的java库
您可以使用标准的android BluetoothGattCharacteristic apis,如getFloatValue(int formatType,int offset),getIntValue(int formatType,int offset),getStringValue(int offset)..请参阅非常好的android开发者网站教程here
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
int flag = characteristic.getProperties();
int format = -1;
if ((flag & 0x01) != 0) {
format = BluetoothGattCharacteristic.FORMAT_UINT16;
Log.d(TAG, "Heart rate format UINT16.");
} else {
format = BluetoothGattCharacteristic.FORMAT_UINT8;
Log.d(TAG, "Heart rate format UINT8.");
}
final int heartRate = characteristic.getIntValue(format, 1);
Log.d(TAG, "Received heart rate: " + heartRate);
intent.putExtra(EXTRA_DATA, String.valueOf(heartRate));
}