Android平台Qt蓝牙BLE广告启动崩溃问题求助
问题分析与解决方案
1. 核心崩溃原因:空指针访问
你的代码中QSharedPointer<QLowEnergyController> leController;仅声明了智能指针但未初始化实例,直接调用leController->startAdvertising()会触发空指针解引用,导致SIGSEGV崩溃。必须先创建QLowEnergyController的外设实例:
// 替换原有的leController声明 QSharedPointer<QLowEnergyController> leController(QLowEnergyController::createPeripheral());
2. Android蓝牙权限配置
2.1 清单文件权限声明
在项目的android/AndroidManifest.xml中添加以下权限(根据Android版本适配):
<!-- Android 11及以下权限 --> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" /> <!-- Android 12+权限 --> <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <!-- 声明支持BLE --> <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
2.2 运行时权限请求
Qt 6.5+通过QPermissions请求运行时权限,在启动广告前必须获取所需权限:
#include <QPermission> #include <QBluetoothPermissions> #include <QSysInfo> // 在main函数中,蓝牙初始化后添加权限请求 QBluetoothAdvertisePermission advertisePerm; QBluetoothConnectPermission connectPerm; QList<QPermission> permissions = {advertisePerm, connectPerm}; if (QSysInfo::AndroidSdkVersion <= 30) { QAccessibilityPermission locationPerm; // Android 11及以下需要位置权限 permissions.append(locationPerm); } // 请求权限 QPermissionStatus status = QPermission::requestPermissions(permissions); if (status != QPermissionStatus::Granted) { qDebug() << "Required permissions not granted"; return app.exit(-1); }
3. 代码修正后的完整示例
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QDebug> #include <QLowEnergyController> #include <QLowEnergyAdvertisingData> #include <QByteArray> #include <QLowEnergyAdvertisingParameters> #include <QPermissions> #include <QBluetoothLocalDevice> #include <QBluetoothPermissions> #include <QSysInfo> #include <QEventLoop> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); // 蓝牙设备初始化 QBluetoothLocalDevice localDevice; if (localDevice.hostMode() == QBluetoothLocalDevice::HostPoweredOff) { qDebug() << "Bluetooth is turned off! Turning on..."; localDevice.powerOn(); // 等待蓝牙完全开启 QEventLoop loop; QObject::connect(&localDevice, &QBluetoothLocalDevice::hostModeChanged, &loop, &QEventLoop::quit); loop.exec(); } // 请求权限 QBluetoothAdvertisePermission advertisePerm; QBluetoothConnectPermission connectPerm; QList<QPermission> permissions = {advertisePerm, connectPerm}; if (QSysInfo::AndroidSdkVersion <= 30) { QAccessibilityPermission locationPerm; permissions.append(locationPerm); } QPermissionStatus status = QPermission::requestPermissions(permissions); if (status != QPermissionStatus::Granted) { qDebug() << "Required permissions not granted"; return app.exit(-1); } // 创建BLE外设控制器 QSharedPointer<QLowEnergyController> leController(QLowEnergyController::createPeripheral()); // 配置广告参数 QLowEnergyAdvertisingParameters advertisingParameters; advertisingParameters.setMode(QLowEnergyAdvertisingParameters::AdvNonConnInd); // 广告数据(确保格式符合BLE规范) QByteArray advData = QByteArray::fromRawData( "\x02\x01\x06\x03\x02\x50\xFD\x17\x16\x50\xFD\x41\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 31 ); QByteArray scanRspData = QByteArray::fromRawData( "\x17\xFF\xD0\x07\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x03\x09\x54\x59", 31 ); QLowEnergyAdvertisingData advertisingData; advertisingData.setRawData(advData); QLowEnergyAdvertisingData advertisingScanData; advertisingScanData.setRawData(scanRspData); // 启动广告 bool success = leController->startAdvertising(advertisingParameters, advertisingData, advertisingScanData); if (success) { qDebug() << "BLE advertising started successfully"; } else { qDebug() << "Failed to start BLE advertising"; } QQmlApplicationEngine engine; QObject::connect( &engine, &QQmlApplicationEngine::objectCreationFailed, &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.loadFromModule("AndroidBLE", "Main"); return app.exec(); }
4. 额外注意事项
- 蓝牙开启需要时间,代码中添加了
QEventLoop等待蓝牙状态变更,避免在蓝牙未完全就绪时执行操作。 - 广告数据必须符合BLE规范:每个AD结构由长度字节、类型字节、数据字节组成,单条广告数据总长度不超过31字节。
- 确保目标Android设备支持BLE外设模式(大部分现代设备均支持)。
内容的提问来源于stack exchange,提问作者Trung Nguyễn
相关产品推荐
相关产品推荐

