You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 05:43:14