藍牙低功耗廣告

藍牙低功耗 (BLE) 技術在多數情況下,會在睡眠模式的剩餘時間中維持剩餘電量。醒來後只會喚醒廣告與短連線,因此廣告會影響耗電量和資料移轉頻寬。

藍牙 5 廣告擴充功能

Android 8.0 支援藍牙 5,可為 BLE 提供更完善的廣播功能改善和彈性的資料通告。藍牙 5 支援 BLE 實體層 (PHY),可保持藍牙 4.2 的耗電量降低,並讓使用者選擇增加頻寬或範圍。詳情請參閱 藍牙 5 核心規格

導入作業

凡是搭載 Android 8.0 且具有相容藍牙控制器的裝置,都會自動使用全新的藍牙 5 功能。您可以使用下列 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 的相容性。