
在Android平台上,应用程序可以通过蓝牙低功耗(BLE)功能广播数据,这通常用于设备发现或数据传输。启动BLE广告需要通过BluetoothLeAdvertiser类,并配置AdvertiseSettings和AdvertiseData。其中,AdvertiseCallback是一个至关重要的组件,用于接收广告启动成功或失败的回调。
以下是启动BLE广告的基本代码示例:
public class BleAdvertiserManager {
private static final String TAG = "BleAdvertiserManager";
private BluetoothLeAdvertiser advertiser;
private AdvertiseCallback advertiseCallback; // 用于存储AdvertiseCallback实例
// 假设 serviceId 和 packet 已经定义
private ParcelUuid serviceId = ParcelUuid.fromString("0000180A-0000-1000-8000-00805F9B34FB"); // 示例服务UUID
private byte[] packet = new byte[]{0x01, 0x02, 0x03, 0x04}; // 示例服务数据
public BleAdvertiserManager() {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter != null) {
advertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
}
}
public void startAdvertising() {
if (advertiser == null) {
Log.e(TAG, "BluetoothLeAdvertiser not available.");
return;
}
AdvertiseSettings advSettings = new AdvertiseSettings.Builder()
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
.setConnectable(false) // 设置为不可连接的广告
.setTimeout(0) // 广告不超时,持续广播
.build();
AdvertiseData data = new AdvertiseData.Builder()
.setIncludeDeviceName(true)
.setIncludeTxPowerLevel(false)
.addServiceUuid(serviceId)
.build();
AdvertiseData response = new AdvertiseData.Builder()
.setIncludeDeviceName(false)
.setIncludeTxPowerLevel(false)
.addServiceData(serviceId, packet)
.build();
// 创建并存储AdvertiseCallback实例
advertiseCallback = new AdvertiseCallback() {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
super.onStartSuccess(settingsInEffect);
Log.d(TAG, "BLE advertising started successfully.");
}
@Override
public void onStartFailure(int errorCode) {
super.onStartFailure(errorCode);
Log.e(TAG, "BLE advertising failed to start: " + errorCode);
}
};
advertiser.startAdvertising(advSettings, data, response, advertiseCallback);
}
}在上述代码中,startAdvertising方法创建了一个AdvertiseCallback匿名内部类实例,并将其传递给advertiser.startAdvertising()。这个advertiseCallback实例被存储在类成员变量中,以便后续使用。
许多开发者在尝试停止BLE广告时,可能会遇到广告无法停止的问题,即使调用了stopAdvertising方法。这通常是由于在停止广告时,传递了与启动广告时不同的AdvertiseCallback实例。
考虑以下错误的停止广告实现方式:
// 错误的停止广告方法示例
public void stopAdvertisingIncorrect() {
if (advertiser == null) {
Log.d(TAG, "Advertiser is null, nothing to stop.");
return;
}
Log.d(TAG, "Attempting to stop advertising incorrectly...");
// 错误:这里创建了一个新的 AdvertiseCallback 实例
advertiser.stopAdvertising(new AdvertiseCallback() {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
// 注意:停止成功的回调实际上是 onStopSuccess,这里是示例错误
Log.d(TAG, "onStopSuccess (incorrect callback)");
super.onStartSuccess(settingsInEffect);
}
@Override
public void onStartFailure(int errorCode) {
// 注意:停止失败的回调实际上是 onStopFailure,这里是示例错误
Log.e(TAG, "onStopFailure (incorrect callback): " + errorCode);
super.onStartFailure(errorCode);
}
});
// 即使将 advertiser 置为 null,也不会停止实际的广播
// advertiser = null;
}当使用上述stopAdvertisingIncorrect方法时,日志中可能会出现类似D/BluetoothLeAdvertiser: wrapper is null的提示,并且广告实际上并未停止。这是因为BluetoothLeAdvertiser内部使用AdvertiseCallback对象作为标识符来管理不同的广告会话。如果你传递了一个新的、不同的AdvertiseCallback对象给stopAdvertising,系统将无法识别到你想要停止的是哪一个正在运行的广告会话,从而导致停止操作失败。
根据Google官方文档的说明,stopAdvertising方法中的callback参数必须是与startAdvertising方法中使用的同一个实例。这是因为AdvertiseCallback对象在内部被用作一个唯一的键,以识别和管理特定的广告会话。
因此,正确的做法是保存启动广告时使用的AdvertiseCallback实例,并在停止广告时重复使用它。
// 正确的停止广告方法示例
public void stopAdvertising() {
if (advertiser == null || advertiseCallback == null) {
Log.d(TAG, "Advertiser or callback is null, nothing to stop.");
return;
}
Log.d(TAG, "Attempting to stop advertising correctly...");
// 正确:使用之前启动广告时存储的同一个 advertiseCallback 实例
advertiser.stopAdvertising(advertiseCallback);
// 停止后可以将 advertiseCallback 置为 null,防止重复停止或资源泄露
advertiseCallback = null;
// advertiser = null; // 根据需要决定是否清空advertiser引用
}通过这种方式,当调用stopAdvertising(advertiseCallback)时,系统能够通过传入的advertiseCallback实例准确地找到对应的正在运行的广告会话并将其停止。
BluetoothLeAdvertiser的stopAdvertising方法要求传入的AdvertiseCallback对象与启动广告时使用的对象完全一致。这背后的原理是,Android系统在内部维护了一个映射表,将每个活动的BLE广告会话与一个特定的AdvertiseCallback实例关联起来。当调用stopAdvertising时,系统会查找与传入的AdvertiseCallback对象匹配的活动会话,然后将其终止。
Google官方文档对此有明确说明: * Stop Bluetooth LE advertising. The {@code callback} must be the same one use in * {@link BluetoothLeAdvertiser#startAdvertising}. (停止蓝牙低功耗广告。callback必须是与BluetoothLeAdvertiser#startAdvertising中使用的同一个。)
这意味着AdvertiseCallback不仅是一个回调接口,它更是一个会话的唯一标识符。如果传入的AdvertiseCallback对象不匹配,系统就无法知道要停止哪个广告,因此广告会持续运行。
Android BLE广告无法停止的问题,其根本原因在于startAdvertising和stopAdvertising方法中AdvertiseCallback实例的不一致。通过确保在停止广告时使用与启动广告时完全相同的AdvertiseCallback对象,开发者可以有效解决此问题,并确保BLE广告功能的正常启动与停止。理解AdvertiseCallback作为广告会话唯一标识符的关键作用,是正确实现Android BLE广告管理的核心。
以上就是Android BLE广告停止失败问题解析与解决方案的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号