startAdvertising 和 startAdvertisingSet 是 Android BLE API 中用于启动蓝牙广告的两个方法,它们的主要区别在于 功能和能力 。startAdvertisingSet 是 Android 8.0 (API 26) 引入的更强大的广告方法,支持 Bluetooth 5.0 的新特性。
主要区别概览
| 特性 | startAdvertising |
startAdvertisingSet |
|---|---|---|
| 引入版本 | Android 5.0 (API 21) | Android 8.0 (API 26) |
| Bluetooth 版本 | 4.x | 5.0+ |
| 广告类型 | 标准广告 (最多31字节) | 扩展广告 (最多1650字节) |
| 同时广播 | 只能一个广告 | 多个广告集同时广播 |
| 周期广告 | 不支持 | 支持 |
| 控制粒度 | 简单控制 | 精细控制,可动态修改 |
| 回调对象 | AdvertiseCallback | AdvertisingSetCallback |
详细对比
1. startAdvertising - 传统广告方法
这是最基本的BLE广告方法,功能相对简单。
java
// 传统广告方法签名
void startAdvertising(
AdvertiseSettings settings,
AdvertiseData advertiseData,
AdvertiseData scanResponse,
AdvertiseCallback callback
)
// 使用示例
bluetoothLeAdvertiser.startAdvertising(
settings,
advertiseData,
scanResponse,
new AdvertiseCallback() {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
// 广告启动成功
}
@Override
public void onStartFailure(int errorCode) {
// 广告启动失败
}
}
);
限制:
- 只能广播最多 31 字节数据
- 一次只能启动一个广告实例
- 不能动态修改广告参数
- 不支持周期广告
2. startAdvertisingSet - 扩展广告方法
这是更强大的广告方法,支持 Bluetooth 5.0 的新特性。
java
// 扩展广告方法签名
void startAdvertisingSet(
AdvertisingSetParameters parameters,
AdvertiseData advertiseData,
AdvertiseData scanResponse,
PeriodicAdvertisingParameters periodicParameters,
AdvertiseData periodicData,
AdvertisingSetCallback callback
)
// 可选参数形式
void startAdvertisingSet(
AdvertisingSetParameters parameters,
AdvertiseData advertiseData,
AdvertiseData scanResponse,
PeriodicAdvertisingParameters periodicParameters,
AdvertiseData periodicData,
int duration,
int maxExtendedAdvertisingEvents,
AdvertisingSetCallback callback
)
功能对比详解
示例对比
传统广告 (startAdvertising)
java
public void startTraditionalAdvertising() {
// 传统广告设置
AdvertiseSettings settings = new AdvertiseSettings.Builder()
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED)
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM)
.setConnectable(true)
.setTimeout(0)
.build();
// 广告数据(最多31字节)
AdvertiseData advertiseData = new AdvertiseData.Builder()
.setIncludeDeviceName(true)
.addServiceUuid(new ParcelUuid(SERVICE_UUID))
.addManufacturerData(0x004C, new byte[]{0x01, 0x02}) // 最多31字节
.build();
bluetoothLeAdvertiser.startAdvertising(settings, advertiseData, null, callback);
}
扩展广告 (startAdvertisingSet)
java
public void startExtendedAdvertisingSet() {
// 1. 创建广告集参数(支持更多配置选项)
AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder()
.setLegacyMode(false) // 使用扩展广告模式
.setConnectable(true)
.setScannable(true)
.setInterval(AdvertisingSetParameters.INTERVAL_MIN) // 广告间隔
.setTxPowerLevel(AdvertisingSetParameters.TX_POWER_MAX) // 发射功率
.setPrimaryPhy(BluetoothDevice.PHY_LE_1M) // 主要PHY
.setSecondaryPhy(BluetoothDevice.PHY_LE_2M) // 次要PHY
.build();
// 2. 广告数据(支持最多1650字节)
AdvertiseData advertiseData = new AdvertiseData.Builder()
.setIncludeDeviceName(true)
.addServiceUuid(new ParcelUuid(SERVICE_UUID))
.addServiceData(new ParcelUuid(SERVICE_UUID), largePayload) // 可以传输大量数据
.build();
// 3. 周期广告参数(可选)
PeriodicAdvertisingParameters periodicParameters = new PeriodicAdvertisingParameters.Builder()
.setIncludeTxPower(true)
.setInterval(PeriodicAdvertisingParameters.INTERVAL_MIN)
.build();
// 4. 周期广告数据
AdvertiseData periodicData = new AdvertiseData.Builder()
.addServiceData(new ParcelUuid(SERVICE_UUID), periodicPayload)
.build();
// 5. 启动广告集
bluetoothLeAdvertiser.startAdvertisingSet(
parameters,
advertiseData,
null, // 扫描响应
periodicParameters,
periodicData,
callback
);
}
关键特性详解
1. 扩展广告 (Extended Advertising)
java
// 启用扩展广告
AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder()
.setLegacyMode(false) // false = 扩展广告,true = 传统广告
.setPrimaryPhy(BluetoothDevice.PHY_LE_1M)
.setSecondaryPhy(BluetoothDevice.PHY_LE_2M)
.build();
// 优势:
// - 广告数据最多1650字节(传统只有31字节)
// - 支持2M PHY,速率更快
// - 可以在不同PHY上同时广播
2. 周期广告 (Periodic Advertising)
java
// 配置周期广告
PeriodicAdvertisingParameters periodicParams = new PeriodicAdvertisingParameters.Builder()
.setIncludeTxPower(true)
.setInterval(PeriodicAdvertisingParameters.INTERVAL_MIN) // 7.5ms - 81.91875s
.build();
// 优势:
// - 扫描设备可以同步到周期广告
// - 减少扫描功耗
// - 适合发送不频繁变化的数据
3. 多个广告集同时运行
java
// 可以同时启动多个广告集
private List<AdvertisingSet> advertisingSets = new ArrayList<>();
public void startMultipleAdvertisingSets() {
// 第一个广告集
AdvertisingSetParameters params1 = new AdvertisingSetParameters.Builder()
.setLegacyMode(true)
.setConnectable(true)
.build();
// 第二个广告集
AdvertisingSetParameters params2 = new AdvertisingSetParameters.Builder()
.setLegacyMode(false)
.setConnectable(false)
.build();
// 同时启动两个广告集
bluetoothLeAdvertiser.startAdvertisingSet(params1, data1, null, null, null, callback1);
bluetoothLeAdvertiser.startAdvertisingSet(params2, data2, null, null, null, callback2);
}
4. 动态广告控制
java
AdvertisingSetCallback callback = new AdvertisingSetCallback() {
@Override
public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower, int status) {
if (status == AdvertisingSetCallback.ADVERTISE_SUCCESS) {
// 1. 动态修改广告数据
advertisingSet.setAdvertisingData(newAdvertiseData);
// 2. 修改扫描响应数据
advertisingSet.setScanResponseData(newScanResponseData);
// 3. 修改广告参数
advertisingSet.setAdvertisingParameters(newParameters);
// 4. 启用/禁用广告
advertisingSet.enableAdvertising(true, duration, maxEvents);
// 5. 周期广告控制
advertisingSet.setPeriodicAdvertisingData(periodicData);
advertisingSet.setPeriodicAdvertisingParameters(periodicParams);
advertisingSet.enablePeriodicAdvertising(true);
}
}
};
完整使用示例
java
public class ExtendedAdvertiser {
private BluetoothLeAdvertiser advertiser;
private AdvertisingSet currentAdvertisingSet;
public void startExtendedAdvertising() {
// 1. 检查是否支持扩展广告
if (!BluetoothAdapter.getDefaultAdapter().isLeExtendedAdvertisingSupported()) {
Log.w("BLE", "设备不支持扩展广告,使用传统广告");
startTraditionalAdvertising();
return;
}
// 2. 配置扩展广告参数
AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder()
.setLegacyMode(false) // 扩展广告
.setConnectable(true)
.setScannable(true)
.setInterval(AdvertisingSetParameters.INTERVAL_MIN)
.setTxPowerLevel(AdvertisingSetParameters.TX_POWER_HIGH)
.setPrimaryPhy(BluetoothDevice.PHY_LE_1M)
.setSecondaryPhy(BluetoothDevice.PHY_LE_2M)
.build();
// 3. 准备大容量广告数据(超过31字节)
byte[] largePayload = new byte[500];
// ... 填充数据
AdvertiseData advertiseData = new AdvertiseData.Builder()
.setIncludeDeviceName(true)
.setIncludeTxPowerLevel(true)
.addServiceUuid(new ParcelUuid(SERVICE_UUID))
.addServiceData(new ParcelUuid(SERVICE_UUID), largePayload)
.build();
// 4. 配置周期广告
PeriodicAdvertisingParameters periodicParams = new PeriodicAdvertisingParameters.Builder()
.setIncludeTxPower(true)
.setInterval(100) // 单位:1.25ms,所以是125ms
.build();
AdvertiseData periodicData = new AdvertiseData.Builder()
.addServiceData(new ParcelUuid(SERVICE_UUID), "Periodic Data".getBytes())
.build();
// 5. 创建回调
AdvertisingSetCallback callback = new AdvertisingSetCallback() {
@Override
public void onAdvertisingSetStarted(AdvertisingSet advertisingSet,
int txPower, int status) {
if (status == ADVERTISE_SUCCESS) {
currentAdvertisingSet = advertisingSet;
Log.i("BLE", "扩展广告启动成功,发射功率:" + txPower + "dBm");
// 启用周期广告
advertisingSet.enablePeriodicAdvertising(true);
}
}
@Override
public void onAdvertisingSetStopped(AdvertisingSet advertisingSet) {
Log.i("BLE", "广告集已停止");
currentAdvertisingSet = null;
}
@Override
public void onPeriodicAdvertisingEnabled(AdvertisingSet advertisingSet,
boolean enable, int status) {
Log.i("BLE", "周期广告" + (enable ? "启用" : "禁用") + ",状态:" + status);
}
};
// 6. 启动扩展广告
advertiser.startAdvertisingSet(
parameters,
advertiseData,
null, // 扫描响应
periodicParams,
periodicData,
callback
);
}
public void updateAdvertisingData(byte[] newData) {
if (currentAdvertisingSet != null) {
AdvertiseData newAdvertiseData = new AdvertiseData.Builder()
.addServiceData(new ParcelUuid(SERVICE_UUID), newData)
.build();
currentAdvertisingSet.setAdvertisingData(newAdvertiseData);
}
}
public void stopAdvertising() {
if (currentAdvertisingSet != null) {
currentAdvertisingSet.stopAdvertising();
currentAdvertisingSet = null;
}
}
}
选择建议
使用 startAdvertising 当:
- 需要兼容 Android 5.0-7.x 设备
- 广告数据不超过31字节
- 只需要基本的广告功能
- 项目时间/资源有限
使用 startAdvertisingSet 当:
- 目标设备是 Android 8.0+ 且支持 Bluetooth 5.0
- 需要传输大量数据(>31字节)
- 需要周期广告功能
- 需要同时广播多个服务
- 需要动态更新广告内容
- 对功耗有更高要求
兼容性处理示例
java
public void startAdvertisingWithFallback() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
bluetoothAdapter.isLeExtendedAdvertisingSupported()) {
// 使用扩展广告
startExtendedAdvertisingSet();
} else {
// 降级到传统广告
startTraditionalAdvertising();
}
}
注意事项
- 权限要求:扩展广告需要 Android 8.0+ 和 Bluetooth 5.0 硬件支持
- 功耗考虑:扩展广告和周期广告可能增加功耗
- 兼容性:老设备可能无法接收扩展广告
- 限制检查 :使用前检查
BluetoothAdapter.isLeExtendedAdvertisingSupported()
总结来说,startAdvertisingSet 是 startAdvertising 的超集,提供了更多高级功能,特别适合需要传输大量数据或需要精细控制广告行为的应用场景。