summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@digia.com>2014-03-14 11:16:27 +0100
committerAlex Blasche <alexander.blasche@digia.com>2014-03-14 11:16:27 +0100
commit83cd348bde8e856d2508c2514cd33a90e593461d (patch)
tree9dbd933129ef4a9e514218fc6177d775aa94c9db /src
parent4439541b05ae88a30159a5597d40f569328783ca (diff)
parent40ac14e13b0aa07124c6ae9ef8eacfe6d8550684 (diff)
Merge branch 'dev' into btle
Conflicts: src/bluetooth/qbluetoothuuid.cpp tests/bttestui/btlocaldevice.cpp Change-Id: Id16ab93ec61361950669da7eb232769c5dc4644f
Diffstat (limited to 'src')
-rw-r--r--src/android/bluetooth/bluetooth.pri5
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java15
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothInputStreamThread.java103
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothSocketServer.java153
-rw-r--r--src/bluetooth/android/android.pri3
-rw-r--r--src/bluetooth/android/androidbroadcastreceiver.cpp13
-rw-r--r--src/bluetooth/android/androidbroadcastreceiver_p.h4
-rw-r--r--src/bluetooth/android/devicediscoverybroadcastreceiver.cpp29
-rw-r--r--src/bluetooth/android/inputstreamthread.cpp110
-rw-r--r--src/bluetooth/android/inputstreamthread_p.h21
-rw-r--r--src/bluetooth/android/jni_android.cpp171
-rw-r--r--src/bluetooth/android/jni_android_p.h75
-rw-r--r--src/bluetooth/android/localdevicebroadcastreceiver.cpp131
-rw-r--r--src/bluetooth/android/localdevicebroadcastreceiver_p.h3
-rw-r--r--src/bluetooth/android/serveracceptancethread.cpp202
-rw-r--r--src/bluetooth/android/serveracceptancethread_p.h26
-rw-r--r--src/bluetooth/android/servicediscoverybroadcastreceiver.cpp18
-rw-r--r--src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp78
-rw-r--r--src/bluetooth/doc/snippets/doc_src_qtbluetooth.pro43
-rw-r--r--src/bluetooth/doc/snippets/snippets.pro8
-rw-r--r--src/bluetooth/doc/src/bluetooth-cpp.qdoc2
-rw-r--r--src/bluetooth/doc/src/bluetooth-index.qdoc7
-rw-r--r--src/bluetooth/doc/src/bluetooth-overview.qdoc28
-rw-r--r--src/bluetooth/doc/src/examples.qdoc2
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp9
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_qnx.cpp2
-rw-r--r--src/bluetooth/qbluetoothhostinfo.cpp13
-rw-r--r--src/bluetooth/qbluetoothhostinfo.h2
-rw-r--r--src/bluetooth/qbluetoothlocaldevice.cpp14
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_android.cpp1
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_bluez.cpp3
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_qnx.cpp37
-rw-r--r--src/bluetooth/qbluetoothserver.cpp4
-rw-r--r--src/bluetooth/qbluetoothserver_android.cpp62
-rw-r--r--src/bluetooth/qbluetoothserver_bluez.cpp20
-rw-r--r--src/bluetooth/qbluetoothserver_p.cpp7
-rw-r--r--src/bluetooth/qbluetoothserver_qnx.cpp56
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_android.cpp41
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp1
-rw-r--r--src/bluetooth/qbluetoothserviceinfo.cpp3
-rw-r--r--src/bluetooth/qbluetoothserviceinfo_qnx.cpp23
-rw-r--r--src/bluetooth/qbluetoothsocket.cpp3
-rw-r--r--src/bluetooth/qbluetoothsocket_android.cpp98
-rw-r--r--src/bluetooth/qbluetoothsocket_bluez.cpp27
-rw-r--r--src/bluetooth/qbluetoothsocket_p.cpp32
-rw-r--r--src/bluetooth/qbluetoothsocket_p.h5
-rw-r--r--src/bluetooth/qbluetoothsocket_qnx.cpp25
-rw-r--r--src/bluetooth/qbluetoothuuid.cpp154
-rw-r--r--src/bluetooth/qbluetoothuuid.h10
-rw-r--r--src/imports/bluetooth/plugin.cpp6
-rw-r--r--src/imports/bluetooth/plugins.qmltypes4
-rw-r--r--src/imports/nfc/plugin.cpp8
-rw-r--r--src/imports/nfc/plugins.qmltypes4
-rw-r--r--src/imports/nfc/qdeclarativenearfield.cpp9
-rw-r--r--src/nfc/doc/snippets/doc_src_qtnfc.cpp24
-rw-r--r--src/nfc/doc/snippets/doc_src_qtnfc.pro51
-rw-r--r--src/nfc/doc/snippets/doc_src_qtnfc.qml12
-rw-r--r--src/nfc/doc/snippets/snippets.pro13
-rw-r--r--src/nfc/doc/src/nfc-cpp.qdoc2
-rw-r--r--src/nfc/doc/src/nfc-index.qdoc4
-rw-r--r--src/nfc/doc/src/nfc-overview.qdoc115
-rw-r--r--src/nfc/qnearfieldmanager.cpp6
-rw-r--r--src/nfc/qnearfieldmanager_qnx.cpp4
-rw-r--r--src/nfc/qnearfieldsharemanager.cpp1
-rw-r--r--src/nfc/qnearfieldsharetarget.cpp3
-rw-r--r--src/nfc/qnearfieldtagtype3.cpp2
-rw-r--r--src/nfc/qnearfieldtarget_qnx_p.h2
-rw-r--r--src/src.pro15
68 files changed, 1505 insertions, 682 deletions
diff --git a/src/android/bluetooth/bluetooth.pri b/src/android/bluetooth/bluetooth.pri
index 5c2cb8f8..b2121ff3 100644
--- a/src/android/bluetooth/bluetooth.pri
+++ b/src/android/bluetooth/bluetooth.pri
@@ -5,7 +5,10 @@ PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/bluetooth
JAVACLASSPATH += $$PWD/src/
JAVASOURCES += \
- $$PATHPREFIX/QtBluetoothBroadcastReceiver.java
+ $$PATHPREFIX/QtBluetoothBroadcastReceiver.java \
+ $$PATHPREFIX/QtBluetoothSocketServer.java \
+ $$PATHPREFIX/QtBluetoothInputStreamThread.java
+
# install
target.path = $$[QT_INSTALL_PREFIX]/jar
diff --git a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java
index 1f0049ef..ba96c0cf 100644
--- a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java
+++ b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver.java
@@ -62,7 +62,20 @@ public class QtBluetoothBroadcastReceiver extends BroadcastReceiver
public void onReceive(Context context, Intent intent)
{
- jniOnReceive(qtObject, context, intent);
+ synchronized (qtactivity) {
+ if (qtObject == 0)
+ return;
+
+ jniOnReceive(qtObject, context, intent);
+ }
+ }
+
+ public void unregisterReceiver()
+ {
+ synchronized (qtactivity) {
+ qtObject = 0;
+ qtactivity.unregisterReceiver(this);
+ }
}
public native void jniOnReceive(long qtObject, Context context, Intent intent);
diff --git a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothInputStreamThread.java b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothInputStreamThread.java
new file mode 100644
index 00000000..57636ad4
--- /dev/null
+++ b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothInputStreamThread.java
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+package org.qtproject.qt5.android.bluetooth;
+
+import java.io.InputStream;
+import java.io.IOException;
+import android.util.Log;
+
+public class QtBluetoothInputStreamThread extends Thread
+{
+ /* Pointer to the Qt object that "owns" the Java object */
+ long qtObject = 0;
+ public boolean logEnabled = false;
+ private static final String TAG = "QtBluetooth";
+ private InputStream m_inputStream = null;
+
+ //error codes
+ public static final int QT_MISSING_INPUT_STREAM = 0;
+ public static final int QT_READ_FAILED = 1;
+ public static final int QT_THREAD_INTERRUPTED = 2;
+
+ public QtBluetoothInputStreamThread()
+ {
+ setName("QtBtInputStreamThread");
+ }
+
+ public void setInputStream(InputStream stream)
+ {
+ m_inputStream = stream;
+ }
+
+ public void run()
+ {
+ if (m_inputStream == null) {
+ errorOccurred(qtObject, QT_MISSING_INPUT_STREAM);
+ return;
+ }
+
+ byte[] buffer = new byte[1000];
+ int bytesRead = 0;
+
+ try {
+ while (!isInterrupted()) {
+ //this blocks until we see incoming data
+ //or close() on related BluetoothSocket is called
+ bytesRead = m_inputStream.read(buffer);
+ readyData(qtObject, buffer, bytesRead);
+ }
+
+ errorOccurred(qtObject, QT_THREAD_INTERRUPTED);
+ } catch (IOException ex) {
+ if (logEnabled)
+ Log.d(TAG, "InputStream.read() failed:" + ex.toString());
+ ex.printStackTrace();
+ errorOccurred(qtObject, QT_READ_FAILED);
+ }
+
+ if (logEnabled)
+ Log.d(TAG, "Leaving input stream thread");
+ }
+
+ public static native void errorOccurred(long qtObject, int errorCode);
+ public static native void readyData(long qtObject, byte[] buffer, int bufferLength);
+}
diff --git a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothSocketServer.java b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothSocketServer.java
new file mode 100644
index 00000000..ee365a49
--- /dev/null
+++ b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothSocketServer.java
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+package org.qtproject.qt5.android.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothServerSocket;
+import android.bluetooth.BluetoothSocket;
+import android.util.Log;
+import java.io.IOException;
+import java.util.UUID;
+
+public class QtBluetoothSocketServer extends Thread
+{
+
+ /* Pointer to the Qt object that "owns" the Java object */
+ long qtObject = 0;
+ public boolean logEnabled = false;
+
+ private static final String TAG = "QtBluetooth";
+ private boolean m_isSecure = false;
+ private UUID m_uuid;
+ private String m_serviceName;
+ private BluetoothServerSocket m_serverSocket = null;
+
+ //error codes
+ public static final int QT_NO_BLUETOOTH_SUPPORTED = 0;
+ public static final int QT_LISTEN_FAILED = 1;
+ public static final int QT_ACCEPT_FAILED = 2;
+
+ public QtBluetoothSocketServer()
+ {
+ setName("QtSocketServerThread");
+ }
+
+ public void setServiceDetails(String uuid, String serviceName, boolean isSecure)
+ {
+ m_uuid = UUID.fromString(uuid);
+ m_serviceName = serviceName;
+ m_isSecure = isSecure;
+
+ }
+
+ public void run()
+ {
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ if (adapter == null) {
+ errorOccurred(qtObject, QT_NO_BLUETOOTH_SUPPORTED);
+ return;
+ }
+
+ try {
+ if (m_isSecure) {
+ m_serverSocket = adapter.listenUsingRfcommWithServiceRecord(m_serviceName, m_uuid);
+ if (logEnabled)
+ Log.d(TAG, "Using secure socket listener");
+ } else {
+ m_serverSocket = adapter.listenUsingInsecureRfcommWithServiceRecord(m_serviceName, m_uuid);
+ if (logEnabled)
+ Log.d(TAG, "Using insecure socket listener");
+ }
+ } catch (IOException ex) {
+ if (logEnabled)
+ Log.d(TAG, "Server socket listen() failed:" + ex.toString());
+ ex.printStackTrace();
+ errorOccurred(qtObject, QT_LISTEN_FAILED);
+ return;
+ }
+
+ BluetoothSocket s = null;
+ if (m_serverSocket != null) {
+ try {
+ while (!isInterrupted()) {
+ //this blocks until we see incoming connection
+ //or close() is called
+ if (logEnabled)
+ Log.d(TAG, "Waiting for new incoming socket");
+ s = m_serverSocket.accept();
+
+ if (logEnabled)
+ Log.d(TAG, "New socket accepted");
+ newSocket(qtObject, s);
+ }
+ } catch (IOException ex) {
+ if (logEnabled)
+ Log.d(TAG, "Server socket accept() failed:" + ex.toString());
+ ex.printStackTrace();
+ errorOccurred(qtObject, QT_ACCEPT_FAILED);
+ }
+ }
+
+ Log.d(TAG, "Leaving server socket thread.");
+ }
+
+ public void close()
+ {
+ if (!isAlive())
+ return;
+
+ try {
+ //ensure closing of thread if we are not currently blocking on accept()
+ interrupt();
+
+ //interrupts accept() call above
+ if (m_serverSocket != null)
+ m_serverSocket.close();
+ } catch (IOException ex) {
+ Log.d(TAG, "Closing server socket close() failed:" + ex.toString());
+ ex.printStackTrace();
+ }
+ }
+
+ public static native void errorOccurred(long qtObject, int errorCode);
+ public static native void newSocket(long qtObject, BluetoothSocket socket);
+}
diff --git a/src/bluetooth/android/android.pri b/src/bluetooth/android/android.pri
index 3c8a0380..0507894f 100644
--- a/src/bluetooth/android/android.pri
+++ b/src/bluetooth/android/android.pri
@@ -4,7 +4,8 @@ PRIVATE_HEADERS += \
android/servicediscoverybroadcastreceiver_p.h \
android/androidbroadcastreceiver_p.h \
android/localdevicebroadcastreceiver_p.h \
- android/serveracceptancethread_p.h
+ android/serveracceptancethread_p.h \
+ android/jni_android_p.h
SOURCES += \
diff --git a/src/bluetooth/android/androidbroadcastreceiver.cpp b/src/bluetooth/android/androidbroadcastreceiver.cpp
index affa7683..c17502ba 100644
--- a/src/bluetooth/android/androidbroadcastreceiver.cpp
+++ b/src/bluetooth/android/androidbroadcastreceiver.cpp
@@ -72,7 +72,6 @@ AndroidBroadcastReceiver::AndroidBroadcastReceiver(QObject* parent)
AndroidBroadcastReceiver::~AndroidBroadcastReceiver()
{
- unregisterReceiver();
}
bool AndroidBroadcastReceiver::isValid() const
@@ -85,19 +84,15 @@ void AndroidBroadcastReceiver::unregisterReceiver()
if (!valid)
return;
- activityObject.callObjectMethod(
- "unregisterReceiver",
- "(Landroid/content/BroadcastReceiver;)V",
- broadcastReceiverObject.object<jobject>());
+ broadcastReceiverObject.callMethod<void>("unregisterReceiver");
}
-void AndroidBroadcastReceiver::addAction(const QString &action)
+void AndroidBroadcastReceiver::addAction(const QAndroidJniObject &action)
{
- if (!valid)
+ if (!valid || !action.isValid())
return;
- QAndroidJniObject actionString = QAndroidJniObject::fromString(action);
- intentFilterObject.callMethod<void>("addAction", "(Ljava/lang/String;)V", actionString.object<jstring>());
+ intentFilterObject.callMethod<void>("addAction", "(Ljava/lang/String;)V", action.object<jstring>());
activityObject.callObjectMethod(
"registerReceiver",
diff --git a/src/bluetooth/android/androidbroadcastreceiver_p.h b/src/bluetooth/android/androidbroadcastreceiver_p.h
index baae6798..58c2b40b 100644
--- a/src/bluetooth/android/androidbroadcastreceiver_p.h
+++ b/src/bluetooth/android/androidbroadcastreceiver_p.h
@@ -58,14 +58,14 @@ public:
AndroidBroadcastReceiver(QObject* parent = 0);
virtual ~AndroidBroadcastReceiver();
- void addAction(const QString &filter);
+ void addAction(const QAndroidJniObject &filter);
bool isValid() const;
+ void unregisterReceiver();
protected:
friend void QtBroadcastReceiver_jniOnReceive(JNIEnv *, jobject, jlong, jobject, jobject);
virtual void onReceive(JNIEnv *env, jobject context, jobject intent) = 0;
- void unregisterReceiver();
QAndroidJniObject activityObject;
QAndroidJniObject intentFilterObject;
diff --git a/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
index 16a6afe4..ca62f013 100644
--- a/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
+++ b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
@@ -44,6 +44,7 @@
#include <QtCore/QLoggingCategory>
#include <QtBluetooth/QBluetoothAddress>
#include <QtBluetooth/QBluetoothDeviceInfo>
+#include "android/jni_android_p.h"
QT_BEGIN_NAMESPACE
@@ -51,9 +52,9 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
DeviceDiscoveryBroadcastReceiver::DeviceDiscoveryBroadcastReceiver(QObject* parent): AndroidBroadcastReceiver(parent)
{
- addAction(QStringLiteral("android.bluetooth.device.action.FOUND"));
- addAction(QStringLiteral("android.bluetooth.adapter.action.DISCOVERY_STARTED"));
- addAction(QStringLiteral("android.bluetooth.adapter.action.DISCOVERY_FINISHED"));
+ addAction(valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionFound));
+ addAction(valueForStaticField(JavaNames::BluetoothAdapter, JavaNames::ActionDiscoveryStarted));
+ addAction(valueForStaticField(JavaNames::BluetoothAdapter, JavaNames::ActionDiscoveryFinished));
}
void DeviceDiscoveryBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobject intent)
@@ -66,15 +67,18 @@ void DeviceDiscoveryBroadcastReceiver::onReceive(JNIEnv *env, jobject context, j
qCDebug(QT_BT_ANDROID) << "DeviceDiscoveryBroadcastReceiver::onReceive() - event:" << action;
- if (action == QStringLiteral("android.bluetooth.adapter.action.DISCOVERY_FINISHED") ) {
+ if (action == valueForStaticField(JavaNames::BluetoothAdapter,
+ JavaNames::ActionDiscoveryFinished).toString()) {
emit finished();
- } else if (action == QStringLiteral("android.bluetooth.adapter.action.DISCOVERY_STARTED") ) {
+ } else if (action == valueForStaticField(JavaNames::BluetoothAdapter,
+ JavaNames::ActionDiscoveryStarted).toString()) {
- } else if (action == QStringLiteral("android.bluetooth.device.action.FOUND")) {
+ } else if (action == valueForStaticField(JavaNames::BluetoothDevice,
+ JavaNames::ActionFound).toString()) {
//get BluetoothDevice
- QAndroidJniObject keyExtra = QAndroidJniObject::fromString(
- QStringLiteral("android.bluetooth.device.extra.DEVICE"));
- QAndroidJniObject bluetoothDevice =
+ QAndroidJniObject keyExtra = valueForStaticField(JavaNames::BluetoothDevice,
+ JavaNames::ExtraDevice);
+ const QAndroidJniObject bluetoothDevice =
intentObject.callObjectMethod("getParcelableExtra",
"(Ljava/lang/String;)Landroid/os/Parcelable;",
keyExtra.object<jstring>());
@@ -84,13 +88,14 @@ void DeviceDiscoveryBroadcastReceiver::onReceive(JNIEnv *env, jobject context, j
const QString deviceName = bluetoothDevice.callObjectMethod<jstring>("getName").toString();
const QBluetoothAddress deviceAddress(bluetoothDevice.callObjectMethod<jstring>("getAddress").toString());
- keyExtra = QAndroidJniObject::fromString(
- QStringLiteral("android.bluetooth.device.extra.RSSI"));
+ keyExtra = valueForStaticField(JavaNames::BluetoothDevice,
+ JavaNames::ExtraRssi);
+
int rssi = intentObject.callMethod<jshort>("getShortExtra",
"(Ljava/lang/String;S)S",
keyExtra.object<jstring>(),
0);
- QAndroidJniObject bluetoothClass = bluetoothDevice.callObjectMethod("getBluetoothClass",
+ const QAndroidJniObject bluetoothClass = bluetoothDevice.callObjectMethod("getBluetoothClass",
"()Landroid/bluetooth/BluetoothClass;");
if (!bluetoothClass.isValid())
return;
diff --git a/src/bluetooth/android/inputstreamthread.cpp b/src/bluetooth/android/inputstreamthread.cpp
index df32ee62..7f5029d9 100644
--- a/src/bluetooth/android/inputstreamthread.cpp
+++ b/src/bluetooth/android/inputstreamthread.cpp
@@ -40,6 +40,7 @@
**
****************************************************************************/
+#include <QtCore/QLoggingCategory>
#include <QtAndroidExtras/QAndroidJniEnvironment>
#include "android/inputstreamthread_p.h"
@@ -47,34 +48,29 @@
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
InputStreamThread::InputStreamThread(QBluetoothSocketPrivate *socket)
- : QThread(), m_stop(false)
+ : QObject(), m_socket_p(socket), expectClosure(false)
{
- m_socket_p = socket;
}
-void InputStreamThread::run()
+bool InputStreamThread::run()
{
- qint32 byte;
- Q_UNUSED(byte)
- while (1) {
- {
- QMutexLocker locker(&m_mutex);
- if (m_stop)
- break;
- }
- readFromInputStream();
- }
+ QMutexLocker lock(&m_mutex);
- QAndroidJniEnvironment env;
- if (m_socket_p->inputStream.isValid())
- m_socket_p->inputStream.callMethod<void>("close");
+ javaInputStreamThread = QAndroidJniObject("org/qtproject/qt5/android/bluetooth/QtBluetoothInputStreamThread");
+ if (!javaInputStreamThread.isValid() || !m_socket_p->inputStream.isValid())
+ return false;
+
+ javaInputStreamThread.callMethod<void>("setInputStream", "(Ljava/io/InputStream;)V",
+ m_socket_p->inputStream.object<jobject>());
+ javaInputStreamThread.setField<jlong>("qtObject", reinterpret_cast<long>(this));
+ javaInputStreamThread.setField<jboolean>("logEnabled", QT_BT_ANDROID().isDebugEnabled());
+
+ javaInputStreamThread.callMethod<void>("start");
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
+ return true;
}
bool InputStreamThread::bytesAvailable() const
@@ -83,68 +79,42 @@ bool InputStreamThread::bytesAvailable() const
return m_socket_p->buffer.size();
}
-//This runs inside the thread.
-void InputStreamThread::readFromInputStream()
+qint64 InputStreamThread::readData(char *data, qint64 maxSize)
{
- QAndroidJniEnvironment env;
-
- int bufLen = 1000; // Seems to magical number that also low-end products can survive.
- jbyteArray nativeArray = env->NewByteArray(bufLen);
-
+ QMutexLocker locker(&m_mutex);
- jint ret = m_socket_p->inputStream.callMethod<jint>("read", "([BII)I", nativeArray, 0, bufLen);
+ if (!m_socket_p->buffer.isEmpty())
+ return m_socket_p->buffer.read(data, maxSize);
- if (env->ExceptionCheck() || ret < 0) {
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
- env->DeleteLocalRef(nativeArray);
- QMutexLocker lock(&m_mutex);
- m_stop = true;
+ return 0;
+}
- /*
- * We cannot distinguish IOException due to valid closure or due to other error
- * Therefore we always have to throw an error and a disconnect signal
- * A genuine disconnect wouldn't need the error signal.
- * For now we always signal error which implicitly emits disconnect() too.
- */
+//inside the java thread
+void InputStreamThread::javaThreadErrorOccurred(int errorCode)
+{
+ QMutexLocker lock(&m_mutex);
- emit error();
- return;
- }
+ if (!expectClosure)
+ emit error(errorCode);
+ else
+ emit error(-1); //magic error, -1 means error was expected due to expected close()
+}
- if (ret == 0) {
- qDebug() << "Nothing to read";
- env->DeleteLocalRef(nativeArray);
- return;
- }
+//inside the java thread
+void InputStreamThread::javaReadyRead(jbyteArray buffer, int bufferLength)
+{
+ QAndroidJniEnvironment env;
QMutexLocker lock(&m_mutex);
- char *writePtr = m_socket_p->buffer.reserve(bufLen);
- env->GetByteArrayRegion(nativeArray, 0, ret, reinterpret_cast<jbyte*>(writePtr));
- env->DeleteLocalRef(nativeArray);
- m_socket_p->buffer.chop(bufLen - ret);
+ char *writePtr = m_socket_p->buffer.reserve(bufferLength);
+ env->GetByteArrayRegion(buffer, 0, bufferLength, reinterpret_cast<jbyte*>(writePtr));
emit dataAvailable();
}
-void InputStreamThread::stop()
-{
- QMutexLocker locker(&m_mutex);
- m_stop = true;
-}
-
-qint64 InputStreamThread::readData(char *data, qint64 maxSize)
+void InputStreamThread::prepareForClosure()
{
- QMutexLocker locker(&m_mutex);
-
- if (m_stop)
- return -1;
-
- if (!m_socket_p->buffer.isEmpty())
- return m_socket_p->buffer.read(data, maxSize);
-
- return 0;
+ QMutexLocker lock(&m_mutex);
+ expectClosure = true;
}
QT_END_NAMESPACE
diff --git a/src/bluetooth/android/inputstreamthread_p.h b/src/bluetooth/android/inputstreamthread_p.h
index 85852534..8b565cff 100644
--- a/src/bluetooth/android/inputstreamthread_p.h
+++ b/src/bluetooth/android/inputstreamthread_p.h
@@ -43,34 +43,39 @@
#ifndef INPUTSTREAMTHREAD_H
#define INPUTSTREAMTHREAD_H
-#include <QtCore/QThread>
+#include <QtCore/QObject>
#include <QtCore/QMutex>
+#include <QtAndroidExtras/QAndroidJniObject>
+#include <jni.h>
QT_BEGIN_NAMESPACE
class QBluetoothSocketPrivate;
-class InputStreamThread : public QThread
+class InputStreamThread : public QObject
{
Q_OBJECT
public:
explicit InputStreamThread(QBluetoothSocketPrivate *socket_p);
- virtual void run();
bool bytesAvailable() const;
- void stop();
+ bool run();
qint64 readData(char *data, qint64 maxSize);
+ void javaThreadErrorOccurred(int errorCode);
+ void javaReadyRead(jbyteArray buffer, int bufferLength);
+
+ void prepareForClosure();
+
signals:
void dataAvailable();
- void error();
+ void error(int errorCode);
private:
- void readFromInputStream();
-
QBluetoothSocketPrivate *m_socket_p;
+ QAndroidJniObject javaInputStreamThread;
mutable QMutex m_mutex;
- bool m_stop;
+ bool expectClosure;
};
QT_END_NAMESPACE
diff --git a/src/bluetooth/android/jni_android.cpp b/src/bluetooth/android/jni_android.cpp
index eb1fc2dd..ebc46a7c 100644
--- a/src/bluetooth/android/jni_android.cpp
+++ b/src/bluetooth/android/jni_android.cpp
@@ -44,20 +44,171 @@
#include <android/log.h>
#include <QtCore/QLoggingCategory>
#include <QtBluetooth/qbluetoothglobal.h>
-#include <QtAndroidExtras/QAndroidJniObject>
+#include "android/jni_android_p.h"
#include "android/androidbroadcastreceiver_p.h"
+#include "android/serveracceptancethread_p.h"
+#include "android/inputstreamthread_p.h"
Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
+typedef QHash<QByteArray, QAndroidJniObject> JCachedStringFields;
+Q_GLOBAL_STATIC(JCachedStringFields, cachedStringFields)
+
+//Java class names
+static const char * const javaBluetoothAdapterClassName = "android/bluetooth/BluetoothAdapter";
+static const char * const javaBluetoothDeviceClassName = "android/bluetooth/BluetoothDevice" ;
+
+//Java field names
+static const char * const javaActionAclConnected = "ACTION_ACL_CONNECTED";
+static const char * const javaActionAclDisconnected = "ACTION_ACL_DISCONNECTED";
+static const char * const javaActionBondStateChanged = "ACTION_BOND_STATE_CHANGED";
+static const char * const javaActionDiscoveryStarted = "ACTION_DISCOVERY_STARTED";
+static const char * const javaActionDiscoveryFinished = "ACTION_DISCOVERY_FINISHED";
+static const char * const javaActionFound = "ACTION_FOUND";
+static const char * const javaActionPairingRequest = "ACTION_PAIRING_REQUEST";
+static const char * const javaActionScanModeChanged = "ACTION_SCAN_MODE_CHANGED";
+static const char * const javaActionUuid = "ACTION_UUID";
+static const char * const javaExtraBondState = "EXTRA_BOND_STATE";
+static const char * const javaExtraDevice = "EXTRA_DEVICE";
+static const char * const javaExtraPairingKey = "EXTRA_PAIRING_KEY";
+static const char * const javaExtraPairingVariant = "EXTRA_PAIRING_VARIANT";
+static const char * const javaExtraRssi = "EXTRA_RSSI";
+static const char * const javaExtraScanMode = "EXTRA_SCAN_MODE";
+static const char * const javaExtraUuid = "EXTRA_UUID";
+
+/*
+ * This function operates on the assumption that each
+ * field is of type java/lang/String.
+ */
+QAndroidJniObject valueForStaticField(JavaNames javaName, JavaNames javaFieldName)
+{
+ //construct key
+ //the switch statements are used to reduce the number of duplicated strings
+ //in the library
+
+ const char* className;
+ switch (javaName) {
+ case JavaNames::BluetoothAdapter:
+ className = javaBluetoothAdapterClassName; break;
+ case JavaNames::BluetoothDevice:
+ className = javaBluetoothDeviceClassName; break;
+ default:
+ qWarning(QT_BT_ANDROID) << "Unknown java class name passed to valueForStaticField():" << javaName;
+ return QAndroidJniObject();
+ }
+
+ const char *fieldName;
+ switch (javaFieldName) {
+ case JavaNames::ActionAclConnected:
+ fieldName = javaActionAclConnected; break;
+ case JavaNames::ActionAclDisconnected:
+ fieldName = javaActionAclDisconnected; break;
+ case JavaNames::ActionBondStateChanged:
+ fieldName = javaActionBondStateChanged; break;
+ case JavaNames::ActionDiscoveryStarted:
+ fieldName = javaActionDiscoveryStarted; break;
+ case JavaNames::ActionDiscoveryFinished:
+ fieldName = javaActionDiscoveryFinished; break;
+ case JavaNames::ActionFound:
+ fieldName = javaActionFound; break;
+ case JavaNames::ActionPairingRequest:
+ fieldName = javaActionPairingRequest; break;
+ case JavaNames::ActionScanModeChanged:
+ fieldName = javaActionScanModeChanged; break;
+ case JavaNames::ActionUuid:
+ fieldName = javaActionUuid; break;
+ case JavaNames::ExtraBondState:
+ fieldName = javaExtraBondState; break;
+ case JavaNames::ExtraDevice:
+ fieldName = javaExtraDevice; break;
+ case JavaNames::ExtraPairingKey:
+ fieldName = javaExtraPairingKey; break;
+ case JavaNames::ExtraPairingVariant:
+ fieldName = javaExtraPairingVariant; break;
+ case JavaNames::ExtraRssi:
+ fieldName = javaExtraRssi; break;
+ case JavaNames::ExtraScanMode:
+ fieldName = javaExtraScanMode; break;
+ case JavaNames::ExtraUuid:
+ fieldName = javaExtraUuid; break;
+ default:
+ qWarning(QT_BT_ANDROID) << "Unknown java field name passed to valueForStaticField():" << javaFieldName;
+ return QAndroidJniObject();
+ }
+
+ int offset_class = qstrlen(className);
+ int offset_field = qstrlen(fieldName);
+ QByteArray key(offset_class + offset_field, Qt::Uninitialized);
+ memcpy(key.data(), className, offset_class);
+ memcpy(key.data()+offset_class, fieldName, offset_field);
+
+ JCachedStringFields::iterator it = cachedStringFields()->find(key);
+ if (it == cachedStringFields()->end()) {
+ QAndroidJniEnvironment env;
+ QAndroidJniObject fieldValue = QAndroidJniObject::getStaticObjectField(
+ className, fieldName, "Ljava/lang/String;");
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ cachedStringFields()->insert(key, QAndroidJniObject());
+ return QAndroidJniObject();
+ }
+
+ cachedStringFields()->insert(key, fieldValue);
+ return fieldValue;
+ } else {
+ return it.value();
+ }
+}
+
void QtBroadcastReceiver_jniOnReceive(JNIEnv *env, jobject /*javaObject*/,
jlong qtObject, jobject context, jobject intent)
{
reinterpret_cast<AndroidBroadcastReceiver*>(qtObject)->onReceive(env, context, intent);
}
+static void QtBluetoothSocketServer_errorOccurred(JNIEnv */*env*/, jobject /*javaObject*/,
+ jlong qtObject, jint errorCode)
+{
+ reinterpret_cast<ServerAcceptanceThread*>(qtObject)->javaThreadErrorOccurred(errorCode);
+}
+
+static void QtBluetoothSocketServer_newSocket(JNIEnv */*env*/, jobject /*javaObject*/,
+ jlong qtObject, jobject socket)
+{
+ reinterpret_cast<ServerAcceptanceThread*>(qtObject)->javaNewSocket(socket);
+}
+
+static void QtBluetoothInputStreamThread_errorOccurred(JNIEnv */*env*/, jobject /*javaObject*/,
+ jlong qtObject, jint errorCode)
+{
+ reinterpret_cast<InputStreamThread*>(qtObject)->javaThreadErrorOccurred(errorCode);
+}
+
+static void QtBluetoothInputStreamThread_readyData(JNIEnv */*env*/, jobject /*javaObject*/,
+ jlong qtObject, jbyteArray buffer, jint bufferLength)
+{
+ reinterpret_cast<InputStreamThread*>(qtObject)->javaReadyRead(buffer, bufferLength);
+}
+
+
static JNINativeMethod methods[] = {
{"jniOnReceive", "(JLandroid/content/Context;Landroid/content/Intent;)V",
- (void *) QtBroadcastReceiver_jniOnReceive},
+ (void *) QtBroadcastReceiver_jniOnReceive},
+};
+
+static JNINativeMethod methods_server[] = {
+ {"errorOccurred", "(JI)V",
+ (void *) QtBluetoothSocketServer_errorOccurred},
+ {"newSocket", "(JLandroid/bluetooth/BluetoothSocket;)V",
+ (void *) QtBluetoothSocketServer_newSocket},
+};
+
+static JNINativeMethod methods_inputStream[] = {
+ {"errorOccurred", "(JI)V",
+ (void *) QtBluetoothInputStreamThread_errorOccurred},
+ {"readyData", "(J[BI)V",
+ (void *) QtBluetoothInputStreamThread_readyData},
};
static const char logTag[] = "QtBluetooth";
@@ -75,8 +226,22 @@ static bool registerNatives(JNIEnv *env)
jclass clazz;
FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/bluetooth/QtBluetoothBroadcastReceiver");
+
if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
- __android_log_print(ANDROID_LOG_FATAL, logTag, "RegisterNatives failed");
+ __android_log_print(ANDROID_LOG_FATAL, logTag, "RegisterNatives for BraodcastReceiver failed");
+ return false;
+ }
+
+ FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/bluetooth/QtBluetoothSocketServer");
+ if (env->RegisterNatives(clazz, methods_server, sizeof(methods_server) / sizeof(methods_server[0])) < 0) {
+ __android_log_print(ANDROID_LOG_FATAL, logTag, "RegisterNatives for SocketServer failed");
+ return false;
+ }
+
+ FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/bluetooth/QtBluetoothInputStreamThread");
+ if (env->RegisterNatives(clazz, methods_inputStream,
+ sizeof(methods_inputStream) / sizeof(methods_inputStream[0])) < 0) {
+ __android_log_print(ANDROID_LOG_FATAL, logTag, "RegisterNatives for InputStreamThread failed");
return false;
}
diff --git a/src/bluetooth/android/jni_android_p.h b/src/bluetooth/android/jni_android_p.h
new file mode 100644
index 00000000..9cddd2f9
--- /dev/null
+++ b/src/bluetooth/android/jni_android_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JNI_ANDROID_P_H
+#define JNI_ANDROID_P_H
+
+#include <QtAndroidExtras/QAndroidJniEnvironment>
+#include <QtAndroidExtras/QAndroidJniObject>
+
+QT_BEGIN_NAMESPACE
+
+enum JavaNames {
+ BluetoothAdapter = 0,
+ BluetoothDevice,
+ ActionAclConnected,
+ ActionAclDisconnected,
+ ActionBondStateChanged,
+ ActionDiscoveryStarted,
+ ActionDiscoveryFinished,
+ ActionFound,
+ ActionPairingRequest,
+ ActionScanModeChanged,
+ ActionUuid,
+ ExtraBondState,
+ ExtraDevice,
+ ExtraPairingKey,
+ ExtraPairingVariant,
+ ExtraRssi,
+ ExtraScanMode,
+ ExtraUuid
+};
+
+QAndroidJniObject valueForStaticField(JavaNames javaName, JavaNames javaFieldName);
+
+QT_END_NAMESPACE
+
+#endif // JNI_ANDROID_P_H
diff --git a/src/bluetooth/android/localdevicebroadcastreceiver.cpp b/src/bluetooth/android/localdevicebroadcastreceiver.cpp
index 0e81ef22..5b7e4a38 100644
--- a/src/bluetooth/android/localdevicebroadcastreceiver.cpp
+++ b/src/bluetooth/android/localdevicebroadcastreceiver.cpp
@@ -40,21 +40,51 @@
****************************************************************************/
#include <QtCore/QLoggingCategory>
+#include <QtCore/private/qjnihelpers_p.h>
#include "localdevicebroadcastreceiver_p.h"
+#include "android/jni_android_p.h"
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
+const char *scanModes[] = {"SCAN_MODE_NONE", "SCAN_MODE_CONNECTABLE", "SCAN_MODE_CONNECTABLE_DISCOVERABLE"};
+const char *bondModes[] = {"BOND_NONE", "BOND_BONDING", "BOND_BONDED"};
+
LocalDeviceBroadcastReceiver::LocalDeviceBroadcastReceiver(QObject *parent) :
AndroidBroadcastReceiver(parent), previousScanMode(0)
{
- addAction(QStringLiteral("android.bluetooth.device.action.BOND_STATE_CHANGED"));
- addAction(QStringLiteral("android.bluetooth.adapter.action.SCAN_MODE_CHANGED"));
- addAction(QStringLiteral("android.bluetooth.device.action.ACL_CONNECTED"));
- addAction(QStringLiteral("android.bluetooth.device.action.ACL_DISCONNECTED"));
- addAction(QStringLiteral("android.bluetooth.device.action.PAIRING_REQUEST")); //API 19
+ addAction(valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionBondStateChanged));
+ addAction(valueForStaticField(JavaNames::BluetoothAdapter, JavaNames::ActionScanModeChanged));
+ addAction(valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionAclConnected));
+ addAction(valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionAclDisconnected));
+ if (QtAndroidPrivate::androidSdkVersion() >= 19)
+ addAction(valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionPairingRequest)); //API 19
+
+ //cache integer values for host & bonding mode
+ //don't use the java fields directly but refer to them by name
+ QAndroidJniEnvironment env;
+ for (uint i = 0; i < (sizeof(hostModePreset)/sizeof(hostModePreset[0])); i++) {
+ hostModePreset[i] = QAndroidJniObject::getStaticField<jint>(
+ "android/bluetooth/BluetoothAdapter",
+ scanModes[i]);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ hostModePreset[i] = 0;
+ }
+ }
+ for (uint i = 0; i < (sizeof(bondingModePreset)/sizeof(bondingModePreset[0])); i++) {
+ bondingModePreset[i] = QAndroidJniObject::getStaticField<jint>(
+ "android/bluetooth/BluetoothDevice",
+ bondModes[i]);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ bondingModePreset[i] = 0;
+ }
+ }
}
void LocalDeviceBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobject intent)
@@ -66,11 +96,13 @@ void LocalDeviceBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobje
const QString action = intentObject.callObjectMethod("getAction", "()Ljava/lang/String;").toString();
qCDebug(QT_BT_ANDROID) << QStringLiteral("LocalDeviceBroadcastReceiver::onReceive() - event: %1").arg(action);
- if (action == QStringLiteral("android.bluetooth.adapter.action.SCAN_MODE_CHANGED")) {
- QAndroidJniObject extrasBundle =
+ if (action == valueForStaticField(JavaNames::BluetoothAdapter,
+ JavaNames::ActionScanModeChanged).toString()) {
+
+ const QAndroidJniObject extrasBundle =
intentObject.callObjectMethod("getExtras","()Landroid/os/Bundle;");
- QAndroidJniObject keyExtra = QAndroidJniObject::fromString(
- QStringLiteral("android.bluetooth.adapter.extra.SCAN_MODE"));
+ const QAndroidJniObject keyExtra = valueForStaticField(JavaNames::BluetoothAdapter,
+ JavaNames::ExtraScanMode);
int extra = extrasBundle.callMethod<jint>("getInt",
"(Ljava/lang/String;)I",
@@ -79,34 +111,28 @@ void LocalDeviceBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobje
if (previousScanMode != extra) {
previousScanMode = extra;
- switch (extra) {
- case 20: //BluetoothAdapter.SCAN_MODE_NONE
- emit hostModeStateChanged(QBluetoothLocalDevice::HostPoweredOff);
- break;
- case 21: //BluetoothAdapter.SCAN_MODE_CONNECTABLE
- emit hostModeStateChanged(QBluetoothLocalDevice::HostConnectable);
- break;
- case 23: //BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE
- emit hostModeStateChanged(QBluetoothLocalDevice::HostDiscoverable);
- break;
- default:
- qCWarning(QT_BT_ANDROID) << "Unknown Host State";
- break;
- }
+ 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 == QStringLiteral("android.bluetooth.device.action.BOND_STATE_CHANGED")) {
+ } else if (action == valueForStaticField(JavaNames::BluetoothDevice,
+ JavaNames::ActionBondStateChanged).toString()) {
//get BluetoothDevice
- QAndroidJniObject keyExtra = QAndroidJniObject::fromString(
- QStringLiteral("android.bluetooth.device.extra.DEVICE"));
- QAndroidJniObject 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 = QAndroidJniObject::fromString(
- QStringLiteral("android.bluetooth.device.extra.BOND_STATE"));
- QAndroidJniObject extrasBundle =
+ 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",
@@ -116,29 +142,28 @@ void LocalDeviceBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobje
if (address.isNull())
return;
- switch (bondState) {
- case 10: //BluetoothDevice.BOND_NONE
+ if (bondState == bondingModePreset[0])
emit pairingStateChanged(address, QBluetoothLocalDevice::Unpaired);
- break;
- case 11: //BluetoothDevice.BOND_BONDING
- //we ignore this as Qt doesn't have equivalent API.
- break;
- case 12: //BluetoothDevice.BOND_BONDED
+ 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);
- break;
- default:
+ else
qCWarning(QT_BT_ANDROID) << "Unknown BOND_STATE_CHANGED value:" << bondState;
- break;
- }
- } else if (action == QStringLiteral("android.bluetooth.device.action.ACL_DISCONNECTED") ||
- action == QStringLiteral("android.bluetooth.device.action.ACL_CONNECTED")) {
+ } 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 == QStringLiteral("android.bluetooth.device.action.ACL_CONNECTED") ? true : false;
+ action == connectEvent ? true : false;
//get BluetoothDevice
- QAndroidJniObject keyExtra = QAndroidJniObject::fromString(
- QStringLiteral("android.bluetooth.device.extra.DEVICE"));
+ const QAndroidJniObject keyExtra = valueForStaticField(JavaNames::BluetoothDevice,
+ JavaNames::ExtraDevice);
QAndroidJniObject bluetoothDevice =
intentObject.callObjectMethod("getParcelableExtra",
"(Ljava/lang/String;)Landroid/os/Parcelable;",
@@ -149,10 +174,11 @@ void LocalDeviceBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobje
return;
emit connectDeviceChanges(address, isConnectEvent);
- } else if (action == QStringLiteral("android.bluetooth.device.action.PAIRING_REQUEST")) {
+ } else if (action == valueForStaticField(JavaNames::BluetoothDevice,
+ JavaNames::ActionPairingRequest).toString()) {
- QAndroidJniObject keyExtra = QAndroidJniObject::fromString(
- QStringLiteral("android.bluetooth.device.extra.PAIRING_VARIANT"));
+ QAndroidJniObject keyExtra = valueForStaticField(JavaNames::BluetoothDevice,
+ JavaNames::ExtraPairingVariant);
int variant = intentObject.callMethod<jint>("getIntExtra",
"(Ljava/lang/String;I)I",
keyExtra.object<jstring>(),
@@ -164,8 +190,8 @@ void LocalDeviceBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobje
return;
case 2: //BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION
{
- keyExtra = QAndroidJniObject::fromString(
- QStringLiteral("android.bluetooth.device.extra.PAIRING_KEY"));
+ keyExtra = valueForStaticField(JavaNames::BluetoothDevice,
+ JavaNames::ExtraPairingKey);
key = intentObject.callMethod<jint>("getIntExtra",
"(Ljava/lang/String;I)I",
keyExtra.object<jstring>(),
@@ -173,8 +199,7 @@ void LocalDeviceBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobje
if (key == -1)
return;
- keyExtra = QAndroidJniObject::fromString(
- QStringLiteral("android.bluetooth.device.extra.DEVICE"));
+ keyExtra = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ExtraDevice);
QAndroidJniObject bluetoothDevice =
intentObject.callObjectMethod("getParcelableExtra",
"(Ljava/lang/String;)Landroid/os/Parcelable;",
diff --git a/src/bluetooth/android/localdevicebroadcastreceiver_p.h b/src/bluetooth/android/localdevicebroadcastreceiver_p.h
index ddd65d92..4059b3bb 100644
--- a/src/bluetooth/android/localdevicebroadcastreceiver_p.h
+++ b/src/bluetooth/android/localdevicebroadcastreceiver_p.h
@@ -65,6 +65,9 @@ signals:
private:
int previousScanMode;
QAndroidJniObject pairingDevice;
+
+ int bondingModePreset[3];
+ int hostModePreset[3];
};
QT_END_NAMESPACE
diff --git a/src/bluetooth/android/serveracceptancethread.cpp b/src/bluetooth/android/serveracceptancethread.cpp
index 88a92478..d46fff7c 100644
--- a/src/bluetooth/android/serveracceptancethread.cpp
+++ b/src/bluetooth/android/serveracceptancethread.cpp
@@ -47,11 +47,9 @@
Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
ServerAcceptanceThread::ServerAcceptanceThread(QObject *parent) :
- QThread(parent), m_stop(false), maxPendingConnections(1)
+ QObject(parent), maxPendingConnections(1)
{
- btAdapter = QAndroidJniObject::callStaticObjectMethod("android/bluetooth/BluetoothAdapter",
- "getDefaultAdapter",
- "()Landroid/bluetooth/BluetoothAdapter;");
+ qRegisterMetaType<QBluetoothServer::Error>("QBluetoothServer::Error");
}
ServerAcceptanceThread::~ServerAcceptanceThread()
@@ -71,161 +69,121 @@ void ServerAcceptanceThread::setServiceDetails(const QBluetoothUuid &uuid,
secFlags = securityFlags;
}
+bool ServerAcceptanceThread::hasPendingConnections() const
+{
+ QMutexLocker lock(&m_mutex);
+ return (pendingSockets.count() > 0);
+}
+
+/*
+ * Returns the next pending connection or an invalid JNI object.
+ * Note that even a stopped thread may still have pending
+ * connections. Pending connections are only terminated upon
+ * thread restart or destruction.
+ */
+QAndroidJniObject ServerAcceptanceThread::nextPendingConnection()
+{
+ QMutexLocker lock(&m_mutex);
+ if (pendingSockets.isEmpty())
+ return QAndroidJniObject();
+ else
+ return pendingSockets.takeFirst();
+}
+
+void ServerAcceptanceThread::setMaxPendingConnections(int maximumCount)
+{
+ QMutexLocker lock(&m_mutex);
+ maxPendingConnections = maximumCount;
+}
+
void ServerAcceptanceThread::run()
{
- m_mutex.lock();
+ QMutexLocker lock(&m_mutex);
- qCDebug(QT_BT_ANDROID) << "Starting ServerSocketAccept thread";
if (!validSetup()) {
qCWarning(QT_BT_ANDROID) << "Invalid Server Socket setup";
- m_mutex.unlock();
return;
}
- shutdownPendingConnections();
-
- m_stop = false;
-
- QString tempUuid = m_uuid.toString();
- tempUuid.chop(1); //remove trailing '}'
- tempUuid.remove(0,1); //remove first '{'
-
- QAndroidJniEnvironment env;
- QAndroidJniObject inputString = QAndroidJniObject::fromString(tempUuid);
- QAndroidJniObject uuidObject = QAndroidJniObject::callStaticObjectMethod(
- "java/util/UUID", "fromString",
- "(Ljava/lang/String;)Ljava/util/UUID;",
- inputString.object<jstring>());
- inputString = QAndroidJniObject::fromString(m_serviceName);
- if (((int)secFlags) == 0) { //no form of security flag set
- qCDebug(QT_BT_ANDROID) << "InSecure listening";
- btServerSocket = btAdapter.callObjectMethod("listenUsingInsecureRfcommWithServiceRecord",
- "(Ljava/lang/String;Ljava/util/UUID;)Landroid/bluetooth/BluetoothServerSocket;",
- inputString.object<jstring>(),
- uuidObject.object<jobject>());
- } else {
- qCDebug(QT_BT_ANDROID) << "Secure listening";
- btServerSocket = btAdapter.callObjectMethod("listenUsingRfcommWithServiceRecord",
- "(Ljava/lang/String;Ljava/util/UUID;)Landroid/bluetooth/BluetoothServerSocket;",
- inputString.object<jstring>(),
- uuidObject.object<jobject>());
- }
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- qCWarning(QT_BT_ANDROID) << "Cannot setup rfcomm socket listener";
- m_mutex.unlock();
- return;
+ if (isRunning()) {
+ stop();
+ shutdownPendingConnections();
}
- if (!btServerSocket.isValid()) {
- qCWarning(QT_BT_ANDROID) << "Invalid BluetoothServerSocket";
- m_mutex.unlock();
+ javaThread = QAndroidJniObject("org/qtproject/qt5/android/bluetooth/QtBluetoothSocketServer");
+ if (!javaThread.isValid())
return;
- }
-
- while (!m_stop) {
- m_mutex.unlock();
-
- qCDebug(QT_BT_ANDROID) << "Waiting for new incoming socket";
- QAndroidJniEnvironment env;
-
- //this call blocks until we see an incoming connection
- QAndroidJniObject socket = btServerSocket.callObjectMethod("accept",
- "()Landroid/bluetooth/BluetoothSocket;");
- qCDebug(QT_BT_ANDROID) << "New socket accepted: ->" << socket.isValid();
- bool exceptionOccurred = false;
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- exceptionOccurred = true;
- }
+ javaThread.setField<jlong>("qtObject", reinterpret_cast<long>(this));
+ javaThread.setField<jboolean>("logEnabled", QT_BT_ANDROID().isDebugEnabled());
- m_mutex.lock();
-
- if (exceptionOccurred || m_stop) {
- //if m_stop is true there is nothing really to be done but exit
- m_stop = true;
- } else if (socket.isValid()){
- if (pendingSockets.count() < maxPendingConnections) {
- pendingSockets.append(socket);
- emit newConnection();
- } else {
- qCWarning(QT_BT_ANDROID) << "Refusing connection due to limited pending socket queue";
- socket.callMethod<void>("close");
- if (env->ExceptionCheck()) {
- qCWarning(QT_BT_ANDROID) << "Error during refusal of new socket";
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
-
-
- }
- } else {
- //should never happen as invalid socket should cause exception
- qCWarning(QT_BT_ANDROID) << "Invalid state during server socket accept";
- }
- }
+ QString tempUuid = m_uuid.toString();
+ tempUuid.chop(1); //remove trailing '}'
+ tempUuid.remove(0,1); //remove first '{'
- m_uuid = QBluetoothUuid();
- m_serviceName = QString();
- btServerSocket = QAndroidJniObject();
- m_mutex.unlock();
+ QAndroidJniObject uuidString = QAndroidJniObject::fromString(tempUuid);
+ QAndroidJniObject serviceNameString = QAndroidJniObject::fromString(m_serviceName);
+ bool isSecure = !(secFlags == QBluetooth::NoSecurity);
+ javaThread.callMethod<void>("setServiceDetails", "(Ljava/lang/String;Ljava/lang/String;Z)V",
+ uuidString.object<jstring>(),
+ serviceNameString.object<jstring>(),
+ isSecure);
+ javaThread.callMethod<void>("start");
}
void ServerAcceptanceThread::stop()
{
- QMutexLocker lock(&m_mutex);
- m_stop = true;
-
- QAndroidJniEnvironment env;
- if (btServerSocket.isValid()) {
+ if (javaThread.isValid()) {
qCDebug(QT_BT_ANDROID) << "Closing server socket";
- btServerSocket.callMethod<void>("close");
- if (env->ExceptionCheck()) {
- qCWarning(QT_BT_ANDROID) << "Exception during closure of server socket";
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
- qCDebug(QT_BT_ANDROID) << "Closing server socket111";
+ javaThread.callMethod<void>("close");
}
}
-bool ServerAcceptanceThread::hasPendingConnections() const
+bool ServerAcceptanceThread::isRunning() const
{
- QMutexLocker lock(&m_mutex);
- return (pendingSockets.count() > 0);
+ if (javaThread.isValid())
+ return javaThread.callMethod<jboolean>("isAlive");
+
+ return false;
}
-/*
- * Returns the next pending connection or an invalid JNI object.
- * Note that even a stopped thread may still have pending
- * connections. Pending connections are only terminated upon
- * thread restart or destruction.
- */
-QAndroidJniObject ServerAcceptanceThread::nextPendingConnection()
+//Runs inside the java thread
+void ServerAcceptanceThread::javaThreadErrorOccurred(int errorCode)
{
- QMutexLocker lock(&m_mutex);
- if (pendingSockets.isEmpty())
- return QAndroidJniObject();
- else
- return pendingSockets.takeFirst();
+ qCDebug(QT_BT_ANDROID) << "JavaThread error:" << errorCode;
+ emit error(QBluetoothServer::InputOutputError);
}
-void ServerAcceptanceThread::setMaxPendingConnections(int maximumCount)
+//Runs inside the Java thread
+void ServerAcceptanceThread::javaNewSocket(jobject s)
{
QMutexLocker lock(&m_mutex);
- maxPendingConnections = maximumCount;
+
+ QAndroidJniObject socket(s);
+ if (!socket.isValid())
+ return;
+
+ if (pendingSockets.count() < maxPendingConnections) {
+ qCDebug(QT_BT_ANDROID) << "New incoming java socket detected";
+ pendingSockets.append(socket);
+ emit newConnection();
+ } else {
+ QAndroidJniEnvironment env;
+ qCWarning(QT_BT_ANDROID) << "Refusing connection due to limited pending socket queue";
+ socket.callMethod<void>("close");
+ if (env->ExceptionCheck()) {
+ qCWarning(QT_BT_ANDROID) << "Error during refusal of new socket";
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+ }
}
-//must be run inside the lock but doesn't lock by itself
bool ServerAcceptanceThread::validSetup() const
{
return (!m_uuid.isNull() && !m_serviceName.isEmpty());
}
-//must be run inside the lock but doesn't lock by itself
void ServerAcceptanceThread::shutdownPendingConnections()
{
while (!pendingSockets.isEmpty()) {
diff --git a/src/bluetooth/android/serveracceptancethread_p.h b/src/bluetooth/android/serveracceptancethread_p.h
index 1297e48f..18142d64 100644
--- a/src/bluetooth/android/serveracceptancethread_p.h
+++ b/src/bluetooth/android/serveracceptancethread_p.h
@@ -43,50 +43,50 @@
#define SERVERACCEPTANCETHREAD_H
#include <QtCore/QMutex>
-#include <QtCore/QThread>
#include <QtAndroidExtras/QAndroidJniObject>
+#include <QtBluetooth/QBluetoothServer>
#include <QtBluetooth/QBluetoothUuid>
#include "qbluetooth.h"
-class ServerAcceptanceThread : public QThread
+class ServerAcceptanceThread : public QObject
{
Q_OBJECT
public:
- enum AndroidError {
- AndroidNoError
- };
-
explicit ServerAcceptanceThread(QObject *parent = 0);
~ServerAcceptanceThread();
void setServiceDetails(const QBluetoothUuid &uuid, const QString &serviceName,
QBluetooth::SecurityFlags securityFlags);
- virtual void run();
- void stop();
+
bool hasPendingConnections() const;
QAndroidJniObject nextPendingConnection();
void setMaxPendingConnections(int maximumCount);
+ void javaThreadErrorOccurred(int errorCode);
+ void javaNewSocket(jobject socket);
+
+ void run();
+ void stop();
+ bool isRunning() const;
+
signals:
void newConnection();
- void error(ServerAcceptanceThread::AndroidError);
+ void error(QBluetoothServer::Error);
private:
bool validSetup() const;
void shutdownPendingConnections();
QList<QAndroidJniObject> pendingSockets;
- QAndroidJniObject btAdapter;
- QAndroidJniObject btServerSocket;
mutable QMutex m_mutex;
QString m_serviceName;
QBluetoothUuid m_uuid;
- bool m_stop;
- AndroidError lastError;
int maxPendingConnections;
QBluetooth::SecurityFlags secFlags;
+ QAndroidJniObject javaThread;
+
};
#endif // SERVERACCEPTANCETHREAD_H
diff --git a/src/bluetooth/android/servicediscoverybroadcastreceiver.cpp b/src/bluetooth/android/servicediscoverybroadcastreceiver.cpp
index 341617bc..0a3f97f9 100644
--- a/src/bluetooth/android/servicediscoverybroadcastreceiver.cpp
+++ b/src/bluetooth/android/servicediscoverybroadcastreceiver.cpp
@@ -41,9 +41,11 @@
#include "android/servicediscoverybroadcastreceiver_p.h"
#include <QtCore/QLoggingCategory>
+#include <QtCore/private/qjnihelpers_p.h>
#include <QtAndroidExtras/QAndroidJniEnvironment>
#include <QtBluetooth/QBluetoothAddress>
#include <QtBluetooth/QBluetoothDeviceInfo>
+#include "android/jni_android_p.h"
QT_BEGIN_NAMESPACE
@@ -51,7 +53,8 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
ServiceDiscoveryBroadcastReceiver::ServiceDiscoveryBroadcastReceiver(QObject* parent): AndroidBroadcastReceiver(parent)
{
- addAction(QStringLiteral("android.bluetooth.device.action.UUID"));
+ if (QtAndroidPrivate::androidSdkVersion() >= 15)
+ addAction(valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionUuid)); //API 15+
}
void ServiceDiscoveryBroadcastReceiver::onReceive(JNIEnv *env, jobject context, jobject intent)
@@ -64,19 +67,20 @@ void ServiceDiscoveryBroadcastReceiver::onReceive(JNIEnv *env, jobject context,
qCDebug(QT_BT_ANDROID) << "ServiceDiscoveryBroadcastReceiver::onReceive() - event:" << action;
- if (action == QStringLiteral("android.bluetooth.device.action.UUID")) {
- QAndroidJniObject keyExtra = QAndroidJniObject::fromString(
- QStringLiteral("android.bluetooth.device.extra.UUID"));
+ if (action == valueForStaticField(JavaNames::BluetoothDevice,
+ JavaNames::ActionUuid).toString()) {
+
+ QAndroidJniObject keyExtra = valueForStaticField(JavaNames::BluetoothDevice,
+ JavaNames::ExtraUuid);
QAndroidJniObject parcelableUuids = intentObject.callObjectMethod(
"getParcelableArrayExtra",
"(Ljava/lang/String;)[Landroid/os/Parcelable;",
keyExtra.object<jstring>());
if (!parcelableUuids.isValid())
return;
- QList<QBluetoothUuid> result = ServiceDiscoveryBroadcastReceiver::convertParcelableArray(parcelableUuids);
+ const QList<QBluetoothUuid> result = ServiceDiscoveryBroadcastReceiver::convertParcelableArray(parcelableUuids);
- keyExtra = QAndroidJniObject::fromString(
- QStringLiteral("android.bluetooth.device.extra.DEVICE"));
+ keyExtra = valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ExtraDevice);
QAndroidJniObject bluetoothDevice =
intentObject.callObjectMethod("getParcelableExtra",
"(Ljava/lang/String;)Landroid/os/Parcelable;",
diff --git a/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp b/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp
index 56459e72..88520c35 100644
--- a/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp
+++ b/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -39,13 +39,36 @@
****************************************************************************/
//! [include]
-#include <qbluetoothlocaldevice.h>
+#include <QtBluetooth/QBluetoothLocalDevice>
//! [include]
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include <QtCore/QObject>
+#include <QtBluetooth/QBluetoothDeviceDiscoveryAgent>
+#include <QtBluetooth/QBluetoothTransferManager>
+#include <QtBluetooth/QBluetoothTransferRequest>
+#include <QtBluetooth/QBluetoothTransferReply>
//! [namespace]
QT_USE_NAMESPACE
//! [namespace]
+class MyClass : public QObject
+{
+ Q_OBJECT
+public:
+ MyClass() : QObject() {}
+ void localDevice();
+ void startDiscovery();
+ void objectPush();
+
+public slots:
+ void deviceDiscovered(const QBluetoothDeviceInfo &device);
+ void transferFinished(QBluetoothTransferReply* reply);
+};
+
+void MyClass::localDevice() {
//! [turningon]
QBluetoothLocalDevice localDevice;
QString localDeviceName;
@@ -60,20 +83,31 @@ if (localDevice.isValid()) {
localDeviceName = localDevice.name();
// Make it visible to others
- localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable)
+ localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable);
+
+ // Get connected devices
+ QList<QBluetoothAddress> remotes;
+ remotes = localDevice.connectedDevices();
}
//! [turningon]
+
+}
+
//! [discovery]
-// Create a discovery agent and connect to its signals
-QBluetoothDiscoveryAgent *discoveryAgent = new QBluetoothDiscoveryAgent(this);
-connect(discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
- this, SLOT(deviceDiscovered(QBluetoothDeviceInfo)));
+void MyClass::startDiscovery()
+{
-// Start a discovery
-discoveryAgent->start();
+ // 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)
@@ -82,18 +116,36 @@ void MyClass::deviceDiscovered(const QBluetoothDeviceInfo &device)
}
//! [discovery]
+void MyClass::objectPush()
+{
//! [sendfile]
// Create a transfer manager
QBluetoothTransferManager *transferManager = new QBluetoothTransferManager(this);
// Create the transfer request and file to be sent
-QBluetoothTransferRequest request(device.address());
+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);
// Connect to the reply's signals to be informed about the status and do cleanups when done
-connect(reply, SIGNAL(finished(QBluetoothTransferReply*)),
- this, SLOT(transferFinished(QBluetoothTransferReply*)));
+QObject::connect(reply, SIGNAL(finished(QBluetoothTransferReply*)),
+ this, SLOT(transferFinished(QBluetoothTransferReply*)));
//! [sendfile]
+}
+
+void MyClass::transferFinished(QBluetoothTransferReply* /*reply*/)
+{
+}
+
+int main(int argc, char** argv)
+{
+ QCoreApplication app(argc, argv);
+ MyClass cl;
+
+ return app.exec();
+}
+
+#include "doc_src_qtbluetooth.moc"
diff --git a/src/bluetooth/doc/snippets/doc_src_qtbluetooth.pro b/src/bluetooth/doc/snippets/doc_src_qtbluetooth.pro
deleted file mode 100644
index ca021b72..00000000
--- a/src/bluetooth/doc/snippets/doc_src_qtbluetooth.pro
+++ /dev/null
@@ -1,43 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** You may use this file under the terms of the BSD license as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-** of its contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#! [contacts project modification]
-QT += bluetooth
-#! [contacts project modification]
diff --git a/src/bluetooth/doc/snippets/snippets.pro b/src/bluetooth/doc/snippets/snippets.pro
new file mode 100644
index 00000000..f59983ee
--- /dev/null
+++ b/src/bluetooth/doc/snippets/snippets.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+TARGET = bluetooth_cppsnippet
+QT = core
+#! [contacts project modification]
+QT += bluetooth
+#! [contacts project modification]
+
+SOURCES += doc_src_qtbluetooth.cpp
diff --git a/src/bluetooth/doc/src/bluetooth-cpp.qdoc b/src/bluetooth/doc/src/bluetooth-cpp.qdoc
index 9bef246b..df18cc6a 100644
--- a/src/bluetooth/doc/src/bluetooth-cpp.qdoc
+++ b/src/bluetooth/doc/src/bluetooth-cpp.qdoc
@@ -42,6 +42,6 @@
To use the C++ library in your application, add the following configuration
option to your \c .pro file:
- \snippet doc_src_qtbluetooth.pro contacts project modification
+ \snippet snippets.pro contacts project modification
*/
diff --git a/src/bluetooth/doc/src/bluetooth-index.qdoc b/src/bluetooth/doc/src/bluetooth-index.qdoc
index 32f6a787..e9575db1 100644
--- a/src/bluetooth/doc/src/bluetooth-index.qdoc
+++ b/src/bluetooth/doc/src/bluetooth-index.qdoc
@@ -32,10 +32,11 @@
Bluetooth is a short-range (less than 100 meters) wireless technology. It
has a reasonably high data transfer rate of 2.1 Mbit/s, which makes it ideal
-for transferring data between devices.
+for transferring data between devices. Currently the API is supported on
+Linux (Bluez 4.x), Android and BlackBerry 10.
Bluetooth connectivity is based on basic device management, such as scanning
-for devices, gathering information about them, and exchaning data between
+for devices, gathering information about them, and exchanging data between
them.
\section1 Getting started
@@ -43,7 +44,7 @@ them.
To use the C++ library in your application, add the following configuration
option to your \c .pro file:
-\snippet doc_src_qtbluetooth.pro contacts project modification
+\snippet snippets.pro contacts project modification
To use the classes of the module in your application you need the following
import statement in your \c .qml file:
diff --git a/src/bluetooth/doc/src/bluetooth-overview.qdoc b/src/bluetooth/doc/src/bluetooth-overview.qdoc
index 4c12ecac..bc8a9543 100644
--- a/src/bluetooth/doc/src/bluetooth-overview.qdoc
+++ b/src/bluetooth/doc/src/bluetooth-overview.qdoc
@@ -39,7 +39,7 @@
\list
\li Retrieve information about the local Bluetooth device.
\li Scan for other Bluetooth devices in range and retrieve information about them.
- \li Push files to remote devices using the OBEX Object Push Profile (OPP).
+ \li Push files to remote devices using the OBEX Object Push Profile (OPP)
\li Connect to remote devices through a RFCOMM channel using the Serial Port Profile (SPP).
\li Create a RFCOMM server that allows incoming connections using SPP.
\li Retrieve specification about Bluetooth Low Energy device.
@@ -47,6 +47,8 @@
\li Receive advertisement from Bluetooth Low Energy device.
\endlist
+ Note that the Object Push Profile is not supported on Android.
+
The following sections describe how to use the Qt Bluetooth C++ API classes
for the above use cases.
@@ -54,16 +56,16 @@
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 is
- to check if Bluetooth is available on the device and read the local device address and name. The
- QBluetoothLocalDevice is the one to provide all of this information. Additionally you can use it
- to turn Bluetooth on and off and set the visibility on the device.
+ 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.
\snippet doc_src_qtbluetooth.cpp turningon
\section1 Scanning for Bluetooth Devices
Similar to the QBluetoothLocalDevice, the API offers QBluetoothDeviceInfo which provides
- that information for remote devices. Although you can just create QBluetoothDeviceInfo objects on
+ 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.
@@ -71,13 +73,13 @@
\section1 Pushing Files to Remote Devices
- Once the desired device is found, there are two main use cases provided by Qt Bluetooth. The
- simpler is to send files via the Obex Object Push Profile (OPP). As the name describes, this
+ 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 only push files from one device to another, but not pull files or browse the remote
file system. Because of this limitation, this 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 the put() function.
+ the request by calling its \l {QBluetoothTransferManager::put()}{put()} function.
\snippet doc_src_qtbluetooth.cpp sendfile
@@ -88,21 +90,21 @@
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 create SPP connections, you need to register a Server one one device by using
- QRfcommServer.
+ To be able to receive incoming SPP connections, you need to listen to incoming connections using
+ \l QBluetoothServer.
\snippet btchat/chatserver.cpp Create the server
Connect to this server from another device playing the client role by using a
- QBluetoothSocket.
+ QBluetoothSocket:
\snippet btchat/chatclient.cpp startClient
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 QRfcommServer and
- QBluetoothSocket classes. A good example to start with SPP is the \l{btchat}{Bluetooth Chat}
+ and client, please refer to the detailed description sections in the \l QBluetoothServer and
+ \l QBluetoothSocket classes. A good example to start with SPP is the \l{btchat}{Bluetooth Chat}
example.
\section1 Bluetooth Low Energy
diff --git a/src/bluetooth/doc/src/examples.qdoc b/src/bluetooth/doc/src/examples.qdoc
index 3b9ea577..08759874 100644
--- a/src/bluetooth/doc/src/examples.qdoc
+++ b/src/bluetooth/doc/src/examples.qdoc
@@ -31,7 +31,7 @@
\title Qt Bluetooth Examples
\brief Examples for the Qt Bluetooth module.
- This is a variety of examples that cover the entire range of the the Qt
+ This is a variety of examples that cover the entire range of the Qt
Bluetooth API. You will find them in their own documentation but they are also
accessible from here.
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
index c2e1792d..4f8ecdff 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
@@ -70,7 +70,10 @@ QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate()
if (m_active)
stop();
- delete receiver;
+ if (receiver) {
+ receiver->unregisterReceiver();
+ delete receiver;
+ }
}
bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const
@@ -120,8 +123,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start()
if (!receiver) {
receiver = new DeviceDiscoveryBroadcastReceiver();
qRegisterMetaType<QBluetoothDeviceInfo>("QBluetoothDeviceInfo");
- QObject::connect(receiver, SIGNAL(deviceDiscovered(const QBluetoothDeviceInfo&)),
- this, SLOT(processDiscoveredDevices(const QBluetoothDeviceInfo&)));
+ QObject::connect(receiver, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
+ this, SLOT(processDiscoveredDevices(QBluetoothDeviceInfo)));
QObject::connect(receiver, SIGNAL(finished()), this, SLOT(processDiscoveryFinished()));
}
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_qnx.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_qnx.cpp
index a20ab90b..42b6ceff 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_qnx.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_qnx.cpp
@@ -186,7 +186,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::remoteDevicesChanged(int fd)
deviceInfo.setRssi(rssi);
bool updated = false;
- //Prevent a device from beeing listed twice
+ //Prevent a device from being listed twice
for (int i=0; i < discoveredDevices.size(); i++) {
if (discoveredDevices.at(i).address() == deviceInfo.address()) {
updated = true;
diff --git a/src/bluetooth/qbluetoothhostinfo.cpp b/src/bluetooth/qbluetoothhostinfo.cpp
index 1e8dbc2e..00ce0680 100644
--- a/src/bluetooth/qbluetoothhostinfo.cpp
+++ b/src/bluetooth/qbluetoothhostinfo.cpp
@@ -82,6 +82,19 @@ QBluetoothHostInfo::~QBluetoothHostInfo()
}
/*!
+ Assigns \a other to this QBluetoothHostInfo instance.
+*/
+QBluetoothHostInfo &QBluetoothHostInfo::operator=(const QBluetoothHostInfo &other)
+{
+ Q_D(QBluetoothHostInfo);
+
+ d->m_address = other.d_func()->m_address;
+ d->m_name = other.d_func()->m_name;
+
+ return *this;
+}
+
+/*!
Returns the Bluetooth address as a QBluetoothAddress.
*/
QBluetoothAddress QBluetoothHostInfo::address() const
diff --git a/src/bluetooth/qbluetoothhostinfo.h b/src/bluetooth/qbluetoothhostinfo.h
index 24590ebb..b4428a82 100644
--- a/src/bluetooth/qbluetoothhostinfo.h
+++ b/src/bluetooth/qbluetoothhostinfo.h
@@ -55,6 +55,8 @@ public:
QBluetoothHostInfo(const QBluetoothHostInfo &other);
~QBluetoothHostInfo();
+ QBluetoothHostInfo &operator=(const QBluetoothHostInfo &other);
+
QBluetoothAddress address() const;
void setAddress(const QBluetoothAddress &address);
diff --git a/src/bluetooth/qbluetoothlocaldevice.cpp b/src/bluetooth/qbluetoothlocaldevice.cpp
index e299ab71..14140846 100644
--- a/src/bluetooth/qbluetoothlocaldevice.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice.cpp
@@ -139,9 +139,11 @@ bool QBluetoothLocalDevice::isValid() const
\fn void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode)
Sets the host mode of this local Bluetooth device to \a mode.
- NOTE: Due to security policies of platforms, this method may behave different on different platforms. For example
- the system can ask the user for confirmation before turning Bluetooth on or off. Not all host modes may be
- supported on all platforms. Please refer to the platform specific Bluetooth documentation for details.
+
+ \note Due to varying security policies on the supported platforms, this method may have
+ differing behaviors on the various platforms. For example the system may ask the user for
+ confirmation before turning Bluetooth on or off and not all host modes may be supported.
+ Please refer to the platform specific Bluetooth documentation for details.
*/
/*!
@@ -172,8 +174,10 @@ bool QBluetoothLocalDevice::isValid() const
\fn QBluetoothLocalDevice::powerOn()
Powers on the device after returning it to the hostMode() state, if it was powered off.
- NOTE: Due to security policies of platforms, this method may behave different on different platforms. For example
- the system can ask the user for confirmation before turning Bluetooth on or off.
+
+ \note Due to varying security policies on the supported platforms, this method may have
+ differing behaviors on the various platforms. For example
+ the system may ask the user for confirmation before turning Bluetooth on or off.
Please refer to the platform specific Bluetooth documentation for details.
*/
diff --git a/src/bluetooth/qbluetoothlocaldevice_android.cpp b/src/bluetooth/qbluetoothlocaldevice_android.cpp
index 4e441bc2..ff36837b 100644
--- a/src/bluetooth/qbluetoothlocaldevice_android.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice_android.cpp
@@ -74,6 +74,7 @@ QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate(
QBluetoothLocalDevicePrivate::~QBluetoothLocalDevicePrivate()
{
+ receiver->unregisterReceiver();
delete receiver;
delete obj;
}
diff --git a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
index 310be91b..9f2e7fd3 100644
--- a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
@@ -503,6 +503,9 @@ void QBluetoothLocalDevicePrivate::_q_devicePropertyChanged(const QString &prope
void QBluetoothLocalDevicePrivate::createCache()
{
+ if (!adapter)
+ return;
+
QDBusPendingReply<QList<QDBusObjectPath> > reply = adapter->ListDevices();
reply.waitForFinished();
if (reply.isError()) {
diff --git a/src/bluetooth/qbluetoothlocaldevice_qnx.cpp b/src/bluetooth/qbluetoothlocaldevice_qnx.cpp
index d0236b6a..8ed29437 100644
--- a/src/bluetooth/qbluetoothlocaldevice_qnx.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice_qnx.cpp
@@ -168,11 +168,42 @@ QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus(const QBluet
{
if (!isValid())
return Unpaired;
+ bool paired = false;
+ bool btle = false; // Bluetooth Low Energy devices
+ QByteArray qnxPath("/pps/services/bluetooth/remote_devices/");
+ qnxPath.append(address.toString().toUtf8());
+ int m_rdfd;
+ if ((m_rdfd = qt_safe_open(qnxPath.constData(), O_RDONLY)) == -1){
+ btle = true;
+ qnxPath.append("-00");
+ if ((m_rdfd = qt_safe_open(qnxPath.constData(), O_RDONLY)) == -1) {
+ qnxPath.replace((qnxPath.length()-3), 3, "-01");
+ if ((m_rdfd = qt_safe_open(qnxPath.constData(), O_RDONLY)) == -1)
+ return Unpaired;
+ }
+ }
+
+ pps_decoder_t ppsDecoder;
+ pps_decoder_initialize(&ppsDecoder, NULL);
+
+ QBluetoothAddress deviceAddr;
+ QString deviceName;
- QVariant status = ppsRemoteDeviceStatus(address.toString().toLocal8Bit(), "paired");
- if (status.toBool())
+ if (!ppsReadRemoteDevice(m_rdfd, &ppsDecoder, &deviceAddr, &deviceName))
+ return Unpaired;
+ bool known = false;
+ // Paired BTLE devices have only known field set to true.
+ if (btle)
+ pps_decoder_get_bool(&ppsDecoder, "known", &known);
+ pps_decoder_get_bool(&ppsDecoder, "paired", &paired);
+ pps_decoder_cleanup(&ppsDecoder);
+
+ if (paired)
+ return Paired;
+ else if (btle && known)
return Paired;
- return Unpaired;
+ else
+ return Unpaired;
}
void QBluetoothLocalDevice::pairingConfirmation(bool confirmation)
diff --git a/src/bluetooth/qbluetoothserver.cpp b/src/bluetooth/qbluetoothserver.cpp
index 3a7e495f..8665e33e 100644
--- a/src/bluetooth/qbluetoothserver.cpp
+++ b/src/bluetooth/qbluetoothserver.cpp
@@ -132,6 +132,8 @@ QT_BEGIN_NAMESPACE
Sets the maximum number of pending connections to \a numConnections. If
the number of pending sockets exceeds this limit new sockets will be rejected.
+ QNX platform supports only one device at the time and it will ignore this value.
+
\sa maxPendingConnections()
*/
@@ -143,7 +145,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn QBluetoothSocket *QBluetoothServer::nextPendingConnection()
- Returns a pointer to aQBluetoothSocket for the next pending connection. It is the callers
+ Returns a pointer to the QBluetoothSocket for the next pending connection. It is the callers
responsibility to delete the pointer.
*/
diff --git a/src/bluetooth/qbluetoothserver_android.cpp b/src/bluetooth/qbluetoothserver_android.cpp
index a2d08757..f90c540e 100644
--- a/src/bluetooth/qbluetoothserver_android.cpp
+++ b/src/bluetooth/qbluetoothserver_android.cpp
@@ -59,8 +59,8 @@ QBluetoothServerPrivate::QBluetoothServerPrivate(QBluetoothServiceInfo::Protocol
: socket(0),maxPendingConnections(1), securityFlags(QBluetooth::NoSecurity), serverType(sType),
m_lastError(QBluetoothServer::NoError)
{
- thread = new ServerAcceptanceThread();
- thread->setMaxPendingConnections(maxPendingConnections);
+ thread = new ServerAcceptanceThread();
+ thread->setMaxPendingConnections(maxPendingConnections);
}
QBluetoothServerPrivate::~QBluetoothServerPrivate()
@@ -71,10 +71,6 @@ QBluetoothServerPrivate::~QBluetoothServerPrivate()
__fakeServerPorts.remove(this);
- if (thread->isRunning()) {
- thread->stop();
- thread->wait();
- }
thread->deleteLater();
thread = 0;
}
@@ -82,33 +78,33 @@ QBluetoothServerPrivate::~QBluetoothServerPrivate()
bool QBluetoothServerPrivate::initiateActiveListening(
const QBluetoothUuid& uuid, const QString &serviceName)
{
- Q_UNUSED(uuid);
- Q_UNUSED(serviceName);
qCDebug(QT_BT_ANDROID) << "Initiate active listening" << uuid.toString() << serviceName;
if (uuid.isNull() || serviceName.isEmpty())
return false;
//no change of SP profile details -> do nothing
- if (uuid == m_uuid && serviceName == m_serviceName)
+ if (uuid == m_uuid && serviceName == m_serviceName && thread->isRunning())
return true;
m_uuid = uuid;
m_serviceName = serviceName;
thread->setServiceDetails(m_uuid, m_serviceName, securityFlags);
- Q_ASSERT(!thread->isRunning());
- thread->start();
- Q_ASSERT(thread->isRunning());
+ thread->run();
+ if (!thread->isRunning())
+ return false;
return true;
}
bool QBluetoothServerPrivate::deactivateActiveListening()
{
- thread->stop();
- thread->wait();
-
+ if (isListening()) {
+ //suppress last error signal due to intended closure
+ thread->disconnect();
+ thread->stop();
+ }
return true;
}
@@ -121,19 +117,30 @@ void QBluetoothServer::close()
{
Q_D(QBluetoothServer);
- d->thread->stop();
- d->thread->wait();
-
- if (d->thread)
- d->thread->disconnect();
__fakeServerPorts.remove(d);
+ if (d->thread->isRunning()) {
+ //suppress last error signal due to intended closure
+ d->thread->disconnect();
+ d->thread->stop();
+ }
}
bool QBluetoothServer::listen(const QBluetoothAddress &localAdapter, quint16 port)
{
+ Q_D(QBluetoothServer);
+ if (serverType() != QBluetoothServiceInfo::RfcommProtocol) {
+ d->m_lastError = UnsupportedProtocolError;
+ emit error(d->m_lastError);
+ return false;
+ }
+
const QList<QBluetoothHostInfo> localDevices = QBluetoothLocalDevice::allDevices();
- if (!localDevices.count())
+ if (!localDevices.count()) {
+ qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth";
+ d->m_lastError = QBluetoothServer::UnknownError;
+ emit error(d->m_lastError);
return false; //no Bluetooth device
+ }
if (!localAdapter.isNull()) {
bool found = false;
@@ -150,13 +157,6 @@ bool QBluetoothServer::listen(const QBluetoothAddress &localAdapter, quint16 por
}
}
- Q_D(QBluetoothServer);
- if (serverType() != QBluetoothServiceInfo::RfcommProtocol) {
- d->m_lastError = UnsupportedProtocolError;
- emit error(d->m_lastError);
- return false;
- }
-
if (d->isListening())
return false;
@@ -202,7 +202,11 @@ bool QBluetoothServer::listen(const QBluetoothAddress &localAdapter, quint16 por
return false;
}
- connect(d->thread, SIGNAL(newConnection()), this, SIGNAL(newConnection()));
+ connect(d->thread, SIGNAL(newConnection()),
+ this, SIGNAL(newConnection()));
+ connect(d->thread, SIGNAL(error(QBluetoothServer::Error)),
+ this, SIGNAL(error(QBluetoothServer::Error)), Qt::QueuedConnection);
+
return true;
}
diff --git a/src/bluetooth/qbluetoothserver_bluez.cpp b/src/bluetooth/qbluetoothserver_bluez.cpp
index b78fb526..e5967f7a 100644
--- a/src/bluetooth/qbluetoothserver_bluez.cpp
+++ b/src/bluetooth/qbluetoothserver_bluez.cpp
@@ -42,6 +42,7 @@
#include "qbluetoothserver.h"
#include "qbluetoothserver_p.h"
#include "qbluetoothsocket.h"
+#include "qbluetoothlocaldevice.h"
#include <QtCore/QLoggingCategory>
#include <QtCore/QSocketNotifier>
@@ -110,6 +111,23 @@ bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port)
return false; //already listening, nothing to do
}
+ QBluetoothLocalDevice device(address);
+ if (!device.isValid()) {
+ qCWarning(QT_BT_BLUEZ) << "Device does not support Bluetooth or"
+ << address.toString() << "is not a valid local adapter";
+ d->m_lastError = QBluetoothServer::UnknownError;
+ emit error(d->m_lastError);
+ return false;
+ }
+
+ QBluetoothLocalDevice::HostMode hostMode = device.hostMode();
+ if (hostMode == QBluetoothLocalDevice::HostPoweredOff) {
+ d->m_lastError = QBluetoothServer::PoweredOffError;
+ emit error(d->m_lastError);
+ qCWarning(QT_BT_BLUEZ) << "Bluetooth device is powered off";
+ return false;
+ }
+
int sock = d->socket->socketDescriptor();
if (sock < 0) {
/* Negative socket descriptor is not always an error case
@@ -142,7 +160,7 @@ bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port)
if (!address.isNull())
convertAddress(address.toUInt64(), addr.rc_bdaddr.b);
else
- convertAddress(Q_UINT64_C(0), addr.rc_bdaddr.b);
+ convertAddress(device.address().toUInt64(), addr.rc_bdaddr.b);
if (::bind(sock, reinterpret_cast<sockaddr *>(&addr), sizeof(sockaddr_rc)) < 0) {
diff --git a/src/bluetooth/qbluetoothserver_p.cpp b/src/bluetooth/qbluetoothserver_p.cpp
index 213d73f1..d9efcf2f 100644
--- a/src/bluetooth/qbluetoothserver_p.cpp
+++ b/src/bluetooth/qbluetoothserver_p.cpp
@@ -46,12 +46,17 @@
QT_BEGIN_NAMESPACE
QBluetoothServerPrivate::QBluetoothServerPrivate(QBluetoothServiceInfo::Protocol sType)
- : serverType(sType), m_lastError(QBluetoothServer::NoError)
+ : maxPendingConnections(1), serverType(sType), m_lastError(QBluetoothServer::NoError)
{
+ if (sType == QBluetoothServiceInfo::RfcommProtocol)
+ socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
+ else
+ socket = new QBluetoothSocket(QBluetoothServiceInfo::L2capProtocol);
}
QBluetoothServerPrivate::~QBluetoothServerPrivate()
{
+ delete socket;
}
void QBluetoothServer::close()
diff --git a/src/bluetooth/qbluetoothserver_qnx.cpp b/src/bluetooth/qbluetoothserver_qnx.cpp
index d4289368..63e92f4f 100644
--- a/src/bluetooth/qbluetoothserver_qnx.cpp
+++ b/src/bluetooth/qbluetoothserver_qnx.cpp
@@ -66,6 +66,8 @@ QBluetoothServerPrivate::~QBluetoothServerPrivate()
q->close();
__fakeServerPorts.remove(this);
ppsUnregisterControl(this);
+ qDeleteAll(activeSockets);
+ activeSockets.clear();
}
void QBluetoothServerPrivate::controlReply(ppsResult result)
@@ -93,7 +95,8 @@ void QBluetoothServerPrivate::controlReply(ppsResult result)
socket->setSocketDescriptor(socketFD, QBluetoothServiceInfo::RfcommProtocol,
QBluetoothSocket::ConnectedState);
- socket->connectToService(QBluetoothAddress(nextClientAddress), m_uuid);
+ socket->d_ptr->m_peerAddress = QBluetoothAddress(nextClientAddress);
+ socket->d_ptr->m_uuid = m_uuid;
activeSockets.append(socket);
socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol, this);
socket->setSocketState(QBluetoothSocket::ListeningState);
@@ -131,17 +134,23 @@ void QBluetoothServerPrivate::controlEvent(ppsResult result)
void QBluetoothServer::close()
{
Q_D(QBluetoothServer);
- if (!d->socket) {
- d->m_lastError = UnknownError;
- emit error(d->m_lastError);
- return;
+ if (!d->activeSockets.isEmpty()) {
+ for (int i = 0; i < d->activeSockets.size(); i++)
+ d->activeSockets.at(i)->close();
+ qDeleteAll(d->activeSockets);
+ d->activeSockets.clear();
+ }
+ if (d->socket) {
+ d->socket->close();
+ delete d->socket;
+ d->socket = 0;
+ if (__fakeServerPorts.contains(d)) {
+ ppsSendControlMessage("deregister_server", 0x1101, d->m_uuid, QString(), QString(), 0);
+ __fakeServerPorts.remove(d);
+ }
+ // force active object (socket) to run and shutdown socket.
+ qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
}
- d->socket->close();
- delete d->socket;
- d->socket = 0;
- ppsSendControlMessage("deregister_server", 0x1101, d->m_uuid, QString(), QString(), 0);
- // force active object (socket) to run and shutdown socket.
- qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
}
bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port)
@@ -154,11 +163,28 @@ bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port)
return false;
}
- // listen has already been called before
- if (d->socket && d->socket->state() == QBluetoothSocket::ListeningState)
+ QBluetoothLocalDevice device(address);
+ if (!device.isValid()) {
+ qCWarning(QT_BT_QNX) << "Device does not support Bluetooth or"
+ << address.toString() << "is not a valid local adapter";
+ d->m_lastError = QBluetoothServer::UnknownError;
+ emit error(d->m_lastError);
+ return false;
+ }
+
+ QBluetoothLocalDevice::HostMode hostMode= device.hostMode();
+ if (hostMode == QBluetoothLocalDevice::HostPoweredOff) {
+ d->m_lastError = QBluetoothServer::PoweredOffError;
+ emit error(d->m_lastError);
+ qCWarning(QT_BT_QNX) << "Bluetooth device is powered off";
return false;
+ }
- d->socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
+ // listen has already been called before
+ if (!d->socket)
+ d->socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
+ else if (d->socket->state() == QBluetoothSocket::ListeningState)
+ return false;
//We can not register an actual Rfcomm port, because the platform does not allow it
//but we need a way to associate a server with a service
@@ -191,7 +217,7 @@ bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port)
void QBluetoothServer::setMaxPendingConnections(int numConnections)
{
Q_D(QBluetoothServer);
- d->maxPendingConnections = numConnections; //Currently not used
+ //QNX supports only one device at the time
}
QBluetoothAddress QBluetoothServer::serverAddress() const
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
index caed88e5..2e55d40e 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
@@ -98,8 +98,14 @@ QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(
QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate()
{
- delete receiver;
- delete localDeviceReceiver;
+ if (receiver) {
+ receiver->unregisterReceiver();
+ delete receiver;
+ }
+ if (localDeviceReceiver) {
+ localDeviceReceiver->unregisterReceiver();
+ delete localDeviceReceiver;
+ }
}
void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address)
@@ -197,7 +203,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr
if (!receiver) {
receiver = new ServiceDiscoveryBroadcastReceiver();
QObject::connect(receiver, SIGNAL(uuidFetchFinished(QBluetoothAddress,QList<QBluetoothUuid>)),
- q, SLOT(_q_processFetchedUuids(const QBluetoothAddress&,const QList<QBluetoothUuid>&)));
+ q, SLOT(_q_processFetchedUuids(QBluetoothAddress,QList<QBluetoothUuid>)));
}
if (!localDeviceReceiver) {
@@ -209,6 +215,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr
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.";
@@ -223,6 +230,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::stop()
discoveredDevices.clear();
//kill receiver to limit load of signals
+ receiver->unregisterReceiver();
receiver->deleteLater();
receiver = 0;
@@ -315,8 +323,9 @@ static QString serviceNameForClassUuid(const uint value)
case QBluetoothUuid::PANU: return QBluetoothServiceDiscoveryAgent::tr("Personal Area Networking (PANU)");
case QBluetoothUuid::NAP: return QBluetoothServiceDiscoveryAgent::tr("Personal Area Networking (NAP)");
case QBluetoothUuid::GN: return QBluetoothServiceDiscoveryAgent::tr("Personal Area Networking (GN)");
- case QBluetoothUuid::DirectPrinting: return QBluetoothServiceDiscoveryAgent::tr("Basic Printing (DP)");
- //case QBluetoothUuid::ReferencePrinting: return QBluetoothServiceDiscoveryAgent::tr("");
+ case QBluetoothUuid::DirectPrinting: return QBluetoothServiceDiscoveryAgent::tr("Basic Direct Printing (BPP)");
+ case QBluetoothUuid::ReferencePrinting: return QBluetoothServiceDiscoveryAgent::tr("Basic Reference Printing (BPP)");
+ case QBluetoothUuid::BasicImage: return QBluetoothServiceDiscoveryAgent::tr("Basic Imaging Profile");
case QBluetoothUuid::ImagingResponder: return QBluetoothServiceDiscoveryAgent::tr("Basic Imaging Responder");
case QBluetoothUuid::ImagingAutomaticArchive: return QBluetoothServiceDiscoveryAgent::tr("Basic Imaging Archive");
case QBluetoothUuid::ImagingReferenceObjects: return QBluetoothServiceDiscoveryAgent::tr("Basic Imaging Ref Objects");
@@ -338,7 +347,14 @@ static QString serviceNameForClassUuid(const uint value)
case QBluetoothUuid::MessageAccessServer: return QBluetoothServiceDiscoveryAgent::tr("Message Access Server");
case QBluetoothUuid::MessageNotificationServer: return QBluetoothServiceDiscoveryAgent::tr("Message Notification Server");
case QBluetoothUuid::MessageAccessProfile: return QBluetoothServiceDiscoveryAgent::tr("Message Access");
- case QBluetoothUuid::PnPInformation: return QBluetoothServiceDiscoveryAgent::tr("Navigation Satellite System");
+ case QBluetoothUuid::GNSS: return QBluetoothServiceDiscoveryAgent::tr("Global Navigation Satellite System");
+ case QBluetoothUuid::GNSSServer: return QBluetoothServiceDiscoveryAgent::tr("Global Navigation Satellite System Server");
+ case QBluetoothUuid::Display3D: return QBluetoothServiceDiscoveryAgent::tr("3D Synchronization Display");
+ case QBluetoothUuid::Glasses3D: return QBluetoothServiceDiscoveryAgent::tr("3D Synchronization Glasses");
+ case QBluetoothUuid::Synchronization3D: return QBluetoothServiceDiscoveryAgent::tr("3D Synchronization");
+ case QBluetoothUuid::MPSProfile: return QBluetoothServiceDiscoveryAgent::tr("Multi-Profile Specification (Profile)");
+ case QBluetoothUuid::MPSService: return QBluetoothServiceDiscoveryAgent::tr("Multi-Profile Specification");
+ case QBluetoothUuid::PnPInformation: return QBluetoothServiceDiscoveryAgent::tr("Device Identification");
//case QBluetoothUuid::GenericNetworking: return QBluetoothServiceDiscoveryAgent::tr("");
//case QBluetoothUuid::GenericFileTransfer: return QBluetoothServiceDiscoveryAgent::tr("");
//case QBluetoothUuid::GenericAudio: return QBluetoothServiceDiscoveryAgent::tr("");
@@ -427,7 +443,6 @@ void QBluetoothServiceDiscoveryAgentPrivate::populateDiscoveredServices(const QB
serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId);
serviceInfo.setServiceName(QBluetoothServiceDiscoveryAgent::tr("Serial Port Profile"));
- //TODO Remove line below - work around
serviceInfo.setServiceUuid(uuids.at(i));
} else if (customUuids.contains(i)) {
//custom uuid but no serial port
@@ -444,16 +459,16 @@ void QBluetoothServiceDiscoveryAgentPrivate::populateDiscoveredServices(const QB
if (!customUuids.contains(i)) {
//if we don't have custom uuid use it as class id as well
- QList<QBluetoothUuid> serviceClassId;
- serviceClassId << uuids.at(i);
- serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, QVariant::fromValue(serviceClassId));
+ QBluetoothServiceInfo::Sequence classId;
+ classId << QVariant::fromValue(uuids.at(i));
+ serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId);
serviceInfo.setServiceName(serviceNameForClassUuid(uuids.at(i).data1));
}
//don't include the service if we already discovered it before
bool alreadyDiscovered = false;
- for (int i = 0; i < discoveredServices.count(); i++) {
- const QBluetoothServiceInfo &info = discoveredServices.at(i);
+ for (int j = 0; j < discoveredServices.count(); j++) {
+ const QBluetoothServiceInfo &info = discoveredServices.at(j);
if (info.device() == serviceInfo.device()
&& info.serviceClassUuids() == serviceInfo.serviceClassUuids()
&& info.serviceUuid() == serviceInfo.serviceUuid()) {
@@ -485,6 +500,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_fetchUuidsTimeout()
Q_ASSERT(sdpCache.isEmpty());
//kill receiver to limit load of signals
+ receiver->unregisterReceiver();
receiver->deleteLater();
receiver = 0;
_q_serviceDiscoveryFinished();
@@ -501,6 +517,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_hostModeStateChanged(QBluetoothL
errorString = QBluetoothServiceDiscoveryAgent::tr("Device is powered off");
//kill receiver to limit load of signals
+ receiver->unregisterReceiver();
receiver->deleteLater();
receiver = 0;
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
index 8b80ed11..c7fc47fb 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
@@ -522,7 +522,6 @@ QVariant QBluetoothServiceDiscoveryAgentPrivate::readAttributeValue(QXmlStreamRe
qCWarning(QT_BT_BLUEZ) << "unknown attribute type"
<< xml.name().toString()
<< xml.attributes().value(QLatin1String("value")).toString();
- Q_ASSERT(false);
xml.skipCurrentElement();
return QVariant();
}
diff --git a/src/bluetooth/qbluetoothserviceinfo.cpp b/src/bluetooth/qbluetoothserviceinfo.cpp
index 84655b77..cfb2bbcb 100644
--- a/src/bluetooth/qbluetoothserviceinfo.cpp
+++ b/src/bluetooth/qbluetoothserviceinfo.cpp
@@ -137,7 +137,8 @@ QT_BEGIN_NAMESPACE
This enum describes the socket protocol used by the service.
\value UnknownProtocol The service uses an unknown socket protocol.
- \value L2capProtocol The service uses the L2CAP socket protocol.
+ \value L2capProtocol The service uses the L2CAP socket protocol. This protocol is not supported
+ for direct socket connections on Android and BlackBerry.
\value RfcommProtocol The service uses the RFCOMM socket protocol.
*/
diff --git a/src/bluetooth/qbluetoothserviceinfo_qnx.cpp b/src/bluetooth/qbluetoothserviceinfo_qnx.cpp
index 0ce566e3..30dac958 100644
--- a/src/bluetooth/qbluetoothserviceinfo_qnx.cpp
+++ b/src/bluetooth/qbluetoothserviceinfo_qnx.cpp
@@ -61,16 +61,31 @@ bool QBluetoothServiceInfoPrivate::isRegistered() const
return registered;
}
+extern QHash<QBluetoothServerPrivate*, int> __fakeServerPorts;
+
bool QBluetoothServiceInfoPrivate::unregisterService()
{
if (!registered)
return false;
-
- return false;
+ if (serverChannel() == -1)
+ return false;
+ if ( __fakeServerPorts.key(serverChannel()) != 0) {
+ if (!ppsSendControlMessage("deregister_server", 0x1101, attributes.value(QBluetoothServiceInfo::ServiceId).value<QBluetoothUuid>(), QString(),
+ attributes.value(QBluetoothServiceInfo::ServiceName).toString(),
+ __fakeServerPorts.key(serverChannel()), BT_SPP_SERVER_SUBTYPE)) {
+ return false;
+ }
+ else {
+ __fakeServerPorts.remove(__fakeServerPorts.key(serverChannel()));
+ registered = false;
+ return true;
+ }
+ }
+ else {
+ return false;
+ }
}
-extern QHash<QBluetoothServerPrivate*, int> __fakeServerPorts;
-
bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress& localAdapter)
{
Q_UNUSED(localAdapter); //QNX always uses default local adapter
diff --git a/src/bluetooth/qbluetoothsocket.cpp b/src/bluetooth/qbluetoothsocket.cpp
index c7aea0b7..6272ca1f 100644
--- a/src/bluetooth/qbluetoothsocket.cpp
+++ b/src/bluetooth/qbluetoothsocket.cpp
@@ -313,7 +313,7 @@ void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, Op
{
Q_D(QBluetoothSocket);
- if (state() != QBluetoothSocket::UnconnectedState) {
+ if (state() != QBluetoothSocket::UnconnectedState && state() != QBluetoothSocket::ServiceLookupState) {
qCWarning(QT_BT) << "QBluetoothSocket::connectToService called on busy socket";
d->errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
setSocketError(QBluetoothSocket::OperationError);
@@ -686,6 +686,7 @@ bool QBluetoothSocket::setSocketDescriptor(int socketDescriptor, QBluetoothServi
/*!
Returns the platform-specific socket descriptor, if available.
+ This function returns -1 if the descriptor is not available or an error has occurred.
*/
int QBluetoothSocket::socketDescriptor() const
diff --git a/src/bluetooth/qbluetoothsocket_android.cpp b/src/bluetooth/qbluetoothsocket_android.cpp
index 93089182..a894fed3 100644
--- a/src/bluetooth/qbluetoothsocket_android.cpp
+++ b/src/bluetooth/qbluetoothsocket_android.cpp
@@ -97,7 +97,6 @@ void QBluetoothSocketPrivate::connectToServiceConc(const QBluetoothAddress &addr
Q_Q(QBluetoothSocket);
Q_UNUSED(openMode);
- qDebug() << "GGGGConnecting to" << address.toString() << uuid.toString();
if (!adapter.isValid()) {
qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth";
errorString = QBluetoothSocket::tr("Device does not support Bluetooth");
@@ -171,9 +170,7 @@ void QBluetoothSocketPrivate::connectToServiceConc(const QBluetoothAddress &addr
}
if (inputThread) {
- inputThread->stop();
- inputThread->wait();
- delete inputThread;
+ inputThread->deleteLater();
inputThread = 0;
}
@@ -201,10 +198,29 @@ void QBluetoothSocketPrivate::connectToServiceConc(const QBluetoothAddress &addr
}
inputThread = new InputStreamThread(this);
- QObject::connect(inputThread, SIGNAL(dataAvailable()), q, SIGNAL(readyRead()), Qt::QueuedConnection);
+ QObject::connect(inputThread, SIGNAL(dataAvailable()),
+ q, SIGNAL(readyRead()), Qt::QueuedConnection);
QObject::connect(inputThread, SIGNAL(error()),
this, SLOT(inputThreadError()), Qt::QueuedConnection);
- inputThread->start();
+
+ if (!inputThread->run()) {
+ //close socket again
+ socketObject.callMethod<void>("close");
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+
+ socketObject = inputStream = outputStream = remoteDevice = QAndroidJniObject();
+
+ delete inputThread;
+ inputThread = 0;
+
+ errorString = QBluetoothSocket::tr("Input stream thread cannot be started");
+ q->setSocketError(QBluetoothSocket::NetworkError);
+ q->setSocketState(QBluetoothSocket::UnconnectedState);
+ return;
+ }
q->setSocketState(QBluetoothSocket::ConnectedState);
emit q->connected();
@@ -233,6 +249,10 @@ void QBluetoothSocketPrivate::abort()
* new state, error and emits relevant signals.
* See QBluetoothSocketPrivate::inputThreadError() for details
*/
+
+ if (inputThread)
+ inputThread->prepareForClosure();
+
//triggers abort of input thread as well
socketObject.callMethod<void>("close");
if (env->ExceptionCheck()) {
@@ -243,9 +263,9 @@ void QBluetoothSocketPrivate::abort()
}
if (inputThread) {
- inputThread->stop();
- inputThread->wait();
- delete inputThread;
+ //don't delete here as signals caused by Java Thread are still
+ //going to be emitted
+ //delete occurs in inputThreadError()
inputThread = 0;
}
@@ -304,10 +324,9 @@ quint16 QBluetoothSocketPrivate::peerPort() const
qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
{
//TODO implement buffered behavior (so far only unbuffered)
- //TODO check that readData and writeData return -1 on error (on all platforms)
Q_Q(QBluetoothSocket);
if (state != QBluetoothSocket::ConnectedState || !outputStream.isValid()) {
- qCWarning(QT_BT_ANDROID) << "Socket::writeData: " << (int)state << outputStream.isValid() ;
+ qCWarning(QT_BT_ANDROID) << "Socket::writeData: " << state << outputStream.isValid();
errorString = QBluetoothSocket::tr("Cannot write while not connected");
q->setSocketError(QBluetoothSocket::OperationError);
return -1;
@@ -335,8 +354,8 @@ qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
{
Q_Q(QBluetoothSocket);
if (state != QBluetoothSocket::ConnectedState || !inputThread) {
- qCWarning(QT_BT_ANDROID) << "Socket::writeData: " << (int)state << outputStream.isValid() ;
- errorString = QBluetoothSocket::tr("Cannot write while not connected");
+ qCWarning(QT_BT_ANDROID) << "Socket::readData: " << state << inputThread ;
+ errorString = QBluetoothSocket::tr("Cannot read while not connected");
q->setSocketError(QBluetoothSocket::OperationError);
return -1;
}
@@ -344,13 +363,38 @@ qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
return inputThread->readData(data, maxSize);
}
-void QBluetoothSocketPrivate::inputThreadError()
+void QBluetoothSocketPrivate::inputThreadError(int errorCode)
{
Q_Q(QBluetoothSocket);
- //any error from InputThread is a NetworkError
- errorString = QBluetoothSocket::tr("Network error during read");
- q->setSocketError(QBluetoothSocket::NetworkError);
+ if (errorCode != -1) { //magic error which is expected and can be ignored
+ errorString = QBluetoothSocket::tr("Network error during read");
+ q->setSocketError(QBluetoothSocket::NetworkError);
+ }
+
+ //finally we can delete the InputStreamThread
+ InputStreamThread *client = qobject_cast<InputStreamThread *>(sender());
+ if (client)
+ client->deleteLater();
+
+ if (socketObject.isValid()) {
+ //triggered when remote side closed the socket
+ //cleanup internal objects
+ //if it was call to local close()/abort() the objects are cleaned up already
+
+ bool stillConnected = socketObject.callMethod<jboolean>("isConnected");
+ if (stillConnected) {
+ QAndroidJniEnvironment env;
+ socketObject.callMethod<void>("close");
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+ }
+
+ inputStream = outputStream = remoteDevice = socketObject = QAndroidJniObject();
+ }
+
q->setSocketState(QBluetoothSocket::UnconnectedState);
emit q->disconnected();
}
@@ -412,17 +456,18 @@ bool QBluetoothSocketPrivate::setSocketDescriptor(const QAndroidJniObject &socke
return false;
}
+ remoteDevice = socketObject.callObjectMethod("getRemoteDevice", "()Landroid/bluetooth/BluetoothDevice;");
+
if (inputThread) {
- inputThread->stop();
- inputThread->wait();
- delete inputThread;
+ inputThread->deleteLater();
inputThread = 0;
}
inputThread = new InputStreamThread(this);
- QObject::connect(inputThread, SIGNAL(dataAvailable()), q, SIGNAL(readyRead()), Qt::QueuedConnection);
- QObject::connect(inputThread, SIGNAL(error()),
- this, SLOT(inputThreadError()), Qt::QueuedConnection);
- inputThread->start();
+ QObject::connect(inputThread, SIGNAL(dataAvailable()),
+ q, SIGNAL(readyRead()), Qt::QueuedConnection);
+ QObject::connect(inputThread, SIGNAL(error(int)),
+ this, SLOT(inputThreadError(int)), Qt::QueuedConnection);
+ inputThread->run();
q->setSocketState(socketState);
@@ -434,11 +479,6 @@ bool QBluetoothSocketPrivate::setSocketDescriptor(const QAndroidJniObject &socke
return true;
}
-int QBluetoothSocketPrivate::socketDescriptor() const
-{
- return 0;
-}
-
qint64 QBluetoothSocketPrivate::bytesAvailable() const
{
//We cannot access buffer directly as it is part of different thread
diff --git a/src/bluetooth/qbluetoothsocket_bluez.cpp b/src/bluetooth/qbluetoothsocket_bluez.cpp
index 235f21d3..6aad6603 100644
--- a/src/bluetooth/qbluetoothsocket_bluez.cpp
+++ b/src/bluetooth/qbluetoothsocket_bluez.cpp
@@ -442,10 +442,18 @@ quint16 QBluetoothSocketPrivate::peerPort() const
qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
{
Q_Q(QBluetoothSocket);
+
+ if (state != QBluetoothSocket::ConnectedState) {
+ errorString = QBluetoothSocket::tr("Cannot write while not connected");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return -1;
+ }
+
if (q->openMode() & QIODevice::Unbuffered) {
if (::write(socket, data, maxSize) != maxSize) {
errorString = QBluetoothSocket::tr("Network Error");
q->setSocketError(QBluetoothSocket::NetworkError);
+ return -1;
}
emit q->bytesWritten(maxSize);
@@ -455,7 +463,7 @@ qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
else {
if(!connectWriteNotifier)
- return 0;
+ return -1;
if(txBuffer.size() == 0) {
connectWriteNotifier->setEnabled(true);
@@ -471,11 +479,19 @@ qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
{
- if(!buffer.isEmpty()){
+ Q_Q(QBluetoothSocket);
+
+ if (state != QBluetoothSocket::ConnectedState) {
+ errorString = QBluetoothSocket::tr("Cannot read while not connected");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return -1;
+ }
+
+ if (!buffer.isEmpty()) {
int i = buffer.read(data, maxSize);
return i;
-
}
+
return 0;
}
@@ -535,11 +551,6 @@ bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoo
return true;
}
-int QBluetoothSocketPrivate::socketDescriptor() const
-{
- return socket;
-}
-
qint64 QBluetoothSocketPrivate::bytesAvailable() const
{
return buffer.size();
diff --git a/src/bluetooth/qbluetoothsocket_p.cpp b/src/bluetooth/qbluetoothsocket_p.cpp
index 018ccea6..6e78be9e 100644
--- a/src/bluetooth/qbluetoothsocket_p.cpp
+++ b/src/bluetooth/qbluetoothsocket_p.cpp
@@ -45,6 +45,10 @@
QT_BEGIN_NAMESPACE
QBluetoothSocketPrivate::QBluetoothSocketPrivate()
+ : socket(-1),
+ socketType(QBluetoothServiceInfo::UnknownProtocol),
+ state(QBluetoothSocket::UnconnectedState),
+ socketError(QBluetoothSocket::NoSocketError)
{
}
@@ -54,7 +58,7 @@ QBluetoothSocketPrivate::~QBluetoothSocketPrivate()
bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
{
- Q_UNUSED(type);
+ socketType = type;
return false;
}
@@ -111,14 +115,31 @@ qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
{
Q_UNUSED(data);
Q_UNUSED(maxSize);
- return 0;
+
+ Q_Q(QBluetoothSocket);
+
+ if (state != QBluetoothSocket::ConnectedState) {
+ errorString = QBluetoothSocket::tr("Cannot write while not connected");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return -1;
+ }
+ return -1;
}
qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
{
Q_UNUSED(data);
Q_UNUSED(maxSize);
- return 0;
+
+ Q_Q(QBluetoothSocket);
+
+ if (state != QBluetoothSocket::ConnectedState) {
+ errorString = QBluetoothSocket::tr("Cannot write while not connected");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return -1;
+ }
+
+ return -1;
}
void QBluetoothSocketPrivate::close()
@@ -135,11 +156,6 @@ bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoo
return false;
}
-int QBluetoothSocketPrivate::socketDescriptor() const
-{
- return 0;
-}
-
qint64 QBluetoothSocketPrivate::bytesAvailable() const
{
return 0;
diff --git a/src/bluetooth/qbluetoothsocket_p.h b/src/bluetooth/qbluetoothsocket_p.h
index 95e67e51..2fabeba1 100644
--- a/src/bluetooth/qbluetoothsocket_p.h
+++ b/src/bluetooth/qbluetoothsocket_p.h
@@ -87,6 +87,8 @@ class QBluetoothSocketPrivate
{
#endif
Q_DECLARE_PUBLIC(QBluetoothSocket)
+ friend class QBluetoothServerPrivate;
+
public:
QBluetoothSocketPrivate();
@@ -131,7 +133,6 @@ public:
bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
QBluetoothSocket::SocketState socketState = QBluetoothSocket::ConnectedState,
QBluetoothSocket::OpenMode openMode = QBluetoothSocket::ReadWrite);
- int socketDescriptor() const;
qint64 bytesAvailable() const;
@@ -169,7 +170,7 @@ public:
InputStreamThread *inputThread;
private Q_SLOTS:
- void inputThreadError();
+ void inputThreadError(int errorCode);
#endif
diff --git a/src/bluetooth/qbluetoothsocket_qnx.cpp b/src/bluetooth/qbluetoothsocket_qnx.cpp
index 81c46dd7..4e277e28 100644
--- a/src/bluetooth/qbluetoothsocket_qnx.cpp
+++ b/src/bluetooth/qbluetoothsocket_qnx.cpp
@@ -214,11 +214,19 @@ quint16 QBluetoothSocketPrivate::peerPort() const
qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
{
Q_Q(QBluetoothSocket);
+
+ if (state != QBluetoothSocket::ConnectedState) {
+ errorString = QBluetoothSocket::tr("Cannot write while not connected");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return -1;
+ }
+
if (q->openMode() & QIODevice::Unbuffered) {
if (::write(socket, data, maxSize) != maxSize) {
errorString = QBluetoothSocket::tr("Network Error");
q->setSocketError(QBluetoothSocket::NetworkError);
qCWarning(QT_BT_QNX) << Q_FUNC_INFO << "Socket error";
+ return -1;
}
Q_EMIT q->bytesWritten(maxSize);
@@ -226,7 +234,7 @@ qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
return maxSize;
} else {
if (!connectWriteNotifier)
- return 0;
+ return -1;
if (txBuffer.size() == 0) {
connectWriteNotifier->setEnabled(true);
@@ -242,7 +250,15 @@ qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
{
- if (!buffer.isEmpty()){
+ Q_Q(QBluetoothSocket);
+
+ if (state != QBluetoothSocket::ConnectedState) {
+ errorString = QBluetoothSocket::tr("Cannot read while not connected");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return -1;
+ }
+
+ if (!buffer.isEmpty()) {
int i = buffer.read(data, maxSize);
return i;
}
@@ -288,11 +304,6 @@ bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoo
return true;
}
-int QBluetoothSocketPrivate::socketDescriptor() const
-{
- return 0;
-}
-
qint64 QBluetoothSocketPrivate::bytesAvailable() const
{
return buffer.size();
diff --git a/src/bluetooth/qbluetoothuuid.cpp b/src/bluetooth/qbluetoothuuid.cpp
index e04dabc3..92b20f2a 100644
--- a/src/bluetooth/qbluetoothuuid.cpp
+++ b/src/bluetooth/qbluetoothuuid.cpp
@@ -49,7 +49,6 @@
QT_BEGIN_NAMESPACE
// Bluetooth base UUID 00000000-0000-1000-8000-00805F9B34FB
-// TODO: make more efficient
Q_GLOBAL_STATIC_WITH_ARGS(QUuid, baseUuid, ("{00000000-0000-1000-8000-00805F9B34FB}"))
/*!
@@ -98,88 +97,81 @@ Q_GLOBAL_STATIC_WITH_ARGS(QUuid, baseUuid, ("{00000000-0000-1000-8000-00805F9B34
/*!
\enum QBluetoothUuid::ServiceClassUuid
- This enum is a convienience type for Bluetooth service class UUIDs. Values of this type will be
- implicitly converted into a QBluetoothUuid when necessary.
+ This enum is a convienience type for Bluetooth service class and profile UUIDs. Values of this type will be
+ implicitly converted into a QBluetoothUuid when necessary. Some UUIDs refer to service class ids, others to profile
+ ids and some can be used as both. In general, profile UUIDs shall only be used in a
+ \l QBluetoothServiceInfo::BluetoothProfileDescriptorList attribute and service class UUIDs shall only be used
+ in a \l QBluetoothServiceInfo::ServiceClassIds attribute. If the UUID is marked as profile and service class UUID
+ it can be used as a value for either of the above service attributes. Such a dual use has historical reasons
+ but is no longer permissible for newer UUIDs.
+
+ The list below explicitly states as what type each UUID shall be used.
+ \value ServiceDiscoveryServer Service discovery server UUID (service)
+ \value BrowseGroupDescriptor Browser group descriptor (service)
\value PublicBrowseGroup Public browse group service class. Services which have the public
- browse group in their \l {QBluetoothServiceInfo::BrowseGroupList}{browse group list} are discoverable
- by the remote devices.
- \value ObexObjectPush OBEX object push service UUID.
- \value ServiceDiscoveryServer
- \value BrowseGroupDescriptor Browser group descriptor
- \value SerialPort Serial Port Profile UUID
- \value LANAccessUsingPPP LAN Access Profile UUID
- \value DialupNetworking Dial-up Networking Profile UUID
- \value IrMCSync Synchronization Profile UUID
- \value OBEXFileTransfer File Transfer Profile (FTP) UUID
- \value IrMCSyncCommand Synchronization Profile UUID
- \value Headset Headset Profile (HSP) UUID
- \value AudioSource Advanced Audio Distribution Profile (A2DP) UUID
- \value AudioSink Advanced Audio Distribution Profile (A2DP) UUID
- \value AV_RemoteControlTarget Audio/Video Remote Control Profile (AVRCP) UUID
- \value AdvancedAudioDistribution Advanced Audio Distribution Profile (A2DP) UUID
- \value AV_RemoteControl Audio/Video Remote Control Profile (AVRCP) UUID
- \value AV_RemoteControlController Audio/Video Remote Control Profile UUID
- \value HeadsetAG Headset Profile (HSP) UUID
- \value PANU Personal Area Networking Profile (PAN) UUID
- \value NAP Personal Area Networking Profile (PAN) UUID
- \value GN Personal Area Networking Profile (PAN) UUID
- \value DirectPrinting Basic Printing Profile (BPP) UUID
- \value ReferencePrinting Related to Basic Printing Profile (BPP) UUID
- \value ImagingResponder Basic Imaging Profile (BIP) UUID
- \value ImagingAutomaticArchive Basic Imaging Profile (BIP) UUID
- \value ImagingReferenceObjects Basic Imaging Profile (BIP) UUID
- \value Handsfree Hands-Free Profile (HFP) Service Class Identifier and Profile Identifier
- \value HandsfreeAudioGateway Hands-free Profile (HFP) UUID
- \value DirectPrintingReferenceObjectsService Basic Printing Profile (BPP) UUID
- \value ReflectedUI Basic Printing Profile (BPP) UUID
- \value BasicPrinting Basic Printing Profile (BPP) UUID
- \value PrintingStatus Basic Printing Profile (BPP) UUID
- \value HumanInterfaceDeviceService Human Interface Device (HID) UUID
- \value HardcopyCableReplacement Hardcopy Cable Replacement Profile (HCRP)
- \value HCRPrint Hardcopy Cable Replacement Profile (HCRP)
- \value HCRScan Hardcopy Cable Replacement Profile (HCRP)
- \value SIMAccess SIM Access Profile (SAP) UUID
- \value PhonebookAccessPCE Phonebook Access Profile (PBAP) UUID
- \value PhonebookAccessPSE Phonebook Access Profile (PBAP) UUID
- \value PhonebookAccess Phonebook Access Profile (PBAP)
- \value HeadsetHS Headset Profile (HSP) UUID
- \value MessageAccessServer Message Access Profile (MAP) UUID
- \value MessageNotificationServer Message Access Profile (MAP) UUID
- \value MessageAccessProfile Message Access Profile (MAP) UUID
- \value PnPInformation Device Identification (DID) UUID
- \value GenericNetworking Generic networking
- \value GenericFileTransfer Generic file transfer
- \value GenericAudio Generic audio
- \value GenericTelephony Generic telephone
- \value VideoSource Video Distribution Profile (VDP)
- \value VideoSink Video Distribution Profile (VDP)
- \value VideoDistribution Video Distribution Profile (VDP)
- \value HDP Health Device Profile
- \value HDPSource Health Device Profile
- \value HDPSink Health Device Profile
- \value HardcopyCableReplacement Hardcopy Cable Replacement Profile (HCRP)
- \value HCRPrint Hardcopy Cable Replacement Profile (HCRP)
- \value HCRScan Hardcopy Cable Replacement Profile (HCRP)
- \value SIMAccess SIM Access Profile (SAP) UUID
- \value PhonebookAccessPCE Phonebook Access Profile (PBAP) UUID
- \value PhonebookAccessPSE Phonebook Access Profile (PBAP) UUID
- \value PhonebookAccess Phonebook Access Profile (PBAP)
- \value HeadsetHS Headset Profile (HSP) UUID
- \value MessageAccessServer Message Access Profile (MAP) UUID
- \value MessageNotificationServer Message Access Profile (MAP) UUID
- \value MessageAccessProfile Message Access Profile (MAP) UUID
- \value PnPInformation Device Identification (DID) UUID
- \value GenericNetworking Generic networking
- \value GenericFileTransfer Generic file transfer
- \value GenericAudio Generic audio
- \value GenericTelephony Generic telephone
- \value VideoSource Video Distribution Profile (VDP)
- \value VideoSink Video Distribution Profile (VDP)
- \value VideoDistribution Video Distribution Profile (VDP)
- \value HDP Health Device Profile
- \value HDPSource Health Device Profile
- \value HDPSink Health Device Profile
+ browse group in their \l {QBluetoothServiceInfo::BrowseGroupList}{browse group list}
+ are discoverable by the remote devices.
+ \value SerialPort Serial Port Profile UUID (service & profile)
+ \value LANAccessUsingPPP LAN Access Profile UUID (service & profile)
+ \value DialupNetworking Dial-up Networking Profile UUID (service & profile)
+ \value IrMCSync Synchronization Profile UUID (service & profile)
+ \value ObexObjectPush OBEX object push service UUID (service & profile)
+ \value OBEXFileTransfer File Transfer Profile (FTP) UUID (service & profile)
+ \value IrMCSyncCommand Synchronization Profile UUID (profile)
+ \value Headset Headset Profile (HSP) UUID (service & profile)
+ \value AudioSource Advanced Audio Distribution Profile (A2DP) UUID (service)
+ \value AudioSink Advanced Audio Distribution Profile (A2DP) UUID (service)
+ \value AV_RemoteControlTarget Audio/Video Remote Control Profile (AVRCP) UUID (service)
+ \value AdvancedAudioDistribution Advanced Audio Distribution Profile (A2DP) UUID (profile)
+ \value AV_RemoteControl Audio/Video Remote Control Profile (AVRCP) UUID (service & profile)
+ \value AV_RemoteControlController Audio/Video Remote Control Profile UUID (service)
+ \value HeadsetAG Headset Profile (HSP) UUID (service)
+ \value PANU Personal Area Networking Profile (PAN) UUID (service & profile)
+ \value NAP Personal Area Networking Profile (PAN) UUID (service & profile)
+ \value GN Personal Area Networking Profile (PAN) UUID (service & profile)
+ \value DirectPrinting Basic Printing Profile (BPP) UUID (service)
+ \value ReferencePrinting Related to Basic Printing Profile (BPP) UUID (service)
+ \value BasicImage Basic Imaging Profile (BIP) UUID (profile)
+ \value ImagingResponder Basic Imaging Profile (BIP) UUID (service)
+ \value ImagingAutomaticArchive Basic Imaging Profile (BIP) UUID (service)
+ \value ImagingReferenceObjects Basic Imaging Profile (BIP) UUID (service)
+ \value Handsfree Hands-Free Profile (HFP) UUID (service & profile)
+ \value HandsfreeAudioGateway Hands-Free Audio Gateway (HFP) UUID (service)
+ \value DirectPrintingReferenceObjectsService Basic Printing Profile (BPP) UUID (service)
+ \value ReflectedUI Basic Printing Profile (BPP) UUID (service)
+ \value BasicPrinting Basic Printing Profile (BPP) UUID (profile)
+ \value PrintingStatus Basic Printing Profile (BPP) UUID (service)
+ \value HumanInterfaceDeviceService Human Interface Device (HID) UUID (service & profile)
+ \value HardcopyCableReplacement Hardcopy Cable Replacement Profile (HCRP) (profile)
+ \value HCRPrint Hardcopy Cable Replacement Profile (HCRP) (service)
+ \value HCRScan Hardcopy Cable Replacement Profile (HCRP) (service)
+ \value SIMAccess SIM Access Profile (SAP) UUID (service and profile)
+ \value PhonebookAccessPCE Phonebook Access Profile (PBAP) UUID (service)
+ \value PhonebookAccessPSE Phonebook Access Profile (PBAP) UUID (service)
+ \value PhonebookAccess Phonebook Access Profile (PBAP) (profile)
+ \value HeadsetHS Headset Profile (HSP) UUID (service)
+ \value MessageAccessServer Message Access Profile (MAP) UUID (service)
+ \value MessageNotificationServer Message Access Profile (MAP) UUID (service)
+ \value MessageAccessProfile Message Access Profile (MAP) UUID (profile)
+ \value GNSS Global Navigation Satellite System UUID (profile)
+ \value GNSSServer Global Navigation Satellite System Server (UUID) (service)
+ \value Display3D 3D Synchronization Display UUID (service)
+ \value Glasses3D 3D Synchronization Glasses UUID (service)
+ \value Synchronization3D 3D Synchronization UUID (profile)
+ \value MPSProfile Multi-Profile Specification UUID (profile)
+ \value MPSService Multi-Profile Specification UUID (service)
+ \value PnPInformation Device Identification (DID) UUID (service & profile)
+ \value GenericNetworking Generic networking UUID (service)
+ \value GenericFileTransfer Generic file transfer UUID (service)
+ \value GenericAudio Generic audio UUID (service)
+ \value GenericTelephony Generic telephone UUID (service)
+ \value VideoSource Video Distribution Profile (VDP) UUID (service)
+ \value VideoSink Video Distribution Profile (VDP) UUID (service)
+ \value VideoDistribution Video Distribution Profile (VDP) UUID (profile)
+ \value HDP Health Device Profile (HDP) UUID (profile)
+ \value HDPSource Health Device Profile Source (HDP) UUID (service)
+ \value HDPSink Health Device Profile Sink (HDP) UUID (service)
\value GenericAccess Generic access service for Bluetooth Low Energy devices UUID (service).
It contains generic information about the device. All available Characteristics are readonly.
\value GenericAttribute
diff --git a/src/bluetooth/qbluetoothuuid.h b/src/bluetooth/qbluetoothuuid.h
index 03b06bf2..c67d2e31 100644
--- a/src/bluetooth/qbluetoothuuid.h
+++ b/src/bluetooth/qbluetoothuuid.h
@@ -112,6 +112,7 @@ public:
GN = 0x1117,
DirectPrinting = 0x1118,
ReferencePrinting = 0x1119,
+ BasicImage = 0x111a,
ImagingResponder = 0x111b,
ImagingAutomaticArchive = 0x111c,
ImagingReferenceObjects = 0x111d,
@@ -133,7 +134,14 @@ public:
MessageAccessServer = 0x1132,
MessageNotificationServer = 0x1133,
MessageAccessProfile = 0x1134,
- PnPInformation = 0x1135,
+ GNSS = 0x1135,
+ GNSSServer = 0x1136,
+ Display3D = 0x1137,
+ Glasses3D = 0x1138,
+ Synchronization3D = 0x1139,
+ MPSProfile = 0x113a,
+ MPSService = 0x113b,
+ PnPInformation = 0x1200,
GenericNetworking = 0x1201,
GenericFileTransfer = 0x1202,
GenericAudio = 0x1203,
diff --git a/src/imports/bluetooth/plugin.cpp b/src/imports/bluetooth/plugin.cpp
index bcf59794..6d3b3afa 100644
--- a/src/imports/bluetooth/plugin.cpp
+++ b/src/imports/bluetooth/plugin.cpp
@@ -75,9 +75,9 @@ public:
qmlRegisterType<QDeclarativeBluetoothService >(uri, major, minor, "BluetoothService");
qmlRegisterType<QDeclarativeBluetoothSocket >(uri, major, minor, "BluetoothSocket");
- // Register the 5.3 types
- // introduces 5.3 version, other existing 5.2 exports automatically become availabe under 5.3 as well
- minor = 3;
+ // Register the 5.4 types
+ // introduces 5.4 version, other existing 5.2 exports become automatically available under 5.2-5.4
+ minor = 4;
qmlRegisterType<QDeclarativeBluetoothDiscoveryModel >(uri, major, minor, "BluetoothDiscoveryModel");
}
};
diff --git a/src/imports/bluetooth/plugins.qmltypes b/src/imports/bluetooth/plugins.qmltypes
index 18647c2c..f7d0d08d 100644
--- a/src/imports/bluetooth/plugins.qmltypes
+++ b/src/imports/bluetooth/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.1
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -notrelocatable QtBluetooth 5.3'
+// 'qmlplugindump -notrelocatable QtBluetooth 5.4'
Module {
Component {
@@ -13,7 +13,7 @@ Module {
exports: [
"QtBluetooth/BluetoothDiscoveryModel 5.0",
"QtBluetooth/BluetoothDiscoveryModel 5.2",
- "QtBluetooth/BluetoothDiscoveryModel 5.3"
+ "QtBluetooth/BluetoothDiscoveryModel 5.4"
]
exportMetaObjectRevisions: [0, 0, 0]
Enum {
diff --git a/src/imports/nfc/plugin.cpp b/src/imports/nfc/plugin.cpp
index 8694e185..16364cf8 100644
--- a/src/imports/nfc/plugin.cpp
+++ b/src/imports/nfc/plugin.cpp
@@ -43,7 +43,6 @@
#include <QtQml/QQmlExtensionPlugin>
#include "qqmlndefrecord.h"
-//#include "qdeclarativenearfieldsocket_p.h"
#include "qdeclarativenearfield_p.h"
#include "qdeclarativendeffilter_p.h"
#include "qdeclarativendeftextrecord_p.h"
@@ -67,7 +66,6 @@ public:
// Register the 5.0 types
int major = 5;
int minor = 0;
- //qmlRegisterType<QDeclarativeNearFieldSocket>(uri, major, minor, "NearFieldSocket");
qmlRegisterType<QDeclarativeNearField>(uri, major, minor, "NearField");
qmlRegisterType<QDeclarativeNdefFilter>(uri, major, minor, "NdefFilter");
@@ -85,9 +83,9 @@ public:
qmlRegisterType<QDeclarativeNdefUriRecord>(uri, major, minor, "NdefUriRecord");
qmlRegisterType<QDeclarativeNdefMimeRecord>(uri, major, minor, "NdefMimeRecord");
- // Register the 5.3 types
- // introduces 5.3 version, other existing 5.2 exports automatically become availabe under 5.3 as well
- minor = 3;
+ // Register the 5.4 types
+ // introduces 5.4 version, other existing 5.2 exports become automatically available under 5.2-5.4l
+ minor = 4;
qmlRegisterType<QDeclarativeNearField>(uri, major, minor, "NearField");
}
};
diff --git a/src/imports/nfc/plugins.qmltypes b/src/imports/nfc/plugins.qmltypes
index fff2834f..bbdc4398 100644
--- a/src/imports/nfc/plugins.qmltypes
+++ b/src/imports/nfc/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.1
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -notrelocatable QtNfc 5.3'
+// 'qmlplugindump -notrelocatable QtNfc 5.4'
Module {
Component {
@@ -55,7 +55,7 @@ Module {
exports: [
"QtNfc/NearField 5.0",
"QtNfc/NearField 5.2",
- "QtNfc/NearField 5.3"
+ "QtNfc/NearField 5.4"
]
exportMetaObjectRevisions: [0, 0, 0]
Property { name: "messageRecords"; type: "QQmlNdefRecord"; isList: true; isReadonly: true }
diff --git a/src/imports/nfc/qdeclarativenearfield.cpp b/src/imports/nfc/qdeclarativenearfield.cpp
index 673c9a0d..b1aeced7 100644
--- a/src/imports/nfc/qdeclarativenearfield.cpp
+++ b/src/imports/nfc/qdeclarativenearfield.cpp
@@ -69,14 +69,7 @@
and \l orderMatch properties to match the required NDEF messages. Once an NDEF message is
successfully read from a tag the \l messageRecords property is updated.
- \code
- NearField {
- filter: [ NdefFilter { type: "U"; typeNameFormat: NdefRecord.NfcRtd; minimum: 1; maximum: 1 } ]
- orderMatch: false
-
- onMessageRecordsChanged: displayMessage()
- }
- \endcode
+ \snippet doc_src_qtnfc.qml QML register for messages
*/
/*!
diff --git a/src/nfc/doc/snippets/doc_src_qtnfc.cpp b/src/nfc/doc/snippets/doc_src_qtnfc.cpp
index b7b0dfc4..62aa65e2 100644
--- a/src/nfc/doc/snippets/doc_src_qtnfc.cpp
+++ b/src/nfc/doc/snippets/doc_src_qtnfc.cpp
@@ -38,11 +38,35 @@
**
****************************************************************************/
+#include <QtCore/QObject>
//! [include]
#include <QtNfc/QNearFieldManager>
//! [include]
+#include <QtNfc/QNdefMessage>
//! [namespace]
QT_USE_NAMESPACE
//! [namespace]
+class MyClass : public QObject
+{
+ Q_OBJECT
+public:
+ MyClass() : QObject()
+ {
+//formatting adjusted to improve usage in docs
+//! [handleNdefMessage]
+QNearFieldManager *manager = new QNearFieldManager(this);
+manager->registerNdefMessageHandler(this,
+ SLOT(handleNdefMessage(QNdefMessage,QNearFieldTarget*)));
+//! [handleNdefMessage]
+ }
+
+public Q_SLOTS:
+ void handleNdefMessage(QNdefMessage,QNearFieldTarget*)
+ {
+ }
+};
+
+#include "doc_src_qtnfc.moc"
+
diff --git a/src/nfc/doc/snippets/doc_src_qtnfc.pro b/src/nfc/doc/snippets/doc_src_qtnfc.pro
deleted file mode 100644
index 5730e227..00000000
--- a/src/nfc/doc/snippets/doc_src_qtnfc.pro
+++ /dev/null
@@ -1,51 +0,0 @@
-#****************************************************************************
-#*
-#* Copyright (C) 2013 Aaron McCarthy <mccarthy.aaron@gmail.com>
-#* Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-#* Contact: http://www.qt-project.org/legal
-#*
-#* This file is part of the documentation of the Qt Toolkit.
-#*
-#* $QT_BEGIN_LICENSE:BSD$
-#* You may use this file under the terms of the BSD license as follows:
-#*
-#* "Redistribution and use in source and binary forms, with or without
-#* modification, are permitted provided that the following conditions are
-#* met:
-#* * Redistributions of source code must retain the above copyright
-#* notice, this list of conditions and the following disclaimer.
-#* * Redistributions in binary form must reproduce the above copyright
-#* notice, this list of conditions and the following disclaimer in
-#* the documentation and/or other materials provided with the
-#* distribution.
-#* * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
-#* of its contributors may be used to endorse or promote products derived
-#* from this software without specific prior written permission.
-#*
-#*
-#* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-#* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-#* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-#* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-#* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-#* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-#* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-#* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-#* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-#* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-#* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-#*
-#* $QT_END_LICENSE$
-#*
-#***************************************************************************/
-
-#! [project modification]
-QT += nfc
-#! [project modification]
-
-SOURCES += main.cpp \
- doc_src_qtnfc.cpp \
- nfc.cpp \
- foorecord.cpp
-
-HEADERS += foorecord.h
diff --git a/src/nfc/doc/snippets/doc_src_qtnfc.qml b/src/nfc/doc/snippets/doc_src_qtnfc.qml
index 6c4d892d..427c24c6 100644
--- a/src/nfc/doc/snippets/doc_src_qtnfc.qml
+++ b/src/nfc/doc/snippets/doc_src_qtnfc.qml
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Aaron McCarthy <mccarthy.aaron@gmail.com>
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -42,4 +43,13 @@
import QtNfc 5.2
//! [import]
-Item { }
+Item {
+//! [QML register for messages]
+ NearField {
+ filter: [ NdefFilter { type: "U"; typeNameFormat: NdefRecord.NfcRtd; minimum: 1; maximum: 1 } ]
+ orderMatch: false
+
+ onMessageRecordsChanged: displayMessage()
+ }
+//! [QML register for messages]
+}
diff --git a/src/nfc/doc/snippets/snippets.pro b/src/nfc/doc/snippets/snippets.pro
new file mode 100644
index 00000000..437782e4
--- /dev/null
+++ b/src/nfc/doc/snippets/snippets.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = nfc_cppsnippet
+QT = core
+#! [project modification]
+QT += nfc
+#! [project modification]
+
+SOURCES += main.cpp \
+ doc_src_qtnfc.cpp \
+ nfc.cpp \
+ foorecord.cpp
+
+HEADERS += foorecord.h
diff --git a/src/nfc/doc/src/nfc-cpp.qdoc b/src/nfc/doc/src/nfc-cpp.qdoc
index 4df93e69..cbb07e0c 100644
--- a/src/nfc/doc/src/nfc-cpp.qdoc
+++ b/src/nfc/doc/src/nfc-cpp.qdoc
@@ -38,6 +38,6 @@ The \l{Qt NFC} C++ API enables an application to access NFC Forum Tags.
To use the C++ library in your application, add the following configuration
option to your \c .pro file:
-\snippet doc_src_qtnfc.pro project modification
+\snippet snippets.pro project modification
*/
diff --git a/src/nfc/doc/src/nfc-index.qdoc b/src/nfc/doc/src/nfc-index.qdoc
index 2ec40891..2944a6ab 100644
--- a/src/nfc/doc/src/nfc-index.qdoc
+++ b/src/nfc/doc/src/nfc-index.qdoc
@@ -38,12 +38,14 @@ The NFC API provides APIs for interacting with NFC Forum Tags and NFC Forum Devi
target detection and loss, registering NDEF message handlers, reading and writing NDEF messages
on NFC Forum Tags and sending tag specific commands.
+Currently the API is supported on BlackBerry 10.
+
\section1 Getting started
To use the C++ library in your application, add the following configuration
option to your \c .pro file:
-\snippet doc_src_qtnfc.pro project modification
+\snippet snippets.pro project modification
To use the classes of the module in your application you need the following
import statement in your \c .qml file:
diff --git a/src/nfc/doc/src/nfc-overview.qdoc b/src/nfc/doc/src/nfc-overview.qdoc
index b7d029bb..b068dfb5 100644
--- a/src/nfc/doc/src/nfc-overview.qdoc
+++ b/src/nfc/doc/src/nfc-overview.qdoc
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Aaron McCarthy <mccarthy.aaron@gmail.com>
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
@@ -36,14 +37,114 @@
With the Qt NFC API typical use cases are:
\list
- \li Detect NFC tags entering and leaving the communication range.
- \li Read and write NDEF message on NFC Forum Tags.
- \li Register an NDEF message handler for a particular content type.
+ \li Detecting NFC tags.
+ \li Reading and writing NDEF messages.
+ \li Registering NDEF message handlers.
+ \li Sharing files and messages.
\endlist
-The following sections describe how to use Qt NFC C++ classes for the above use cases.
+The following sections describe how to use Qt NFC C++ classes and QML types for the above use cases.
-\section1 Detect NFC tags entering and leaving communication range.
-\section1 Read and write an NDEF message on NFC Forum Tags.
-\section1 Register an NDEF message handler for a particular content type.
+\section1 C++ Overview
+
+The C++ API provides access to the full feature set of the Qt NFC API. This section introduces the
+major features available to developers.
+
+\section2 Detecting NFC Tags
+
+The \l QNearFieldManager class is responsible for the detection of new NFC tags coming
+into range of the device. The \l QNearFieldManager::targetDetected() and
+\l QNearFieldManager::targetLost() signals are emitted when
+a tag comes into or leaves the range. The passed \l QNearFieldTarget parameter acts
+as primary interaction point for each detected tag. The detection does not actually start though until
+\l QNearFieldManager::startTargetDetection() has been called.
+
+\snippet ndefeditor/mainwindow.cpp QNearFieldManager init
+\snippet ndefeditor/mainwindow.cpp QNearFieldManager start detection
+
+Finally the detection can be stopped:
+
+\snippet ndefeditor/mainwindow.cpp QNearFieldManager stop detection
+
+Although each \l QNearFieldTarget instance is owned by its related \l QNearFieldManager
+instance it can be beneficial to manually delete each instance. Otherwise they would continue to
+exist until the \l QNearFieldManager instance is deleted. The best way to do that would be in response
+to the \l QNearFieldManager::targetLost() signal:
+
+\snippet ndefeditor/mainwindow.cpp QNearFieldTarget lost
+
+\note The target object should only be deleted via deleteLater() if it is deleted inside the slot.
+
+\section2 Reading and Writing NDEF Messages
+
+The \l QNearFieldTarget instance returned by \l QNearFieldManager::targetDetected() signal
+is used to interact with the tag. Reading and writing a message is an asynchronous operation.
+The \l QNearFieldTarget::RequestId class associates individual operations and their results.
+
+\snippet ndefeditor/mainwindow.cpp QNearFieldTarget detected
+
+Once the \l QNearFieldTarget::readNdefMessages() request was successfully processed, the
+\l QNearFieldTarget::ndefMessageRead() signal is emitted. Each returned \l QNdefMessage
+may consist of zero or more \l QNdefRecord entries, which can be identified by their type.
+For more information about processing of records, see the \l QNdefRecord class documentation.
+As the above code demonstrates, writing of NDEF messages is triggered via
+\l QNearFieldTarget::writeNdefMessages(). The successful completion of the write operation
+is indicated by the emission of the \l QNearFieldTarget::ndefMessagesWritten() signal. Any
+type of error during read or write is indicated via \l QNearFieldTarget::error().
+
+\section2 Registering NDEF Message Handlers
+
+The above described method (of reading NDEF messages) directly connects to the platform's NFC infrastructure.
+However on some platforms (in particular mobile platforms) this may not actually trigger the target slot
+if the application is currently running in the background. This is not desirable in cases where an
+application wants to be activated if the platform detects a tag of particular type.
+For this purpose the Qt NFC API provides the possibility to register an NDEF message handler. The handler
+is called by the operating system, when the detected NDEF message matches the given filter criteria.
+Depending on the platform it may even be possible to start the application that registered the handler.
+
+\note This feature is not available on all platforms and, in addition to the code snippets below,
+may require further platform specific setup.
+
+\snippet annotatedurl/main.cpp QNearFieldManager register handler
+
+For comparison an application that uses an empty NDEF filter (match all behavior) in combination with
+\l QNearFieldManager::registerNdefMessageHandler() would behave similarly to another application that uses
+\l QNearFieldTarget::readNdefMessages() while being in the forground. For more information about
+registration details of NDEF message handlers, see the
+\l {QNearFieldManager#automatically-launching-ndef-message-handlers}{QNearFieldManager} class description.
+
+The content of \c handleMessage() may look like the snippet below. Any incoming NDEF message of type
+\c text or \c uri will be processed:
+
+\snippet annotatedurl/annotatedurl.cpp handleMessage 1
+\snippet annotatedurl/annotatedurl.cpp handleMessage 2
+\snippet annotatedurl/annotatedurl.cpp handleMessage 3
+\snippet annotatedurl/annotatedurl.cpp handleMessage 4
+
+\section2 Sharing Files and Messages
+
+Since Qt 5.3, Qt NFC provides a generic NFC share feature. If both devices support the same protocol,
+the feature can be used to share files or NDEF messages. The advantage is that the two involved partners
+can quickly establish a connection via NFC but transfer the data through, for example, Bluetooth or Wifi.
+Effectively, this combines the low configuration effort of NFC with high data rate communication bearers
+which usually require a much more complex setup.
+
+\note The API does not make any guarantees about the actual communication bearer used during the transfer.
+The bearer is chosen based on the device's capabilities and the properties of the to-be-shared data.
+
+\l QNearFieldShareManager and \l QNearFieldShareTarget are responsible for accessing the NFC share feature.
+
+\section1 QML Overview
+
+The QML API only supports a very small subset of the Qt NFC feature set. This section outlines the available QML features.
+
+\section2 Reading NDEF Messages
+
+The user can specify NDEF filters and use those filters to register for the automatic reception of NDEF
+messages which match those filters. The \l NearField::messageRecords property contains the list of NDEF records
+of the last NDEF message read matching the given filters.
+
+\snippet doc_src_qtnfc.qml QML register for messages
+
+If no filter is set, the message handler will match all incoming NDEF messages.
*/
diff --git a/src/nfc/qnearfieldmanager.cpp b/src/nfc/qnearfieldmanager.cpp
index f2fafdce..88656a6e 100644
--- a/src/nfc/qnearfieldmanager.cpp
+++ b/src/nfc/qnearfieldmanager.cpp
@@ -103,11 +103,7 @@ QT_BEGIN_NAMESPACE
If the application has been registered as an NDEF message handler, the application only needs
to call the registerNdefMessageHandler() function:
- \code
- QNearFieldManager *manager = new QNearFieldManager;
- manager->registerNdefMessageHandler(this,
- SLOT(handleNdefMessage(QNdefMessage,QNearFieldTarget)));
- \endcode
+ \snippet doc_src_qtnfc.cpp handleNdefMessage
On BlackBerry the registration for NDEF message handlers is done over the
\l{https://developer.blackberry.com/native/documentation/core/invocation_framework.html}{Invocation Framework}.
diff --git a/src/nfc/qnearfieldmanager_qnx.cpp b/src/nfc/qnearfieldmanager_qnx.cpp
index b09a6ed4..14dfc755 100644
--- a/src/nfc/qnearfieldmanager_qnx.cpp
+++ b/src/nfc/qnearfieldmanager_qnx.cpp
@@ -139,13 +139,13 @@ bool QNearFieldManagerPrivateImpl::unregisterNdefMessageHandler(int handlerId)
void QNearFieldManagerPrivateImpl::requestAccess(QNearFieldManager::TargetAccessModes accessModes)
{
Q_UNUSED(accessModes);
- //Do nothing, because we dont have access modes for the target
+ //Do nothing, because we don't have access modes for the target
}
void QNearFieldManagerPrivateImpl::releaseAccess(QNearFieldManager::TargetAccessModes accessModes)
{
Q_UNUSED(accessModes);
- //Do nothing, because we dont have access modes for the target
+ //Do nothing, because we don't have access modes for the target
}
void QNearFieldManagerPrivateImpl::handleMessage(const QNdefMessage &message, QNearFieldTarget *target)
diff --git a/src/nfc/qnearfieldsharemanager.cpp b/src/nfc/qnearfieldsharemanager.cpp
index b3e736b6..43b1634b 100644
--- a/src/nfc/qnearfieldsharemanager.cpp
+++ b/src/nfc/qnearfieldsharemanager.cpp
@@ -58,6 +58,7 @@ QT_BEGIN_NAMESPACE
\ingroup connectivity-nfc
\inmodule QtNfc
+ \since 5.3
Applications can share NDEF data or file content using NFC technology by tapping two NFC-enabled devices
together. The QNearFieldShareManager provides a high level entry point to access this functionality.
diff --git a/src/nfc/qnearfieldsharetarget.cpp b/src/nfc/qnearfieldsharetarget.cpp
index 9ac66c5c..606090b5 100644
--- a/src/nfc/qnearfieldsharetarget.cpp
+++ b/src/nfc/qnearfieldsharetarget.cpp
@@ -58,9 +58,12 @@ QT_BEGIN_NAMESPACE
\ingroup connectivity-nfc
\inmodule QtNfc
+ \since 5.3
The QNearFieldShareTarget class can be used for sharing NDEF message or files to a remote
NFC enabled device supporting the same protocol.
+
+ \sa QNearFieldShareManager
*/
/*!
diff --git a/src/nfc/qnearfieldtagtype3.cpp b/src/nfc/qnearfieldtagtype3.cpp
index b8cc89fe..8668dda4 100644
--- a/src/nfc/qnearfieldtagtype3.cpp
+++ b/src/nfc/qnearfieldtagtype3.cpp
@@ -109,7 +109,7 @@ QNearFieldTarget::RequestId QNearFieldTagType3::serviceData(quint16 serviceCode)
}
/*!
- Writes \a data to the the service specified by \a serviceCode. Returns a request id which can
+ Writes \a data to the service specified by \a serviceCode. Returns a request id which can
be used to track the completion status of the request.
Once the request completes the response can be retrieved from the requestResponse() function.
diff --git a/src/nfc/qnearfieldtarget_qnx_p.h b/src/nfc/qnearfieldtarget_qnx_p.h
index 789d8de5..faff94e2 100644
--- a/src/nfc/qnearfieldtarget_qnx_p.h
+++ b/src/nfc/qnearfieldtarget_qnx_p.h
@@ -147,7 +147,7 @@ public:
if (!isSupported) {
nfc_tag_supports_tag_type (m_target,TAG_TYPE_ISO_15693_3, &isSupported);
tagType = TAG_TYPE_ISO_15693_3;
- //We dont support this tag
+ //We don't support this tag
if (!isSupported) {
Q_EMIT QNearFieldTarget::error(QNearFieldTarget::UnsupportedError, QNearFieldTarget::RequestId());
return QNearFieldTarget::RequestId();
diff --git a/src/src.pro b/src/src.pro
index 47ab514a..e2ed3c88 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -1,6 +1,17 @@
TEMPLATE = subdirs
-CONFIG += ordered
SUBDIRS += bluetooth nfc
android: SUBDIRS += android
-qtHaveModule(quick): SUBDIRS += imports
+
+bluetooth_doc_snippets.subdir = bluetooth/doc/snippets
+bluetooth_doc_snippets.depends = bluetooth
+SUBDIRS += bluetooth_doc_snippets
+
+nfc_doc_snippets.subdir = nfc/doc/snippets
+nfc_doc_snippets.depends = nfc
+SUBDIRS += nfc_doc_snippets
+
+qtHaveModule(quick) {
+ imports.depends += bluetooth nfc
+ SUBDIRS += imports
+}