| <html devsite><head> |
| <title>蓝牙低功耗公告功能</title> |
| <meta name="project_path" value="/_project.yaml"/> |
| <meta name="book_path" value="/_book.yaml"/> |
| </head> |
| <body> |
| <!-- |
| Copyright 2017 The Android Open Source Project |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <p> |
| 蓝牙低功耗 (BLE) 大部分时间处于睡眠模式,以节省电量。它只会在进行公告和进行短促连接时唤醒,因此这些公告会影响电量消耗和数据传输带宽。 |
| </p> |
| |
| <h2 id="bluetooth-5-advertising-extension">蓝牙 5 公告功能扩展</h2> |
| |
| <p>Android 8.0 支持蓝牙 5,该版本针对 BLE 对广播功能进行了改进,并提供了灵活的数据公告功能。蓝牙 5 支持 BLE 物理层 (PHY),PHY 不仅保留了蓝牙 4.2 的耗电量少这一优点,还允许用户选择更大的带宽或范围。如需更多信息,请参阅<a href="https://www.bluetooth.com/specifications/adopted-specifications">蓝牙 5 核心规格</a>。 |
| </p> |
| |
| <h3 id="implementation">实现</h3> |
| |
| <p> |
| 蓝牙 5 的新功能可自动适用于运行 Android 8.0 且具有兼容蓝牙控制器的设备。您可以使用这些 <code><a href="https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html"> |
| BluetoothAdapter</a></code> 方法来检查设备是否支持蓝牙 5 的功能: |
| </p> |
| |
| <ul> |
| <li><code>isLe2MPhySupported()</code></li> |
| <li><code>isLeCodedPhySupported()</code></li> |
| <li><code>isLeExtendedAdvertisingSupported()</code></li> |
| <li><code>isLePeriodicAdvertisingSupported()</code></li> |
| </ul> |
| |
| <p> |
| 要停用公告功能,请联系蓝牙芯片供应商来停用芯片组支持。 |
| </p> |
| |
| <p> |
| 蓝牙 PHY 是互斥的,并且每个 PHY 的行为均由蓝牙 SIG 预先定义。默认情况下,Android 8.0 使用蓝牙 4.2 的蓝牙 LE 1M PHY。<code><a href="https://developer.android.com/reference/android/bluetooth/le/package-summary.html"> |
| android.bluetooth.le</a></code> 程序包通过以下 API 提供蓝牙 5 的公告功能: |
| </p> |
| |
| <ul> |
| <li><code>AdvertisingSet</code></li> |
| <li><code>AdvertisingSetCallback</code></li> |
| <li><code>AdvertisingSetParameters</code></li> |
| <li><code>PeriodicAdvertisingParameters</code></li> |
| </ul> |
| |
| <p> |
| 通过使用 <code><a href="https://developer.android.com/reference/android/bluetooth/le/BluetoothLeAdvertiser.html"> |
| android.bluetooth.le.BluetoothLeAdvertiser</a></code> 中的 <code><a href="https://developer.android.com/reference/android/bluetooth/le/BluetoothLeAdvertiser.html#startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, |
| android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, |
| android.bluetooth.le.PeriodicAdvertisingParameters, |
| android.bluetooth.le.AdvertiseData, |
| android.bluetooth.le.AdvertisingSetCallback)"> |
| startAdvertisingSet()</a></code> 方法,可以创建 <code><a href="https://developer.android.com/reference/android/bluetooth/le/AdvertisingSet.html"> |
| AdvertisingSet</a></code> 来修改蓝牙公告设置。即使对蓝牙 5 或其公告功能的支持被停用,API 功能也可以应用于 LE 1M PHY。 |
| </p> |
| |
| <h4 id="examples">示例</h4> |
| |
| <p> |
| 该示例应用使用蓝牙 LE 1M PHY 进行公告: |
| </p> |
| |
| <pre class="prettyprint"> |
| // 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); |
| }</pre> |
| |
| <p> |
| 该示例应用使用 BLE 2M PHY 进行公告。该应用会首先检查设备是否支持要使用的功能。如果设备支持公告功能,该应用会将 BLE 2M PHY 配置为主 PHY。当 2M PHY 处于活动状态时,公告功能不支持蓝牙 4.x 控制器,因此 <code>setLegacyMode</code> 会被设为 <code>false</code>。该示例可在进行公告时修改参数,也可暂停公告。 |
| </p> |
| |
| <pre class="prettyprint">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_2M) |
| .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); |
| }</pre> |
| |
| <h3 id="verification">验证</h3> |
| |
| <p>运行适用的<a href="https://www.bluetooth.com/develop-with-bluetooth/test-tools">蓝牙产品测试</a>,以验证设备是否与蓝牙 5 兼容。 |
| </p> |
| |
| <p> |
| AOSP 包含 Android 通讯测试套件 (ACTS),其中包括针对蓝牙 5 的测试。您可以在以下位置找到针对蓝牙 5 的 ACTS 测试:<code><a href="https://android.googlesource.com/platform/tools/test/connectivity/+/master/acts/tests/google/ble/bt5/"> |
| tools/test/connectivity/acts/tests/google/ble/bt5</a></code>。 |
| </p> |
| |
| </body></html> |