Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [Solved] Bluetooth list paired devices
QtWS25 Last Chance

[Solved] Bluetooth list paired devices

Scheduled Pinned Locked Moved General and Desktop
6 Posts 2 Posters 10.2k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    s.frings74
    wrote on 17 Sept 2014, 18:55 last edited by
    #1

    Sorry for asking such a simple question, but I'm really stuck finding the answer in the documentation.

    How can get a list of paired devices without starting the long discovery process?

    1 Reply Last reply
    0
    • S Offline
      S Offline
      s.frings74
      wrote on 26 Sept 2014, 19:02 last edited by
      #2

      It seems that the Bluez libraries don't provide that functionality , which may be the cause why QtBluetooth also does not provide it. Searching the web I found out that there should be a DBUS service which provides the list. However, that service is not available in Ubuntu (and maybe also other Linux distributions).

      There is a command-line tool called "bt-device" in the package "bluez-utils" which provides exactly the list that I was searching for. So I use that as long there is no direct support in QtBluetooth.

      @
      QMap<QString,QString> LinuxRfComm::getKnownDevices() {
      QMap<QString,QString> result;

      // Run the external Bluetooth program. Example of the output:
      // HC-06 (20:13:11:15:16:08)
      QProcess command;
      command.start("bt-device -l");
      command.waitForFinished(3000);
      QByteArray output=command.readAllStandardOutput();
      
      // Split the result
      QRegExp regexp("(.*) \\((.*)\\)");
      foreach(QByteArray line, output.split('\n')) {
          if (regexp.indexIn(line)>=0) {
              result.insert(regexp.cap(2),regexp.cap(1));
          }
      }
      
      qDebug("Found %i devices",result.size());
      return result;
      

      }
      @

      1 Reply Last reply
      0
      • S Offline
        S Offline
        s.frings74
        wrote on 26 Sept 2014, 19:04 last edited by
        #3

        Android does also provide this list, but only in the Java API. We can call it from Qt this way:

        @
        QMap<QString,QString> AndroidRfComm::getKnownDevices() {
        QMap<QString,QString> result;
        QAndroidJniObject pairedDevicesSet=adapter.callObjectMethod("getBondedDevices","()Ljava/util/Set;"); // Set<BluetoothDevice>
        check("BluetoothAdapter.getBondedDevices()",pairedDevicesSet);
        jint size=pairedDevicesSet.callMethod<jint>("size");
        check("Set<BluetoothDevice>.size()");
        qDebug("Found %i paired devices",size);
        if (size>0) {
        QAndroidJniObject iterator=pairedDevicesSet.callObjectMethod("iterator","()Ljava/util/Iterator;"); // Iterator<BluetoothDevice>
        check("Set<BluetoothDevice>.iterator()",iterator);
        for (int i=0; i<size; i++) {
        QAndroidJniObject dev=iterator.callObjectMethod("next","()Ljava/lang/Object;"); // BluetoothDevice
        check("Iterator<BluetoothDevice>.next()",dev);
        QString address=dev.callObjectMethod("getAddress","()Ljava/lang/String;").toString();
        QString name=dev.callObjectMethod("getName","()Ljava/lang/String;").toString();
        result.insert(address,name);
        }
        }
        return result;
        }
        @

        1 Reply Last reply
        0
        • J Offline
          J Offline
          jim4bs
          wrote on 8 Nov 2014, 09:16 last edited by
          #4

          Hi

          I'd like to use your JNI method in order to find a paired device address from a tablet. The reason is that I cannot figure out how to RFCOMM connect from a Samsung tablet to a COM/bluetooth board (testing device simulating a BT server). Qt Doc example is straitforward but with a paired Galaxy Tab3 ST110 (and same on NEXUS 4):

          _socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
          _socket->connectToService(remoteService)
          gives socket error 8 (unsupported protocol) !!!

          Question 1/ Did I miss something in Qt docs ? maybe I had to prepare the remoteService data structure in some way ?

          Question 2/ Qt offers a second way to RFCOMM connect that use the Bluetooth remote address and a UUID. Hence I would like to determine the address of paired device from my tablet. I used JNI long ago so could you please tell me about the following details in your code example

          2a) is the variable adapter declaration should be
          QAndroidJniObject adapter("android/bluetooth/BluetoothAdapter");

          2b) what is the check() method ? some verification ? could it be removed ?

          Thanks
          J

          1 Reply Last reply
          0
          • S Offline
            S Offline
            s.frings74
            wrote on 8 Nov 2014, 15:35 last edited by
            #5

            QBluetoothSocket has another method to connect with address and UUID instead of a service object. You will need this because the Java Interface returns only the name and address of the device.

            Do it this way:

            QBluetoothAddress("20:13:11:15:16:08");
            QString uuid("00001101-0000-1000-8000-00805F9B34FB");
            QBluetoothSocket* socket=new QBluetoothSocket(); socket->connectToService(QBluetoothAddress(btAddress),QBluetoothUuid(uuid));

            Here is a complete working program using only JNI that might be helpful http://stefanfrings.de/android_qt/AndroidBluetooth.zip

            Or another program that combines JNI with the Qt Bluetooth library: http://stefanfrings.de/avr_io/ioModule.zip

            You need to know the correct UUID. I found it with Google. You could also scan for devices and check out what's stored in the service object. It should always contain the device address and either a UUID or a port number. For my cases it turned out that the UUID is more universal because all devices use the same but different port numbers.

            Some phones/tablets simply don't support RFCOMM protocol. You may try any RFCOMM application from the Play Store to verify that. I can recommend: https://play.google.com/store/apps/details?id=mobi.dzs.android.BluetoothSPP&hl=de (It recommends to upgrade but that newer version doesn't work on my phone).

            I see the example source from my previous post is incomplete, it does not tell how to get the "adapter" object. The check method checks for exceptions as documented in http://qt-project.org/doc/qt-5/qandroidjniobject.html in the chapter Handling Java Exceptions.

            Now this is a more complete example:
            @
            QStringList IoModule::getBluetoothDevices() {
            QStringList result;
            QString fmt("%1 %2");

            #ifdef Q_OS_ANDROID
                // Query via Android Java API.
                QAndroidJniObject adapter=QAndroidJniObject::callStaticObjectMethod("android/bluetooth/BluetoothAdapter","getDefaultAdapter","()Landroid/bluetooth/BluetoothAdapter;"); // returns a BluetoothAdapter
                if (checkException("BluetoothAdapter.getDefaultAdapter()",&adapter)) {
                    return result;
                }
                QAndroidJniObject pairedDevicesSet=adapter.callObjectMethod("getBondedDevices","()Ljava/util/Set;"); // returns a Set<BluetoothDevice>
                if (checkException("BluetoothAdapter.getBondedDevices()",&pairedDevicesSet)) {
                    return result;
                }
                jint size=pairedDevicesSet.callMethod<jint>("size");
                checkException("Set<BluetoothDevice>.size()");
                if (size>0) {
                    QAndroidJniObject iterator=pairedDevicesSet.callObjectMethod("iterator","()Ljava/util/Iterator;"); // returns an Iterator<BluetoothDevice>
                    if (checkException("Set<BluetoothDevice>.iterator()",&iterator)) {
                        return result;
                    }
                    for (int i=0; i<size; i++) {
                        QAndroidJniObject dev=iterator.callObjectMethod("next","()Ljava/lang/Object;"); // returns a BluetoothDevice
                        if (checkException("Iterator<BluetoothDevice>.next()",&dev)) {
                            continue;
                        }
                        QString address=dev.callObjectMethod("getAddress","()Ljava/lang/String;").toString(); // returns a String
                        QString name=dev.callObjectMethod("getName","()Ljava/lang/String;").toString(); // returns a String
                        result.append(fmt.arg(address).arg(name));
                    }
                }
            
            #elif defined Q_OS_LINUX
                // Query via the Linux command bt-device.
                QProcess command;
                command.start("bt-device -l");
                command.waitForFinished(3000);
                if (command.error()==QProcess::FailedToStart) {
                    qWarning("Cannot execute the command 'bt-device': %s",qPrintable(command.errorString()));
                }
                else {
                    // Parse the output, example: HC-06 (20:13:11:15:16:08)
                    QByteArray output=command.readAllStandardOutput();
                    QRegExp regexp("(.*) \\((.*)\\)");
                    foreach(QByteArray line, output.split('\n')) {
                        if (regexp.indexIn(line)>=0) {
                            result.append(fmt.arg(regexp.cap(2)).arg(regexp.cap(1)));
                        }
                    }
                }
            #endif
            
            return result;
            

            }

            #ifdef Q_OS_ANDROID
            bool IoModule::checkException(const char* method, const QAndroidJniObject* obj) {
            static QAndroidJniEnvironment env;
            bool result=false;
            if (env->ExceptionCheck()) {
            qCritical("Exception in %s",method);
            env->ExceptionDescribe();
            env->ExceptionClear();
            result=true;
            }
            if (!(obj==NULL || obj->isValid())) {
            qCritical("Invalid object returned by %s",method);
            result=true;
            }
            return result;
            }
            #endif
            @

            If there is still something missing, checkout my two example programs (from above).

            1 Reply Last reply
            0
            • J Offline
              J Offline
              jim4bs
              wrote on 12 Nov 2014, 14:15 last edited by
              #6

              Hi
              Thanks you very much: I have used your Qt/JNI/Java method for getting the remote address of my paired device and apply strategy 2. As a result
              1/ I (your code) was successfull for retrieving the correct remode address
              2/ With the connectToService(address, sppUuid) strategy the tablet seems to connect (see trace below)

              Not definitly sure that SPP protocol is fully implemented on SAMSUNG Galaxy Tab3 Lite, I have to check in and out data now and I will report to you.

              Something more to note: if my tablet (client) tries to connect to early after remote board (server) power up it can be in Qt that the socket Connected Signal fires as well as Socket error signal and that the trace indicates at the same time "Service Not Found". Perhaps the SDP protocol is establihsed after the socket server at the remote side...

              AGAIN : Thanks you very much for your help !

              J

              D/Qt ( 7868): ..\src\bttalker.cpp:83 (BtTalker::BtTalker(QObject*)): client socket prepared
              D/Qt ( 7868): ..\src\bttalker.cpp:129 (void BtTalker::startClient(const QBluetoothServiceInfo&)): local adapter host mode: 1
              D/Qt ( 7868): ..\src\bttalker.cpp:158 (void BtTalker::startClient(const QBluetoothServiceInfo&)): remote paired device:
              D/Qt ( 7868): ..\src\bttalker.cpp:162 (void BtTalker::startClient(const QBluetoothServiceInfo&)): try to connect to "00:06:66:46:86:00" / "{00001101-0000-1000-8000-00805f9b34fb}"
              D/Qt ( 7868): ..\src\bttalker.cpp:167 (void BtTalker::startClient(const QBluetoothServiceInfo&)): Socket connected to RFCOMM service

              1 Reply Last reply
              0

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved