藍牙低功耗廣告

低功耗藍牙 (BLE) 透過在大部分時間保持睡眠模式來節省電力。它喚醒只是為了進行廣告和短連接,因此廣告會影響功耗和資料傳輸頻寬。

藍牙5廣告擴展

Android 8.0 支援藍牙 5,為 BLE 提供廣播改進和靈活的數據廣告。藍牙 5 支援 BLE 物理層 (PHY),保留藍牙 4.2 降低的功耗,並讓使用者選擇增加的頻寬或範圍。更多資訊可以在藍牙 5 核心規範中找到。

執行

新的藍牙 5 功能自動適用於運行 Android 8.0 且具有相容藍牙控制器的裝置。使用這些BluetoothAdapter方法來檢查裝置是否支援藍牙5功能:

  • isLe2MPhySupported()
  • isLeCodedPhySupported()
  • isLeExtendedAdvertisingSupported()
  • isLePeriodicAdvertisingSupported()

若要停用廣告功能,請與藍牙晶片供應商合作以停用晶片組支援。

藍牙 PHY 相互獨立,每個 PHY 的行為均由藍牙 SIG 預先定義。預設情況下,Android 8.0 使用藍牙 4.2 以來的藍牙 LE 1M PHY。 android.bluetooth.le包透過以下 API 公開藍牙 5 廣告功能:

  • AdvertisingSet
  • AdvertisingSetCallback
  • AdvertisingSetParameters
  • PeriodicAdvertisingParameters

使用android.bluetooth.le.BluetoothLeAdvertiser中的startAdvertisingSet()方法建立AdvertisingSet以修改藍牙廣告設定。即使停用了對藍牙 5 或其廣告功能的支持,API 功能也可以應用於 LE 1M PHY。

例子

此範例應用程式使用藍牙 LE 1M PHY 進行廣告:

  // Start legacy advertising. Works for devices with 5.x controllers,
  // and devices that support multi-advertising.

  void example1() {
   BluetoothLeAdvertiser advertiser =
      BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();

   AdvertisingSetParameters parameters = (new AdvertisingSetParameters.Builder())
           .setLegacyMode(true) // True by default, but set here as a reminder.
           .setConnectable(true)
           .setInterval(AdvertisingSetParameters.INTERVAL_HIGH)
           .setTxPowerLevel(AdvertisingSetParameters.TX_POWER_MEDIUM)
           .build();

   AdvertiseData data = (new AdvertiseData.Builder()).setIncludeDeviceName(true).build();

   AdvertisingSetCallback callback = new AdvertisingSetCallback() {
       @Override
       public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower, int status) {
           Log.i(LOG_TAG, "onAdvertisingSetStarted(): txPower:" + txPower + " , status: "
             + status);
           currentAdvertisingSet = advertisingSet;
       }

       @Override
       public void onAdvertisingDataSet(AdvertisingSet advertisingSet, int status) {
           Log.i(LOG_TAG, "onAdvertisingDataSet() :status:" + status);
       }

       @Override
       public void onScanResponseDataSet(AdvertisingSet advertisingSet, int status) {
           Log.i(LOG_TAG, "onScanResponseDataSet(): status:" + status);
       }

       @Override
       public void onAdvertisingSetStopped(AdvertisingSet advertisingSet) {
           Log.i(LOG_TAG, "onAdvertisingSetStopped():");
       }
   };

   advertiser.startAdvertisingSet(parameters, data, null, null, null, callback);

   // After onAdvertisingSetStarted callback is called, you can modify the
   // advertising data and scan response data:
   currentAdvertisingSet.setAdvertisingData(new AdvertiseData.Builder().
     setIncludeDeviceName(true).setIncludeTxPowerLevel(true).build());
   // Wait for onAdvertisingDataSet callback...
   currentAdvertisingSet.setScanResponseData(new
     AdvertiseData.Builder().addServiceUuid(new ParcelUuid(UUID.randomUUID())).build());
   // Wait for onScanResponseDataSet callback...

   // When done with the advertising:
   advertiser.stopAdvertisingSet(callback);
}

此範例應用程式使用 BLE 2M PHY 進行廣告。該應用程式首先檢查設備是否支援正在使用的功能。如果支援廣告功能,則應用程式會將 BLE 2M PHY 配置為主要 PHY。當 2M PHY 處於活動狀態時,廣告不支援藍牙 4.x 控制器,因此setLegacyMode設定為false 。此範例在廣告時修改參數並暫停廣告。

void example2() {
   BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
   BluetoothLeAdvertiser advertiser =
     BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();

   // Check if all features are supported
   if (!adapter.isLe2MPhySupported()) {
       Log.e(LOG_TAG, "2M PHY not supported!");
       return;
   }
   if (!adapter.isLeExtendedAdvertisingSupported()) {
       Log.e(LOG_TAG, "LE Extended Advertising not supported!");
       return;
   }

   int maxDataLength = adapter.getLeMaximumAdvertisingDataLength();

   AdvertisingSetParameters.Builder parameters = (new AdvertisingSetParameters.Builder())
           .setLegacyMode(false)
           .setInterval(AdvertisingSetParameters.INTERVAL_HIGH)
           .setTxPowerLevel(AdvertisingSetParameters.TX_POWER_MEDIUM)
           .setPrimaryPhy(BluetoothDevice.PHY_LE_1M)
           .setSecondaryPhy(BluetoothDevice.PHY_LE_2M);

   AdvertiseData data = (new AdvertiseData.Builder()).addServiceData(new
     ParcelUuid(UUID.randomUUID()),
           "You should be able to fit large amounts of data up to maxDataLength. This goes
           up to 1650 bytes. For legacy advertising this would not
           work".getBytes()).build();

   AdvertisingSetCallback callback = new AdvertisingSetCallback() {
       @Override
       public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower, int status) {
           Log.i(LOG_TAG, "onAdvertisingSetStarted(): txPower:" + txPower + " , status: "
            + status);
           currentAdvertisingSet = advertisingSet;
       }

       @Override
       public void onAdvertisingSetStopped(AdvertisingSet advertisingSet) {
           Log.i(LOG_TAG, "onAdvertisingSetStopped():");
       }
   };

   advertiser.startAdvertisingSet(parameters.build(), data, null, null, null, callback);

   // After the set starts, you can modify the data and parameters of currentAdvertisingSet.
   currentAdvertisingSet.setAdvertisingData((new
     AdvertiseData.Builder()).addServiceData(new ParcelUuid(UUID.randomUUID()),
           "Without disabling the advertiser first, you can set the data, if new data is
            less than 251 bytes long.".getBytes()).build());

   // Wait for onAdvertisingDataSet callback...

   // Can also stop and restart the advertising
   currentAdvertisingSet.enableAdvertising(false, 0, 0);
   // Wait for onAdvertisingEnabled callback...
   currentAdvertisingSet.enableAdvertising(true, 0, 0);
   // Wait for onAdvertisingEnabled callback...

   // Or modify the parameters - i.e. lower the tx power
   currentAdvertisingSet.enableAdvertising(false, 0, 0);
   // Wait for onAdvertisingEnabled callback...
   currentAdvertisingSet.setAdvertisingParameters(parameters.setTxPowerLevel
     (AdvertisingSetParameters.TX_POWER_LOW).build());
   // Wait for onAdvertisingParametersUpdated callback...
   currentAdvertisingSet.enableAdvertising(true, 0, 0);
   // Wait for onAdvertisingEnabled callback...

   // When done with the advertising:
   advertiser.stopAdvertisingSet(callback);
}

確認

執行適用的藍牙產品測試以驗證裝置與藍牙 5 的兼容性。

AOSP 包含 Android 通訊測試套件 (ACTS),其中包含藍牙 5 的測試。藍牙 5 的 ACTS 測試可以在tools/test/connectivity/acts/tests/google/ble/bt5中找到。