170 Q_Q(QBluetoothSocket);
172 qCWarning(QT_BT_ANDROID) <<
"Falling back to reverse uuid workaround.";
173 const QBluetoothUuid reverse = reverseUuid(uuid);
174 if (reverse.isNull())
177 QString tempUuid = reverse.toString(QUuid::WithoutBraces);
180 const QJniObject inputString = QJniObject::fromString(tempUuid);
181 const QJniObject uuidObject = QJniObject::callStaticMethod<QtJniTypes::UUID>(
182 QtJniTypes::Traits<QtJniTypes::UUID>::className(),
"fromString",
183 inputString.object<jstring>());
185 if (secFlags == QBluetooth::SecurityFlags(QBluetooth::Security::NoSecurity)) {
186 qCDebug(QT_BT_ANDROID) <<
"Connecting via insecure rfcomm";
187 socketObject = remoteDevice.callMethod<QtJniTypes::BluetoothSocket>(
188 "createInsecureRfcommSocketToServiceRecord",
189 uuidObject.object<QtJniTypes::UUID>());
191 qCDebug(QT_BT_ANDROID) <<
"Connecting via secure rfcomm";
192 socketObject = remoteDevice.callMethod<QtJniTypes::BluetoothSocket>(
193 "createRfcommSocketToServiceRecord",
194 uuidObject.object<QtJniTypes::UUID>());
197 if (!socketObject.isValid()) {
198 remoteDevice = QJniObject();
199 errorString = QBluetoothSocket::tr(
"Cannot connect to %1",
200 "%1 = uuid").arg(reverse.toString());
201 q->setSocketError(QBluetoothSocket::SocketError::ServiceNotFoundError);
202 q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
207 workerThread->setupWorker(
this, socketObject, uuidObject,
USE_FALLBACK);
208 workerThread->start();
209 emit connectJavaSocket();
232 const QBluetoothUuid &uuid,
233 QIODevice::OpenMode openMode)
235 Q_Q(QBluetoothSocket);
238 qCDebug(QT_BT_ANDROID) <<
"connectToServiceHelper()" << address.toString() << uuid.toString();
240 if (!ensureAndroidPermission(QBluetoothPermission::Access)) {
241 qCWarning(QT_BT_ANDROID) <<
"Bluetooth socket connect failed due to missing permissions";
242 errorString = QBluetoothSocket::tr(
243 "Bluetooth socket connect failed due to missing permissions.");
244 q->setSocketError(QBluetoothSocket::SocketError::MissingPermissionsError);
245 q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
249 q->setSocketState(QBluetoothSocket::SocketState::ConnectingState);
251 if (!adapter.isValid()) {
252 qCWarning(QT_BT_ANDROID) <<
"Device does not support Bluetooth";
253 errorString = QBluetoothSocket::tr(
"Device does not support Bluetooth");
254 q->setSocketError(QBluetoothSocket::SocketError::NetworkError);
255 q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
259 const int state = adapter.callMethod<jint>(
"getState");
261 qCWarning(QT_BT_ANDROID) <<
"Bluetooth device offline";
262 errorString = QBluetoothSocket::tr(
"Device is powered off");
263 q->setSocketError(QBluetoothSocket::SocketError::NetworkError);
264 q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
269 QJniObject inputString = QJniObject::fromString(address.toString());
270 remoteDevice = adapter.callMethod<QtJniTypes::BluetoothDevice>(
"getRemoteDevice",
271 inputString.object<jstring>());
272 if (!remoteDevice.isValid()) {
273 errorString = QBluetoothSocket::tr(
"Cannot access address %1",
"%1 = Bt address e.g. 11:22:33:44:55:66").arg(address.toString());
274 q->setSocketError(QBluetoothSocket::SocketError::HostNotFoundError);
275 q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
280 const QString tempUuid = uuid.toString(QUuid::WithoutBraces);
282 inputString = QJniObject::fromString(tempUuid);
283 const QJniObject uuidObject = QJniObject::callStaticMethod<QtJniTypes::UUID>(
284 QtJniTypes::Traits<QtJniTypes::UUID>::className(),
"fromString",
285 inputString.object<jstring>());
287 if (secFlags == QBluetooth::SecurityFlags(QBluetooth::Security::NoSecurity)) {
288 qCDebug(QT_BT_ANDROID) <<
"Connecting via insecure rfcomm";
289 socketObject = remoteDevice.callMethod<QtJniTypes::BluetoothSocket>(
290 "createInsecureRfcommSocketToServiceRecord",
291 uuidObject.object<QtJniTypes::UUID>());
293 qCDebug(QT_BT_ANDROID) <<
"Connecting via secure rfcomm";
294 socketObject = remoteDevice.callMethod<QtJniTypes::BluetoothSocket>(
295 "createRfcommSocketToServiceRecord",
296 uuidObject.object<QtJniTypes::UUID>());
299 if (!socketObject.isValid()) {
300 remoteDevice = QJniObject();
301 errorString = QBluetoothSocket::tr(
"Cannot connect to %1 on %2",
302 "%1 = uuid, %2 = Bt address").arg(uuid.toString()).arg(address.toString());
303 q->setSocketError(QBluetoothSocket::SocketError::ServiceNotFoundError);
304 q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
309 workerThread->setupWorker(
this, socketObject, uuidObject, !
USE_FALLBACK, uuid);
310 workerThread->start();
311 emit connectJavaSocket();
315 const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode)
317 Q_Q(QBluetoothSocket);
319 if (q->state() != QBluetoothSocket::SocketState::UnconnectedState
320 && q->state() != QBluetoothSocket::SocketState::ServiceLookupState) {
321 qCWarning(QT_BT_ANDROID) <<
"QBluetoothSocketPrivateAndroid::connectToService called on busy socket";
322 errorString = QBluetoothSocket::tr(
"Trying to connect while connection is in progress");
323 q->setSocketError(QBluetoothSocket::SocketError::OperationError);
329
330
331
332
333
334
335
336
337
338
339
340
342 auto protocol = service.socketProtocol();
344 case QBluetoothServiceInfo::L2capProtocol:
345 case QBluetoothServiceInfo::UnknownProtocol:
346 qCWarning(QT_BT_ANDROID) <<
"Changing socket protocol to RFCOMM";
347 protocol = QBluetoothServiceInfo::RfcommProtocol;
349 case QBluetoothServiceInfo::RfcommProtocol:
353 if (!ensureNativeSocket(protocol)) {
354 errorString = QBluetoothSocket::tr(
"Socket type not supported");
355 q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError);
358 connectToServiceHelper(service.device().address(), service.serviceUuid(), openMode);
362 const QBluetoothAddress &address,
const QBluetoothUuid &uuid,
363 QIODevice::OpenMode openMode)
365 Q_Q(QBluetoothSocket);
367 if (q->state() != QBluetoothSocket::SocketState::UnconnectedState) {
368 qCWarning(QT_BT_ANDROID) <<
"QBluetoothSocketPrivateAndroid::connectToService called on busy socket";
369 errorString = QBluetoothSocket::tr(
"Trying to connect while connection is in progress");
370 q->setSocketError(QBluetoothSocket::SocketError::OperationError);
374 if (q->socketType() == QBluetoothServiceInfo::UnknownProtocol) {
375 qCWarning(QT_BT_ANDROID) <<
"QBluetoothSocketPrivateAndroid::connectToService cannot "
376 "connect with 'UnknownProtocol' (type provided by given service)";
377 errorString = QBluetoothSocket::tr(
"Socket type not supported");
378 q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError);
382 if (!ensureNativeSocket(q->socketType())) {
383 errorString = QBluetoothSocket::tr(
"Socket type not supported");
384 q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError);
387 connectToServiceHelper(address, uuid, openMode);
406 Q_Q(QBluetoothSocket);
411 if (socket != socketObject)
419 inputStream = socketObject.callMethod<QtJniTypes::InputStream>(
"getInputStream");
420 outputStream = socketObject.callMethod<QtJniTypes::OutputStream>(
"getOutputStream");
422 if (!inputStream.isValid() || !outputStream.isValid()) {
424 emit closeJavaSocket();
425 socketObject = inputStream = outputStream = remoteDevice = QJniObject();
428 errorString = QBluetoothSocket::tr(
"Obtaining streams for service failed");
429 q->setSocketError(QBluetoothSocket::SocketError::NetworkError);
430 q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
434 inputThread =
new InputStreamThread(
this);
435 QObject::connect(inputThread, SIGNAL(dataAvailable()),
436 q, SIGNAL(readyRead()), Qt::QueuedConnection);
437 QObject::connect(inputThread, SIGNAL(errorOccurred(
int)),
this, SLOT(inputThreadError(
int)),
438 Qt::QueuedConnection);
442 emit closeJavaSocket();
444 socketObject = inputStream = outputStream = remoteDevice = QJniObject();
449 errorString = QBluetoothSocket::tr(
"Input stream thread cannot be started");
450 q->setSocketError(QBluetoothSocket::SocketError::NetworkError);
451 q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
456 q->setOpenMode(QIODevice::ReadWrite|QIODevice::Unbuffered);
458 q->setSocketState(QBluetoothSocket::SocketState::ConnectedState);
462 const QJniObject &socket,
const QJniObject &targetUuid,
463 const QBluetoothUuid &qtTargetUuid)
465 Q_UNUSED(targetUuid);
466 Q_Q(QBluetoothSocket);
470 if (socket != socketObject)
473 if (!useReverseUuidWorkAroundConnect || !fallBackReversedConnect(qtTargetUuid)) {
474 errorString = QBluetoothSocket::tr(
"Connection to service failed");
475 socketObject = remoteDevice = QJniObject();
476 q->setSocketError(QBluetoothSocket::SocketError::ServiceNotFoundError);
477 q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
478 qCWarning(QT_BT_ANDROID) <<
"Socket connect workaround failed";
603 Q_Q(QBluetoothSocket);
604 if (state != QBluetoothSocket::SocketState::ConnectedState || !outputStream.isValid()) {
605 qCWarning(QT_BT_ANDROID) <<
"Socket::writeData: " << state << outputStream.isValid();
606 errorString = QBluetoothSocket::tr(
"Cannot write while not connected");
607 q->setSocketError(QBluetoothSocket::SocketError::OperationError);
611 const qint32 javaSize = q26::saturate_cast<qint32>(maxSize);
613 jbyteArray nativeData = env->NewByteArray(javaSize);
614 env->SetByteArrayRegion(nativeData, 0, javaSize,
reinterpret_cast<
const jbyte*>(data));
615 auto methodId = env.findMethod(outputStream.objectClass(),
619 env->CallVoidMethod(outputStream.object(), methodId, nativeData, 0, javaSize);
620 env->DeleteLocalRef(nativeData);
622 if (!methodId || env.checkAndClearExceptions()) {
623 qCWarning(QT_BT_ANDROID) <<
"Error while writing";
624 errorString = QBluetoothSocket::tr(
"Error during write on socket.");
625 q->setSocketError(QBluetoothSocket::SocketError::NetworkError);
629 emit q->bytesWritten(javaSize);
700 QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode)
702 Q_Q(QBluetoothSocket);
704 if (q->state() != QBluetoothSocket::SocketState::UnconnectedState || !socket.isValid())
707 if (!ensureNativeSocket(socketType_))
710 socketObject = socket;
712 inputStream = socketObject.callMethod<QtJniTypes::InputStream>(
"getInputStream");
713 outputStream = socketObject.callMethod<QtJniTypes::OutputStream>(
"getOutputStream");
715 if (!inputStream.isValid() || !outputStream.isValid()) {
718 socketObject.callMethod<
void>(
"close");
720 socketObject = inputStream = outputStream = remoteDevice = QJniObject();
723 errorString = QBluetoothSocket::tr(
"Obtaining streams for service failed");
724 q->setSocketError(QBluetoothSocket::SocketError::NetworkError);
725 q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
729 remoteDevice = socketObject.callMethod<QtJniTypes::BluetoothDevice>(
"getRemoteDevice");
735 inputThread =
new InputStreamThread(
this);
736 QObject::connect(inputThread, SIGNAL(dataAvailable()),
737 q, SIGNAL(readyRead()), Qt::QueuedConnection);
738 QObject::connect(inputThread, SIGNAL(errorOccurred(
int)),
this, SLOT(inputThreadError(
int)),
739 Qt::QueuedConnection);
747 workerThread->setupWorker(
this, socketObject, QJniObject(), !
USE_FALLBACK);
748 workerThread->start();
750 q->setOpenMode(openMode | QIODevice::Unbuffered);
751 q->setSocketState(socketState);