android BluetoothDevice.getName()返回null

问题描述:

有时,BluetoothDevice.getName()返回null。我该如何解决它? remoteDeviceName在下面的代码中可能为null。我需要通过remoteDeviceName区分我的设备和其他设备。android BluetoothDevice.getName()返回null

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

为什么你不做一些空检查? – 2014-10-10 02:37:11

+0

cource,我可以检查它是否为null。但是空名对我来说毫无用处。它不是空的,所以有一些API来刷新设备名称? – maonanyue 2014-10-10 02:41:43

BluetoothDevice.getName()可能返回null如果名称无法确定。这可能是由于许多因素造成的。无论如何,名称是友好的设备的名称,不应该用于区分它与其他设备。而应使用通过getAddress()的硬件地址。

+3

用户无法在我们的无线设备(手表等)中看到蓝牙地址,只知道设备的蓝牙名称。所以,当getName()返回null时,选择确切的设备来连接是个问题。 – maonanyue 2014-10-10 05:56:44

最后,我发现了解决方案:

1.适用于设备连接:从复关

读取设备名称特性服务org.bluetooth.service.generic_accessorg.bluetooth.characteristic.gap.device_name。没有连接

2.对于设备:

/** 
    * 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

如何从gatt特性中获取设备名称?你可以给我任何例子 – 2016-04-20 08:27:05

在棉花糖,利用ScanRecord.getDeviceName()检索嵌入在扫描记录的本地名称。

BluetoothDevice.getName()如果本地名称包含在扫描响应中,而不是直接通告数据包中,则不可靠。

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

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

getDeviceName方法不存在ScanRecord类。你能发表一个示例代码吗? – 2017-09-18 14:39:12

+0

@NagendraBadiganti包括示例代码。 – Kevin 2017-09-19 21:48:23

我发现如果您在扫描后立即查询设备名称,它可能会返回null。为了解决这个问题,我在UI线程上每隔一秒左右轮询一次runnable,最多3次(所以3秒),这个名字通常是在那个时候解决的。

注意,在所提供的片段,封闭类实现Runnable,因此为什么我可以通过thisView.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); 
     } 
    } 

我试图显示我的RN4020蓝牙模块的名称及所面临的同样的问题。发现问题Microchip的论坛:

如果启用私人服务或MLDP,设备 名的最大字节数是6个字节,由于31字节的有效载荷的广告限制。

我已将设备名称设置为9个字符。将名称设置为4个字节可解决问题。

如果您认识到您的自定义服务的UUID,以便您知道它的设备,则还可以连接到设备并读取其名称(如果其长度超过6个字节)。这也是在微芯片论坛中提出的。

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