Android Bluetooth: получить идентификаторы UUID обнаруженных устройств
Сейчас я работаю над небольшой библиотекой bluetooth для Android и пытаюсь получить все сервисные идентификаторы устройств, которые я обнаружил в своем окружении.
Когда мой приемник вещания получает BluetoothDevice.ACTION_FOUND
намеренно, я извлекаю устройство и звоню:
device.fetchUuidsWithSdp();
Это приведет BluetoothDevice.ACTION_UUID
намерения для каждого найденного устройства, и я обрабатываю их одним и тем же приемником:
BluetoothDevice d = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Parcelable[] uuidExtra = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
if(uuidExtra == null) {
Log.e(TAG, "UUID = null");
}
if(d != null && uuidExtra != null)
Log.d(TAG, d.getName() + ": " + uuidExtra.toString());
Дело в том, что uuidExtra
всегда null
,
Как я могу получить все UUIDs окружающих устройств?
РЕДАКТИРОВАТЬ:
Я работаю на Nexus 7. Я попробовал код, который я нашел в Интернете, и это также дает мне NullPointerException: http://digitalhacksblog.blogspot.de/2012/05/android-example-bluetooth-discover-and.html
Спасибо.
5 ответов
В документации об этом говорится...
Всегда содержит дополнительное поле
BluetoothDevice.EXTRA_UUID
Однако, как и вы, я обнаружил, что это не так.
Если вы позвоните fetchUuidsWithSdp()
пока обнаружение устройства все еще происходит BluetoothDevice.EXTRA_UUID
может быть нулевым
Вы должны ждать, пока вы не получите BluetoothAdapter.ACTION_DISCOVERY_FINISHED
прежде чем делать какие-либо звонки fetchUuidsWithSdp()
,
ПРИМЕЧАНИЕ. Это решение относится к
CLASSIC
блютуз а неBLE
, ЗаBLE
проверить, как отправить специфические данные производителя в рекламодателя на периферийной стороне
Проблема с загрузкой Uuids заключается в том, что у вас есть только один адаптер Bluetooth, и у нас не может быть параллельных вызовов API, которые используют адаптер для своих целей.
Как указал Эдди, подожди BluetoothAdapter.ACTION_DISCOVERY_FINISHED
а затем позвоните fetchUuidsWithSdp()
,
Тем не менее, это не может гарантировать, что uuids будет получен для всех устройств. В дополнение к этому нужно ждать каждого последующего вызова fetchuuidsWithSdp()
для завершения, а затем позвоните этому методу для другого устройства.
Смотрите код ниже -
ArrayList<BluetoothDevice> mDeviceList = new ArrayList<BluetoothDevice>();
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = (BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
mDeviceList.add(device);
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
// discovery has finished, give a call to fetchUuidsWithSdp on first device in list.
if (!mDeviceList.isEmpty()) {
BluetoothDevice device = mDeviceList.remove(0);
boolean result = device.fetchUuidsWithSdp();
}
} else if (BluetoothDevice.ACTION_UUID.equals(action)) {
// This is when we can be assured that fetchUuidsWithSdp has completed.
// So get the uuids and call fetchUuidsWithSdp on another device in list
BluetoothDevice deviceExtra = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Parcelable[] uuidExtra = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
System.out.println("DeviceExtra address - " + deviceExtra.getAddress());
if (uuidExtra != null) {
for (Parcelable p : uuidExtra) {
System.out.println("uuidExtra - " + p);
}
} else {
System.out.println("uuidExtra is still null");
}
if (!mDeviceList.isEmpty()) {
BluetoothDevice device = mDeviceList.remove(0);
boolean result = device.fetchUuidsWithSdp();
}
}
}
}
ОБНОВЛЕНИЕ: Последние версии Android (мм и выше) приведет к запуску процесса сопряжения с каждым устройством
Я полагаю, что вы должны быть в паре с устройством, чтобы получить uuids. По крайней мере, это то, что случилось со мной.
Вот хороший пример того, как получить UUID характеристик сервиса от сервиса, который я сделал для получения устройств измерения частоты пульса:
private class HeartRateBluetoothGattCallback extends BluetoothGattCallback {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
logMessage("CONNECTED TO " + gatt.getDevice().getName(), false, false);
gatt.discoverServices();
} else if(newState == BluetoothProfile.STATE_DISCONNECTED) {
logMessage("DISCONNECTED FROM " + gatt.getDevice().getName(), false, false);
if(mIsTrackingHeartRate)
handleHeartRateDeviceDisconnection(gatt);
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
logMessage("DISCOVERING SERVICES FOR " + gatt.getDevice().getName(), false, false);
if(mDesiredHeartRateDevice != null &&
gatt.getDevice().getAddress().equals(mDesiredHeartRateDevice.getBLEDeviceAddress())) {
if(subscribeToHeartRateGattServices(gatt)) {
mIsTrackingHeartRate = true;
setDeviceScanned(getDiscoveredBLEDevice(gatt.getDevice().getAddress()), DiscoveredBLEDevice.CONNECTED);
broadcastHeartRateDeviceConnected(gatt.getDevice());
} else
broadcastHeartRateDeviceFailedConnection(gatt.getDevice());
} else {
parseGattServices(gatt);
disconnectGatt(getDiscoveredBLEDevice(gatt.getDevice().getAddress()));
}
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
if(characteristic.getUuid().equals(UUID.fromString(HEART_RATE_VALUE_CHAR_READ_ID))) {
int flag = characteristic.getProperties();
int format = -1;
if ((flag & 0x01) != 0)
format = BluetoothGattCharacteristic.FORMAT_UINT16;
else
format = BluetoothGattCharacteristic.FORMAT_UINT8;
Integer heartRateValue = characteristic.getIntValue(format, 1);
if(heartRateValue != null)
broadcastHeartRateValue(heartRateValue);
else
Log.w(SERVICE_NAME, "UNABLE TO FORMAT HEART RATE DATA");
}
};
};
private void parseGattServices(BluetoothGatt gatt) {
boolean isHeartRate = false;
for(BluetoothGattService blueToothGattService : gatt.getServices()) {
logMessage("GATT SERVICE: " + blueToothGattService.getUuid().toString(), false, false);
if(blueToothGattService.getUuid().toString().contains(HEART_RATE_DEVICE_SERVICE_CHARACTERISTIC_PREFIX))
isHeartRate = true;
}
if(isHeartRate) {
setDeviceScanned(getDiscoveredBLEDevice(gatt.getDevice().getAddress()), DiscoveredBLEDevice.IS_HEART_RATE);
broadcastHeartRateDeviceFound(getDiscoveredBLEDevice(gatt.getDevice().getAddress()));
} else
setDeviceScanned(getDiscoveredBLEDevice(gatt.getDevice().getAddress()), DiscoveredBLEDevice.NOT_HEART_RATE);
}
private void handleHeartRateDeviceDisconnection(BluetoothGatt gatt) {
broadcastHeartRateDeviceDisconnected(gatt.getDevice());
gatt.close();
clearoutHeartRateData();
scanForHeartRateDevices();
}
private void disconnectGatt(DiscoveredBLEDevice device) {
logMessage("CLOSING GATT FOR " + device.getBLEDeviceName(), false, false);
device.getBlueToothGatt().close();
device.setBlueToothGatt(null);
mInDiscoveryMode = false;
}
private boolean subscribeToHeartRateGattServices(BluetoothGatt gatt) {
for(BluetoothGattService blueToothGattService : gatt.getServices()) {
if(blueToothGattService.getUuid().toString().contains(HEART_RATE_DEVICE_SERVICE_CHARACTERISTIC_PREFIX)) {
mHeartRateGattService = blueToothGattService;
for(BluetoothGattCharacteristic characteristic : mHeartRateGattService.getCharacteristics()) {
logMessage("CHARACTERISTIC UUID = " + characteristic.getUuid().toString(), false, false);
for(BluetoothGattDescriptor descriptor :characteristic.getDescriptors()) {
logMessage("DESCRIPTOR UUID = " + descriptor.getUuid().toString(), false, false);
}
if(characteristic.getUuid().equals(UUID.fromString(HEART_RATE_VALUE_CHAR_READ_ID))) {
gatt.setCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(HEART_RATE_VALUE_CHAR_DESC_ID));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
return gatt.writeDescriptor(descriptor);
}
}
break; //break out of master for-loop
}
}
return false;
}
device.getUuids() используйте это, чтобы получить все uuid этого сопряженного устройства в форме ParcelUuid; Пример кода ниже:-
private void get_uuid_from_paired_devices(){
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
for (BluetoothDevice device: pairedDevices){
for (ParcelUuid uuid: device.getUuids()){
String uuid_string = uuid.toString();
Log.d(TAG, "uuid : "+uuid_string);
}
}
}
Ниже работал для меня, чтобы получить записи с удаленного устройства
-0-
registerReceiver(..,
new IntentFilter(BluetoothDevice.ACTION_UUID));
-1- device.fetchUuidsWithSdp ();
-2 изнутри ресивера
if (BluetoothDevice.ACTION_UUID.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Parcelable[] uuids = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
for (Parcelable ep : uuids) {
Utilities.print("UUID records : "+ ep.toString());
}
}
Вы также можете получить автономные кэшированные записи UUID с помощью
BluetoothDevice.getUuids();