如何用BluetoothLeScanner广播iBeacon class?

How to broadcast iBeacon with the BluetoothLeScanner class?

我想使用 BluetoothLeAdvertiser class from android.bluetooth.le 通过 android 传输 iBluetooth。但似乎我无法设置某些 制造商规格数据 字段以匹配 iBeacon 的字段。


iBeacon结构

This and this 告诉您 iBeacon 的 制造商规格数据 值需要包含什么。基本上:

Apple Company Identifier (Little Endian), 0x004c = 76
data type, 0x02 => iBeacon
data length, 0x15 = 21
uuid: 585CDE931B0142CC9A1325009BEDC65E
major: [0000]
minor: 0000
meaured power at 1 meter: 0xc5 = -59




我一直在关注具有以下步骤的 this tutorial

  1. 创建 AdvertiseData object using AdvertiseData.Builder.addManufacturerData()(我认为应该是 制造商规格数据,请参阅下面的问题)

    protected void setAdvertiseData() {
    
      AdvertiseData.Builder mBuilder = new AdvertiseData.Builder();
    
      ByteBuffer mManufacturerData = ByteBuffer.allocate(24);
    
      byte[] uuid = getIdAsByte(UUID.fromString("0CF052C2-97CA-407C-84F8-B62AAC4E9020"));
    
      mManufacturerData.put(0, (byte)0xBE); // Beacon Identifier
    
      mManufacturerData.put(1, (byte)0xAC); // Beacon Identifier
    
      for (int i=2; i<=17; i++) {
    
        mManufacturerData.put(i, uuid[i-2]); // adding the UUID
    
      }
    
      mManufacturerData.put(18, (byte)0x00); // first byte of Major
      mManufacturerData.put(19, (byte)0x09); // second byte of Major
      mManufacturerData.put(20, (byte)0x00); // first minor
      mManufacturerData.put(21, (byte)0x06); // second minor
      mManufacturerData.put(22, (byte)0xB5); // txPower
      mBuilder.addManufacturerData(224, mManufacturerData.array()); // using google's company ID
      mAdvertiseData = mBuilder.build();
    }
    
  2. 创建AdvertiseSettings using the AdvertiseSettings.Builder

    protected void setAdvertiseSettings() {
      AdvertiseSettings.Builder mBuilder = new AdvertiseSettings.Builder();
      mBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_POWER);
      mBuilder.setConnectable(false);
      mBuilder.setTimeout(0);
      mBuilder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM);
      mAdvertiseSettings = mBuilder.build();
    }
    
  3. 使用 BluetoothLeAdvertiser 广播 AdvertiseSettings 和 AdvertiseData。 (这也需要一个回调,告诉蓝牙传输是否有效,没有问题)

    mBluetoothLeAdvertiser.startAdvertising(mAdvertiseSettings, mAdvertiseData, mAdvertiseCallback);
    




这些步骤的问题是:




起初我是按照 this 教程,发送一个 Alt-Beacon。也许 BluetoothLeAdvertiser class 假设我仍在传输与 iBeacon 结构不同的 Alt-Beacon。

Alt-Beacon 结构:



其他资源:

更新代码

public AdvertiseData getiBeaconData() {
    AdvertiseData.Builder mBuilder = new AdvertiseData.Builder();
    ByteBuffer mManufacturerData = ByteBuffer.allocate(24);

    byte[] uuid = getIdAsByte(UUID.fromString(thisCont.getString( R.string.ble_uuid )) );
    ParcelUuid parced = new ParcelUuid(UUID.fromString(thisCont.getString( R.string.ble_uuid )) );
    /*

R.string.ble_uuid == CDB7950D-73F1-4D4D-8E47-C090502DBD63 这是关于 iBeacon 结构 http://smlie-blog.blogspot.com/2014/06/bluetooth-ibeacon-packet-format.html */

    //mManufacturerData.put((byte)0x00); //Manufactor Id 1
    //mManufacturerData.put((byte)0x4C); //Manufactor Id 2
   // mManufacturerData.put((byte)0xBE); //ibeconid1
    mManufacturerData.put((byte)0x02); //ibeconid2
    mManufacturerData.put((byte)0x15); //Data length
    for (byte i:uuid) {
        mManufacturerData.put(i); // adding the UUID
    }
    mManufacturerData.put((byte)0x00); //major first
    mManufacturerData.put((byte)0x00); //major second
    mManufacturerData.put((byte)0x00); //minor first
    mManufacturerData.put((byte)0x00); //minor second
    //mManufacturerData.put((byte)0xC5); //TX power

    /*
    mManufacturerData.put((byte)0x1A); // Beacon Identifier was BE  iBeacon = 00
    mManufacturerData.put((byte)0xFF); // Beacon Identifier was AC  iBeacon = 02
    /* the above 2 lines are the ibeacon AD Indicator

    for (byte i:uuid) {
        mManufacturerData.put(i); // adding the UUID
    }
    mManufacturerData.put((byte)0x00); // first byte of Major
    mManufacturerData.put((byte)0x00); // second byte of Major
    mManufacturerData.put((byte)0x00); // first minor
    mManufacturerData.put((byte)0x00); // second minor
    mManufacturerData.put((byte)0xC5); // txPower (RSSI) (from tx)
    mBuilder.addManufacturerData(16, mManufacturerData.array()); // using google's company ID
    */

    mBuilder.addManufacturerData(76, mManufacturerData.array()); // using google's company ID
    //mBuilder.addServiceUuid(parced);
    return mBuilder.build();

}

我觉得你的代码很好。一些评论:

  • Apple 的制造商 ID 是 76:mBuilder.addManufacturerData(76, mManufacturerData.array())
  • iBeacon 类型为 0x02:mManufacturerData.put(0, (byte)0x02); // Beacon Identifier
  • 长度为 0x15:mManufacturerData.put(1, (byte)0x15); // Beacon Identifier
  • 我不确定这是否有效:UUID.fromString("0CF052C297CA407C84F8B62AAC4E9020")。通常 fromString() 方法需要这样的东西:UUID.fromString("F0018B9B-7509-4C31-A905-1A27D39C003D")

总结一下:

protected void setAdvertiseData() {

     AdvertiseData.Builder mBuilder = new AdvertiseData.Builder()

     ByteBuffer mManufacturerData = ByteBuffer.allocate(23);

     byte[] uuid = getIdAsByte(UUID.fromString("0CF052C297CA407C84F8B62AAC4E9020"));

     mManufacturerData.put(0, (byte)0x02);
     mManufacturerData.put(1, (byte)0x15); 

     for (int i=2; i<=17; i++) {
       mManufacturerData.put(i, uuid[i-2]); // adding the UUID
     }

     mManufacturerData.put(18, (byte)0x00); // first byte of Major
     mManufacturerData.put(19, (byte)0x09); // second byte of Major
     mManufacturerData.put(20, (byte)0x00); // first minor
     mManufacturerData.put(21, (byte)0x06); // second minor
     mManufacturerData.put(22, (byte)0xB5); // txPower

     mBuilder.addManufacturerData(76, mManufacturerData.array()); 
     mAdvertiseData = mBuilder.build();
}