Qt Bluetooth 概述

采用 Qt Bluetooth API 的典型使用案例:

  • 检索本地蓝牙设备的有关信息。
  • 扫描范围内的其它蓝牙设备并检索它们的有关信息。
  • Push files to remote devices using the OBEX Object Push Profile (OPP)
  • Connect to remote devices through a RFCOMM channel using the Serial Port Profile (SPP).
  • Create a RFCOMM server that allows incoming connections using SPP.
  • 检索低功耗蓝牙设备的有关规范。
  • 连接到蓝牙低功耗设备。
  • Receive advertisement from Bluetooth Low Energy device.

Note that the Object Push Profile is not supported on Android and Windows.

Note that parts of RFCOMM functionality cannot be configured by Qt on Windows. A service's ServiceClassIds and ProtocolDescriptorList are filled automatically by Windows. Therefore registering a service with custom values for these fields might not yield the expected result on Windows.

The following sections describe how to use the Qt Bluetooth C++ API classes for the above use cases.

检索本地设备信息

The Qt Bluetooth API has three main purposes. The first one is to obtain local and remote device information. The first steps in retrieving device information are to check if Bluetooth is available on the device and read the local device address and name. QBluetoothLocalDevice is the class that provides all of this information. Additionally you can use it to turn Bluetooth on/off, set the visibility of the device and determine the current connections.

QBluetoothLocalDevice localDevice;
QString localDeviceName;
// Check if Bluetooth is available on this device
if (localDevice.isValid()) {
    // Turn Bluetooth on
    localDevice.powerOn();
    // Read local device name
    localDeviceName = localDevice.name();
    // Make it visible to others
    localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable);
    // Get connected devices
    QList<QBluetoothAddress> remotes;
    remotes = localDevice.connectedDevices();
}
					
					

扫描蓝牙设备

类似于 QBluetoothLocalDevice ,API 提供 QBluetoothDeviceInfo which provides similar information for remote devices. Although you can just create QBluetoothDeviceInfo objects on your own and fill them with data, the easier way is to use the QBluetoothDeviceDiscoveryAgent to start an automated search for visible Bluetooth devices within the connectable range.

void MyClass::startDeviceDiscovery()
{
    // Create a discovery agent and connect to its signals
    QBluetoothDeviceDiscoveryAgent *discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
    connect(discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
            this, SLOT(deviceDiscovered(QBluetoothDeviceInfo)));
    // Start a discovery
    discoveryAgent->start();
    //...
}
// In your local slot, read information about the found devices
void MyClass::deviceDiscovered(const QBluetoothDeviceInfo &device)
{
    qDebug() << "Found new device:" << device.name() << '(' << device.address().toString() << ')';
}
					
					

把文件推送到远程设备

Once the desired device was found, there are two main use cases provided by Qt Bluetooth. The simpler one is to send files via the Obex Object Push Profile (OPP). As the name describes, this profile can push files from one device to another. Currently it is not possible to pull files or browse the remote file system. The profile does not require the two devices to be paired before exchanging data. To push files to remote devices, create a QBluetoothTransferRequest and ask the QBluetoothTransferManager to push the file contained in the request by calling its put() 函数。

// Create a transfer manager
QBluetoothTransferManager *transferManager = new QBluetoothTransferManager(this);
// Create the transfer request and file to be sent
QBluetoothAddress remoteAddress("00:11:22:33:44:55:66");
QBluetoothTransferRequest request(remoteAddress);
QFile *file = new QFile("testfile.txt");
// Ask the transfer manager to send it
QBluetoothTransferReply *reply = transferManager->put(request, file);
if (reply->error() == QBluetoothTransferReply::NoError) {
    // Connect to the reply's signals to be informed about the status and do cleanups when done
    QObject::connect(reply, SIGNAL(finished(QBluetoothTransferReply*)),
                     this, SLOT(transferFinished(QBluetoothTransferReply*)));
    QObject::connect(reply, SIGNAL(error(QBluetoothTransferReply::TransferError)),
                     this, SLOT(error(QBluetoothTransferReply::TransferError)));
} else {
    qWarning() << "Cannot push testfile.txt:" << reply->errorString();
}
					
					

在设备之间交换数据

The more flexible approach for communication between two Bluetooth enabled devices, is to create a virtual serial port connection and freely exchange data over that connection. This can be done by the Serial Port Profile (SPP). The Serial Port Profile emulates a serial connection over the Bluetooth transport protocol RFCOMM.

To be able to receive incoming SPP connections, you need to listen to incoming connections using QBluetoothServer .

rfcommServer = new QBluetoothServer(QBluetoothServiceInfo::RfcommProtocol, this);
connect(rfcommServer, &QBluetoothServer::newConnection,
        this, QOverload<>::of(&ChatServer::clientConnected));
bool result = rfcommServer->listen(localAdapter);
if (!result) {
    qWarning() << "Cannot bind chat server to" << localAdapter.toString();
    return;
}
					

Connect to this server from another device playing the client role by using a QBluetoothSocket :

void ChatClient::startClient(const QBluetoothServiceInfo &remoteService)
{
    if (socket)
        return;
    // Connect to service
    socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
    qDebug() << "Create socket";
    socket->connectToService(remoteService);
    qDebug() << "ConnectToService done";
    connect(socket, &QBluetoothSocket::readyRead, this, &ChatClient::readSocket);
    connect(socket, &QBluetoothSocket::connected, this, QOverload<>::of(&ChatClient::connected));
    connect(socket, &QBluetoothSocket::disconnected, this, &ChatClient::disconnected);
    connect(socket, QOverload<QBluetoothSocket::SocketError>::of(&QBluetoothSocket::error),
            this, &ChatClient::onSocketErrorOccurred);
}
					

Using such a connection allows to exchange any form of data in both directions. It is perfectly suited for gaming or for syncing the state between two instances of an application on two devices. For more detailed descriptions on how to configure the server and client, please refer to the detailed description sections in the QBluetoothServer and QBluetoothSocket classes. A good example to start with SPP is the 蓝牙聊天 范例。

低功耗蓝牙

Bluetooth Low Energy, also known as Bluetooth Smart, is a new technology enabling devices with low energy consumption to communicate with each other. More details about this technology and the related Qt APIs can be found in the 低功耗蓝牙概述 .