android BluetoothDevice.getName () return null

En algún momento, BluetoothDevice.getName () devuelve null. ¿Cómo puedo arreglarlo? remoteDeviceName puede ser nulo en el siguiente código. Y necesito distinguir mi dispositivo y otros dispositivos por remoteDeviceName.

BluetoothAdapter.getDefaultAdapter().startLeScan(new LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord) { String remoteDeviceName = device.getName(); Log.d("Scanning", "scan device " + remoteDeviceName); }); 

Finalmente, descubrí la solución:

1. Para el dispositivo conectado:

Lea el nombre del dispositivo desde la función gatt org.bluetooth.characteristic.gap.device_name del servicio org.bluetooth.service.generic_access .

2. Para dispositivo no conectado:

  /** * Get device name from ble advertised data */ private LeScanCallback mScanCb = new LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord) { final BleAdvertisedData badata = BleUtil.parseAdertisedData(scanRecord); String deviceName = device.getName(); if( deviceName == null ){ deviceName = badata.getName(); } } ////////////////////// Helper Classes: BleUtil and BleAdvertisedData /////////////// final public class BleUtil { private final static String TAG=BleUtil.class.getSimpleName(); public static BleAdvertisedData parseAdertisedData(byte[] advertisedData) { List uuids = new ArrayList(); String name = null; if( advertisedData == null ){ return new BleAdvertisedData(uuids, name); } ByteBuffer buffer = ByteBuffer.wrap(advertisedData).order(ByteOrder.LITTLE_ENDIAN); while (buffer.remaining() > 2) { byte length = buffer.get(); if (length == 0) break; byte type = buffer.get(); switch (type) { case 0x02: // Partial list of 16-bit UUIDs case 0x03: // Complete list of 16-bit UUIDs while (length >= 2) { uuids.add(UUID.fromString(String.format( "%08x-0000-1000-8000-00805f9b34fb", buffer.getShort()))); length -= 2; } break; case 0x06: // Partial list of 128-bit UUIDs case 0x07: // Complete list of 128-bit UUIDs while (length >= 16) { long lsb = buffer.getLong(); long msb = buffer.getLong(); uuids.add(new UUID(msb, lsb)); length -= 16; } break; case 0x09: byte[] nameBytes = new byte[length-1]; buffer.get(nameBytes); try { name = new String(nameBytes, "utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } break; default: buffer.position(buffer.position() + length - 1); break; } } return new BleAdvertisedData(uuids, name); } } public class BleAdvertisedData { private List mUuids; private String mName; public BleAdvertisedData(List uuids, String name){ mUuids = uuids; mName = name; } public List getUuids(){ return mUuids; } public String getName(){ return mName; } } 

BluetoothDevice.getName() puede devolver null si no se pudo determinar el nombre. Esto podría deberse a una cantidad de factores. De todos modos, el nombre es el nombre descriptivo del dispositivo y no debe usarse para distinguirlo de otros dispositivos. En su lugar, use la dirección de hardware a través de getAddress() .

Estaba tratando de mostrar el nombre de mi módulo Bluetooth RN4020 y me enfrenté al mismo problema. Encontrado el problema en el foro de Microchip:

Si habilitó el servicio privado o MLDP, el número máximo de bytes del nombre del dispositivo es de 6 bytes, debido a la limitación de la carga útil del anuncio de 31 bytes.

Había establecido el nombre del dispositivo a 9 caracteres. Establecer el nombre en 4 bytes solucionó el problema.

Si reconoce los UUID de sus servicios personalizados para que sepa cuál es su dispositivo, también puede conectarse al dispositivo y leer su nombre (si es más de 6 bytes en mi caso). Esto también fue sugerido en el foro de Microchips.

http://www.microchip.com/forums/m846328.aspx

Descubrí que si consulta el nombre del dispositivo inmediatamente después de recogerlo en el escaneo, puede devolver nulo. Para evitar esto, sondear un ejecutable cada segundo más o menos en la hebra de la interfaz de usuario un máximo de 3 veces (tan 3 segundos), y el nombre generalmente se resuelve para entonces.

Tenga en cuenta que, en el fragmento proporcionado, la clase Runnable implementa Runnable , por lo que puedo pasar this a View.postDelayed(Runnable action, long delayMillis)

  private static final int MAX_NAME_CHECKS = 3; private static final int NAME_CHECK_PERIOD = 1000; int nameChecks; @Override public void run() { resolveName(); } /** * Checks for the device name, for a maximum of {@link ViewHolder#MAX_NAME_CHECKS} * as the name may not have been resolved at binding. */ private void resolveName() { if (device != null) { String name = device.getName(); boolean isEmptyName = TextUtils.isEmpty(name); if (isEmptyName) deviceName.setText(R.string.unknown_device); else deviceName.setText(name); // Check later if device name is resolved if (nameChecks++ < MAX_NAME_CHECKS && isEmptyName) itemView.postDelayed(this, NAME_CHECK_PERIOD); } } 

En Marshmallow, utilice ScanRecord.getDeviceName() para recuperar el nombre local incrustado en el registro de exploración.

BluetoothDevice.getName() no es confiable si el nombre local se incluye en una respuesta de escaneo, en lugar de en el paquete publicitario inmediato.

  @Override public void onScanResult(int callbackType, ScanResult scanResult) { super.onScanResult(callbackType, scanResult); // Retrieve device name via ScanRecord. String deviceName = scanResult.getScanRecord().getDeviceName(); } 

Sé que esto es antiguo, pero esta respuesta más orientada a las especificaciones puede ayudar a responder algunos casos.

En Bluetooth Low Energy, los datos publicitarios y de respuesta de escaneo solo requieren tener la dirección Bluetooth. Los datos publicitarios son la forma en que un endpoint cliente BTLE descubre un dispositivo de servicio. Un cliente puede solicitar una respuesta de escaneo y obtener más datos. El nombre del dispositivo es opcional en esta información. Sin embargo, la especificación BTLE requiere que todos los puntos finales de Bluetooth de baja energía admitan el servicio de acceso genérico que se requiere para admitir la característica de nombre del dispositivo. Desafortunadamente, para leer esa característica, el Android primero debe conectarse y hacer un descubrimiento del servicio. Si la respuesta de publicidad / escaneo no proporciona la información, no creo que Android se conecte al dispositivo para obtener el nombre. Al menos, nunca he visto ninguna indicación de conexión sin que la aplicación solicite específicamente una conexión. Esto no es lo que desea que se le solicite si desea tomar la decisión de conectarse.

Afortunadamente, la mayoría de los dispositivos BTLE con los que he trabajado proporcionan su nombre en la respuesta de publicidad o escaneo.

Otra posibilidad es que el dispositivo pueda colocar el nombre en la parte de respuesta de escaneo del anuncio. Dependiendo de cómo se haya configurado el escáner BTLE de Android, uno podría obtener solo los datos de publicidad y no la respuesta de escaneo. En este caso, el nombre no se encontrará si el dispositivo lo coloca en la respuesta de escaneo. Sin embargo, la configuración predeterminada del escáner es tal que se debe recibir una respuesta de escaneo antes de pasar los datos de escaneo a la aplicación.