DeviceDiscoveryDialog::DeviceDiscoveryDialog(QWidget *parent) : QDialog(parent), discoveryAgent(new QBluetoothDeviceDiscoveryAgent), localDevice(new QBluetoothLocalDevice), ui(new Ui_DeviceDiscovery) { ui->setupUi(this); #if defined (Q_OS_SYMBIAN) || defined(Q_OS_WINCE) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6) setWindowState(Qt::WindowFullScreen); #endif connect(ui->inquiryType, SIGNAL(toggled(bool)), this, SLOT(setGeneralUnlimited(bool))); connect(ui->scan, SIGNAL(clicked()), this, SLOT(startScan())); connect(discoveryAgent, SIGNAL(deviceDiscovered(const QBluetoothDeviceInfo&)), this, SLOT(addDevice(const QBluetoothDeviceInfo&))); connect(discoveryAgent, SIGNAL(finished()), this, SLOT(scanFinished())); connect(ui->list, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(itemActivated(QListWidgetItem*))); connect(localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)), this, SLOT(hostModeStateChanged(QBluetoothLocalDevice::HostMode))); hostModeStateChanged(localDevice->hostMode()); // add context menu for devices to be able to pair device ui->list->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->list, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(displayPairingMenu(QPoint))); connect(localDevice, SIGNAL(pairingFinished(const QBluetoothAddress&, QBluetoothLocalDevice::Pairing)) , this, SLOT(pairingDone(const QBluetoothAddress&, QBluetoothLocalDevice::Pairing))); }
BtLocalDevice::BtLocalDevice(QObject *parent) : QObject(parent), securityFlags(QBluetooth::NoSecurity) { localDevice = new QBluetoothLocalDevice(this); connect(localDevice, SIGNAL(error(QBluetoothLocalDevice::Error)), this, SIGNAL(error(QBluetoothLocalDevice::Error))); connect(localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)), this, SIGNAL(hostModeStateChanged())); connect(localDevice, SIGNAL(pairingFinished(QBluetoothAddress,QBluetoothLocalDevice::Pairing)), this, SLOT(pairingFinished(QBluetoothAddress,QBluetoothLocalDevice::Pairing))); connect(localDevice, SIGNAL(deviceConnected(QBluetoothAddress)), this, SLOT(connected(QBluetoothAddress))); connect(localDevice, SIGNAL(deviceDisconnected(QBluetoothAddress)), this, SLOT(disconnected(QBluetoothAddress))); connect(localDevice, SIGNAL(pairingDisplayConfirmation(QBluetoothAddress,QString)), this, SLOT(pairingDisplayConfirmation(QBluetoothAddress,QString))); if (localDevice->isValid()) { deviceAgent = new QBluetoothDeviceDiscoveryAgent(this); connect(deviceAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), this, SLOT(deviceDiscovered(QBluetoothDeviceInfo))); connect(deviceAgent, SIGNAL(finished()), this, SLOT(discoveryFinished())); connect(deviceAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)), this, SLOT(discoveryError(QBluetoothDeviceDiscoveryAgent::Error))); connect(deviceAgent, SIGNAL(canceled()), this, SLOT(discoveryCanceled())); serviceAgent = new QBluetoothServiceDiscoveryAgent(this); connect(serviceAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)), this, SLOT(serviceDiscovered(QBluetoothServiceInfo))); connect(serviceAgent, SIGNAL(finished()), this, SLOT(serviceDiscoveryFinished())); connect(serviceAgent, SIGNAL(canceled()), this, SLOT(serviceDiscoveryCanceled())); connect(serviceAgent, SIGNAL(error(QBluetoothServiceDiscoveryAgent::Error)), this, SLOT(serviceDiscoveryError(QBluetoothServiceDiscoveryAgent::Error))); socket = new QBluetoothSocket(SOCKET_PROTOCOL, this); connect(socket, SIGNAL(stateChanged(QBluetoothSocket::SocketState)), this, SLOT(socketStateChanged(QBluetoothSocket::SocketState))); connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(socketError(QBluetoothSocket::SocketError))); connect(socket, SIGNAL(connected()), this, SLOT(socketConnected())); connect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected())); connect(socket, SIGNAL(readyRead()), this, SLOT(readData())); setSecFlags(socket->preferredSecurityFlags()); server = new QBluetoothServer(SOCKET_PROTOCOL, this); connect(server, SIGNAL(newConnection()), this, SLOT(serverNewConnection())); connect(server, SIGNAL(error(QBluetoothServer::Error)), this, SLOT(serverError(QBluetoothServer::Error))); } else { deviceAgent = 0; serviceAgent = 0; socket = 0; server = 0; } }
void tst_QBluetoothLocalDevice::tst_hostModes() { QFETCH(QBluetoothLocalDevice::HostMode, hostModeExpected); QBluetoothLocalDevice localDevice; QSignalSpy hostModeSpy(&localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode))); // there should be no changes yet QVERIFY(hostModeSpy.isEmpty()); QTest::qWait(1000); localDevice.setHostMode(hostModeExpected); // wait for the device to switch bluetooth mode. QTest::qWait(1000); if (hostModeExpected != localDevice.hostMode()) { WAIT_FOR_CONDITION(hostModeSpy.count(),1); QVERIFY(hostModeSpy.count() > 0); } // test the actual signal values. QList<QVariant> arguments = hostModeSpy.takeFirst(); QBluetoothLocalDevice::HostMode hostMode = qvariant_cast<QBluetoothLocalDevice::HostMode>(arguments.at(0)); QCOMPARE(hostModeExpected, hostMode); // test actual QCOMPARE(hostModeExpected, localDevice.hostMode()); }
void tst_QBluetoothLocalDevice::tst_powerOff() { if (!QBluetoothLocalDevice::allDevices().count()) QSKIP("Skipping test due to missing Bluetooth device"); { QBluetoothLocalDevice *device = new QBluetoothLocalDevice(); device->powerOn(); delete device; // wait for the device to switch bluetooth mode. QTest::qWait(1000); } QBluetoothLocalDevice localDevice; QSignalSpy hostModeSpy(&localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode))); // there should be no changes yet QVERIFY(hostModeSpy.isValid()); QVERIFY(hostModeSpy.isEmpty()); localDevice.setHostMode(QBluetoothLocalDevice::HostPoweredOff); // async, wait for it QTRY_VERIFY(hostModeSpy.count() > 0); // we should not be powered off QVERIFY(localDevice.hostMode() == QBluetoothLocalDevice::HostPoweredOff); }
bool RfCommClient::powerOn() { qDebug() << __PRETTY_FUNCTION__ << ">>"; // turn on BT in case it is not on if (localDevice.hostMode() == QBluetoothLocalDevice::HostPoweredOff) { connect(&localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)), this, SLOT(hostModeStateChanged(QBluetoothLocalDevice::HostMode))); // connect(localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)), // this, SLOT(hostModeStateChanged(QBluetoothLocalDevice::HostMode))); qDebug() << __PRETTY_FUNCTION__ << "Turning power on"; localDevice.powerOn(); } else { qDebug() << __PRETTY_FUNCTION__ << "<< Power already on! returning true"; return true; } qDebug() << __PRETTY_FUNCTION__ << "<< returning false"; return false; }
DeviceDiscoveryDialog::DeviceDiscoveryDialog(QWidget *parent) : QDialog(parent), localDevice(new QBluetoothLocalDevice), ui(new Ui_DeviceDiscovery) { ui->setupUi(this); /* * In case of multiple Bluetooth adapters it is possible to set adapter * which will be used. Example code: * * QBluetoothAddress address("XX:XX:XX:XX:XX:XX"); * discoveryAgent = new QBluetoothDeviceDiscoveryAgent(address); * **/ discoveryAgent = new QBluetoothDeviceDiscoveryAgent(); connect(ui->inquiryType, SIGNAL(toggled(bool)), this, SLOT(setGeneralUnlimited(bool))); connect(ui->scan, SIGNAL(clicked()), this, SLOT(startScan())); connect(discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), this, SLOT(addDevice(QBluetoothDeviceInfo))); connect(discoveryAgent, SIGNAL(finished()), this, SLOT(scanFinished())); connect(ui->list, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(itemActivated(QListWidgetItem*))); connect(localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)), this, SLOT(hostModeStateChanged(QBluetoothLocalDevice::HostMode))); hostModeStateChanged(localDevice->hostMode()); // add context menu for devices to be able to pair device ui->list->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->list, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(displayPairingMenu(QPoint))); connect(localDevice, SIGNAL(pairingFinished(QBluetoothAddress,QBluetoothLocalDevice::Pairing)) , this, SLOT(pairingDone(QBluetoothAddress,QBluetoothLocalDevice::Pairing))); }
void tst_QBluetoothLocalDevice::tst_powerOn() { { QBluetoothLocalDevice localDevice; QSignalSpy hostModeSpy(&localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode))); // there should be no changes yet QVERIFY(hostModeSpy.isEmpty()); localDevice.powerOn(); // async, wait for it WAIT_FOR_CONDITION(hostModeSpy.count(),1); QVERIFY(hostModeSpy.count() > 0); QBluetoothLocalDevice::HostMode hostMode= localDevice.hostMode(); // we should not be powered off QVERIFY(hostMode == QBluetoothLocalDevice::HostConnectable || hostMode == QBluetoothLocalDevice::HostDiscoverable); } }
void tst_QBluetoothLocalDevice::tst_powerOn() { QBluetoothLocalDevice localDevice; QSignalSpy hostModeSpy(&localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode))); // there should be no changes yet QVERIFY(hostModeSpy.isValid()); QVERIFY(hostModeSpy.isEmpty()); if (!QBluetoothLocalDevice::allDevices().count()) QSKIP("Skipping test due to missing Bluetooth device"); localDevice.powerOn(); // async, wait for it QTRY_VERIFY(hostModeSpy.count() > 0); QBluetoothLocalDevice::HostMode hostMode= localDevice.hostMode(); // we should not be powered off QVERIFY(hostMode == QBluetoothLocalDevice::HostConnectable || hostMode == QBluetoothLocalDevice::HostDiscoverable); }
void tst_QBluetoothLocalDevice::tst_powerOff() { { QBluetoothLocalDevice *device = new QBluetoothLocalDevice(); device->powerOn(); delete device; // wait for the device to switch bluetooth mode. QTest::qWait(1000); } QBluetoothLocalDevice localDevice; QSignalSpy hostModeSpy(&localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode))); // there should be no changes yet QVERIFY(hostModeSpy.isEmpty()); localDevice.setHostMode(QBluetoothLocalDevice::HostPoweredOff); // async, wait for it WAIT_FOR_CONDITION(hostModeSpy.count(),1); QVERIFY(hostModeSpy.count() > 0); // we should not be powered off QVERIFY(localDevice.hostMode() == QBluetoothLocalDevice::HostPoweredOff); }
void tst_QBluetoothDeviceDiscoveryAgent::initTestCase() { qRegisterMetaType<QBluetoothDeviceInfo>("QBluetoothDeviceInfo"); qRegisterMetaType<QBluetoothDeviceDiscoveryAgent::InquiryType>("QBluetoothDeviceDiscoveryAgent::InquiryType"); // turn on BT in case it is not on QBluetoothLocalDevice *device = new QBluetoothLocalDevice(); if (device->hostMode() == QBluetoothLocalDevice::HostPoweredOff) { QSignalSpy hostModeSpy(device, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode))); QVERIFY(hostModeSpy.isEmpty()); device->powerOn(); int connectTime = 5000; // ms while (hostModeSpy.count() < 1 && connectTime > 0) { QTest::qWait(500); connectTime -= 500; } QVERIFY(hostModeSpy.count() > 0); } QBluetoothLocalDevice::HostMode hostMode= device->hostMode(); QVERIFY(hostMode == QBluetoothLocalDevice::HostConnectable || hostMode == QBluetoothLocalDevice::HostDiscoverable || hostMode == QBluetoothLocalDevice::HostDiscoverableLimitedInquiry); delete device; }
void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address) { Q_Q(QBluetoothServiceDiscoveryAgent); if (!btAdapter.isValid()) { error = QBluetoothServiceDiscoveryAgent::UnknownError; errorString = QBluetoothServiceDiscoveryAgent::tr("Platform does not support Bluetooth"); //abort any outstanding discoveries discoveredDevices.clear(); emit q->error(error); _q_serviceDiscoveryFinished(); return; } /* SDP discovery was officially added by Android API v15 * BluetoothDevice.getUuids() existed in earlier APIs already and in the future we may use * reflection to support earlier Android versions than 15. Unfortunately * BluetoothDevice.fetchUuidsWithSdp() and related APIs had some structure changes * over time. Therefore we won't attempt this with reflection. * * TODO: Use reflection to support getUuuids() where possible. * */ if (QtAndroidPrivate::androidSdkVersion() < 15) { qCWarning(QT_BT_ANDROID) << "Aborting SDP enquiry due to too low Android API version (requires v15+)"; error = QBluetoothServiceDiscoveryAgent::UnknownError; errorString = QBluetoothServiceDiscoveryAgent::tr("Android API below v15 does not support SDP discovery"); //abort any outstanding discoveries sdpCache.clear(); discoveredDevices.clear(); emit q->error(error); _q_serviceDiscoveryFinished(); return; } QAndroidJniObject inputString = QAndroidJniObject::fromString(address.toString()); QAndroidJniObject remoteDevice = btAdapter.callObjectMethod("getRemoteDevice", "(Ljava/lang/String;)Landroid/bluetooth/BluetoothDevice;", inputString.object<jstring>()); QAndroidJniEnvironment env; if (env->ExceptionCheck()) { env->ExceptionClear(); env->ExceptionDescribe(); //if it was only device then its error -> otherwise go to next device if (singleDevice) { error = QBluetoothServiceDiscoveryAgent::InputOutputError; errorString = QBluetoothServiceDiscoveryAgent::tr("Cannot create Android BluetoothDevice"); qCWarning(QT_BT_ANDROID) << "Cannot start SDP for" << discoveredDevices.at(0).name() << "(" << address.toString() << ")"; emit q->error(error); } _q_serviceDiscoveryFinished(); return; } if (mode == QBluetoothServiceDiscoveryAgent::MinimalDiscovery) { qCDebug(QT_BT_ANDROID) << "Minimal discovery on (" << discoveredDevices.at(0).name() << ")" << address.toString() ; //Minimal discovery uses BluetoothDevice.getUuids() QAndroidJniObject parcelUuidArray = remoteDevice.callObjectMethod( "getUuids", "()[Landroid/os/ParcelUuid;"); if (!parcelUuidArray.isValid()) { if (singleDevice) { error = QBluetoothServiceDiscoveryAgent::InputOutputError; errorString = QBluetoothServiceDiscoveryAgent::tr("Cannot obtain service uuids"); emit q->error(error); } qCWarning(QT_BT_ANDROID) << "Cannot retrieve SDP UUIDs for" << discoveredDevices.at(0).name() << "(" << address.toString() << ")"; _q_serviceDiscoveryFinished(); return; } const QList<QBluetoothUuid> results = ServiceDiscoveryBroadcastReceiver::convertParcelableArray(parcelUuidArray); populateDiscoveredServices(discoveredDevices.at(0), results); _q_serviceDiscoveryFinished(); } else { qCDebug(QT_BT_ANDROID) << "Full discovery on (" << discoveredDevices.at(0).name() << ")" << address.toString(); //Full discovery uses BluetoothDevice.fetchUuidsWithSdp() if (!receiver) { receiver = new ServiceDiscoveryBroadcastReceiver(); QObject::connect(receiver, SIGNAL(uuidFetchFinished(QBluetoothAddress,QList<QBluetoothUuid>)), q, SLOT(_q_processFetchedUuids(QBluetoothAddress,QList<QBluetoothUuid>))); } if (!localDeviceReceiver) { localDeviceReceiver = new LocalDeviceBroadcastReceiver(); QObject::connect(localDeviceReceiver, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)), q, SLOT(_q_hostModeStateChanged(QBluetoothLocalDevice::HostMode))); } jboolean result = remoteDevice.callMethod<jboolean>("fetchUuidsWithSdp"); if (!result) { //kill receiver to limit load of signals receiver->unregisterReceiver(); receiver->deleteLater(); receiver = 0; qCWarning(QT_BT_ANDROID) << "Cannot start dynamic fetch."; _q_serviceDiscoveryFinished(); } } }
void LocalDeviceBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobject intent) { Q_UNUSED(context); Q_UNUSED(env); QAndroidJniObject intentObject(intent); const QString action = intentObject.callObjectMethod("getAction", "()Ljava/lang/String;").toString(); qCDebug(QT_BT_ANDROID) << QStringLiteral("LocalDeviceBroadcastReceiver::onReceive() - event: %1").arg(action); if (action == valueForStaticField(JavaNames::BluetoothAdapter, JavaNames::ActionScanModeChanged).toString()) { const QAndroidJniObject extrasBundle = intentObject.callObjectMethod("getExtras","()Landroid/os/Bundle;"); const QAndroidJniObject keyExtra = valueForStaticField(JavaNames::BluetoothAdapter, JavaNames::ExtraScanMode); int extra = extrasBundle.callMethod<jint>("getInt", "(Ljava/lang/String;)I", keyExtra.object<jstring>()); if (previousScanMode != extra) { previousScanMode = extra; if (extra == hostModePreset[0]) emit hostModeStateChanged(QBluetoothLocalDevice::HostPoweredOff); else if (extra == hostModePreset[1]) emit hostModeStateChanged(QBluetoothLocalDevice::HostConnectable); else if (extra == hostModePreset[2]) emit hostModeStateChanged(QBluetoothLocalDevice::HostDiscoverable); else qCWarning(QT_BT_ANDROID) << "Unknown Host State"; } } else if (action == valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionBondStateChanged).toString()) { //get BluetoothDevice QAndroidJniObject keyExtra = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ExtraDevice); const QAndroidJniObject bluetoothDevice = intentObject.callObjectMethod("getParcelableExtra", "(Ljava/lang/String;)Landroid/os/Parcelable;", keyExtra.object<jstring>()); //get new bond state keyExtra = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ExtraBondState); const QAndroidJniObject extrasBundle = intentObject.callObjectMethod("getExtras","()Landroid/os/Bundle;"); int bondState = extrasBundle.callMethod<jint>("getInt", "(Ljava/lang/String;)I", keyExtra.object<jstring>()); QBluetoothAddress address(bluetoothDevice.callObjectMethod<jstring>("getAddress").toString()); if (address.isNull()) return; if (bondState == bondingModePreset[0]) emit pairingStateChanged(address, QBluetoothLocalDevice::Unpaired); else if (bondState == bondingModePreset[1]) ; //we ignore this as Qt doesn't have equivalent API value else if (bondState == bondingModePreset[2]) emit pairingStateChanged(address, QBluetoothLocalDevice::Paired); else qCWarning(QT_BT_ANDROID) << "Unknown BOND_STATE_CHANGED value:" << bondState; } else if (action == valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionAclConnected).toString() || action == valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionAclDisconnected).toString()) { const QString connectEvent = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionAclConnected).toString(); const bool isConnectEvent = action == connectEvent ? true : false; //get BluetoothDevice const QAndroidJniObject keyExtra = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ExtraDevice); QAndroidJniObject bluetoothDevice = intentObject.callObjectMethod("getParcelableExtra", "(Ljava/lang/String;)Landroid/os/Parcelable;", keyExtra.object<jstring>()); QBluetoothAddress address(bluetoothDevice.callObjectMethod<jstring>("getAddress").toString()); if (address.isNull()) return; emit connectDeviceChanges(address, isConnectEvent); } else if (action == valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionPairingRequest).toString()) { QAndroidJniObject keyExtra = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ExtraPairingVariant); int variant = intentObject.callMethod<jint>("getIntExtra", "(Ljava/lang/String;I)I", keyExtra.object<jstring>(), -1); int key = -1; switch (variant) { case -1: //ignore -> no pairing variant set return; case 2: //BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION { keyExtra = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ExtraPairingKey); key = intentObject.callMethod<jint>("getIntExtra", "(Ljava/lang/String;I)I", keyExtra.object<jstring>(), -1); if (key == -1) return; keyExtra = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ExtraDevice); QAndroidJniObject bluetoothDevice = intentObject.callObjectMethod("getParcelableExtra", "(Ljava/lang/String;)Landroid/os/Parcelable;", keyExtra.object<jstring>()); //we need to keep a reference around in case the user confirms later on pairingDevice = bluetoothDevice; QBluetoothAddress address(bluetoothDevice.callObjectMethod<jstring>("getAddress").toString()); //User has choice to confirm or not. If no confirmation is happening //the OS default pairing dialog can be used or timeout occurs. emit pairingDisplayConfirmation(address, QString::number(key)); break; } default: qCWarning(QT_BT_ANDROID) << "Unknown pairing variant: " << variant; return; } } }