2014-10-10 9 views
10

Manchmal gibt BluetoothDevice.getName() null zurück. Wie kann ich es reparieren? remoteDeviceName möglicherweise Null im folgenden Code. Und ich muss mein Gerät und andere Geräte durch remoteDeviceName unterscheiden.android BluetoothDevice.getName() gibt null zurück

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); 
      }); 
+0

warum machen Sie keine Null-Überprüfung? –

+0

Natürlich kann ich prüfen, ob es null ist. Aber null Name ist für mich nutzlos. Und es ist nicht null, also gibt es eine API, um den Gerätenamen zu aktualisieren? – maonanyue

Antwort

3

BluetoothDevice.getName() kann null zurück, wenn der Name nicht ermittelt werden konnte. Dies könnte auf eine beliebige Anzahl von Faktoren zurückzuführen sein. Unabhängig davon ist der Name der freundliche Name des Geräts, und sollte nicht verwendet werden, um es von anderen Geräten zu unterscheiden. Verwenden Sie stattdessen die Hardwareadresse unter getAddress().

+3

Benutzer können Bluetooth-Adresse in unserem ble Gerät (Uhr und so weiter) nicht sehen, und nur Bluetooth Name des Gerätes kennen. Wenn also getName() null zurückgibt, ist es ein Problem, das genaue Gerät für die Verbindung auszuwählen. – maonanyue

11

Schließlich fand ich die Lösung aus:

1.Bei Gerät verbunden:

Read Gerätenamen aus gatt charakteristischen org.bluetooth.characteristic.gap.device_name des Dienstes org.bluetooth.service.generic_access.

2.Bei Gerät nicht angeschlossen:

/** 
    * 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<UUID> uuids = new ArrayList<UUID>(); 
      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<UUID> mUuids; 
     private String mName; 
     public BleAdvertisedData(List<UUID> uuids, String name){ 
      mUuids = uuids; 
      mName = name; 
     } 

     public List<UUID> getUuids(){ 
      return mUuids; 
     } 

     public String getName(){ 
      return mName; 
     } 
    } 
+0

Wie erhalten Sie Gerätename von Gatt-Eigenschaft? Können Sie mir ein Beispiel geben –

0

Auf Eibisch, nutzen ScanRecord.getDeviceName() den lokalen Namen in der Scan-Datensatz eingebettet abzurufen.

BluetoothDevice.getName() ist unzuverlässig, wenn der lokale Name in einer Scanantwort enthalten ist und nicht im Sofortwerbungspaket.

@Override 
    public void onScanResult(int callbackType, ScanResult scanResult) { 
     super.onScanResult(callbackType, scanResult); 

     // Retrieve device name via ScanRecord. 
     String deviceName = scanResult.getScanRecord().getDeviceName(); 
    } 
+0

getDeviceName Methode existiert nicht für ScanRecord-Klasse. Können Sie einen Beispielcode posten? –

+0

@NagendraBadiganti-Beispielcode enthalten. – Kevin

0

Ich habe festgestellt, dass bei einer Abfrage nach dem Namen des Geräts sofort, nachdem es beim Scannen abgerufen wurde, möglicherweise null zurückgegeben wird. Um dies zu umgehen, werde ich jede Sekunde oder so auf dem UI-Thread maximal 3 mal (also 3 Sekunden) abfragen und der Name wird normalerweise bis dahin aufgelöst.

Hinweis, im Snippet vorgesehen, implementiert die umgebenden Klasse Runnable, also warum ich this in 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); 
     } 
    } 
0

Ich habe versucht, Namen meines RN4020 Bluetooth-Modul angezeigt werden und vor dem gleichen Problem passieren kann. Gefunden das Problem in Microchip Forum:

Wenn Sie private Dienstleister oder MLDP, das maximale Bytes Gerät Namen ist 6 Bytes, aufgrund der 31-Byte-Anzeige Nutzlastbeschränkung freigegeben.

Ich hatte den Gerätenamen auf 9 Zeichen gesetzt. Durch Festlegen des Namens auf 4 Byte wurde das Problem behoben.

Wenn Sie die UUIDs Ihrer benutzerdefinierten Dienste erkennen, so dass Sie Ihr Gerät kennen, können Sie auch eine Verbindung zum Gerät herstellen und dessen Namen lesen (wenn es in meinem Fall länger als 6 Byte ist). Dies wurde auch im Microchips Forum vorgeschlagen.

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