藍牙低功耗 (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 的行為都由 Bluetooth SIG 預先定義。根據預設,Android 8.0 會使用藍牙 4.2 的藍牙 LE 1M PHY。android.bluetooth.le
套件會透過下列 API 公開 Bluetooth 5 廣告功能:
AdvertisingSet
AdvertisingSetCallback
AdvertisingSetParameters
PeriodicAdvertisingParameters
建立 AdvertisingSet
,透過 android.bluetooth.le.BluetoothLeAdvertiser
中的 startAdvertisingSet()
方法修改藍牙廣告設定。即使停用藍牙 5 或其廣告功能,API 功能也適用於 LE 1M PHY。
範例
這個範例應用程式使用 Bluetooth 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 處於啟用狀態時,廣告不支援 Bluetooth 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 can 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 - for example, 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 相容。