Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Bluetooth Socket For Android



  • Hello everyone,

    I'm currently developing an embedded system with a Raspberry Pi 3 B+ (GCC C program with Bluez) & Android App (Qt C++/QML) connected via Bluetooth. I have got bi-directional communication working with RFCOMM and Serial Port Profile. However, the user currently has to click a connect button, wait for the connection to accept on the Pi, then click a separate send button to actually write to the socket; I'm trying to automate this.

    However, if I simply call my sendBluetooth() function at the end of my connectBluetooth() function, apparently the device is not open. I have also tried putting the entire sendBluetooth() function inside my connectBluetooth() function, but I get the same error. If I click on the connect button (which just runs the connectBluetooth() function), then the send button (which just runs the sendBluetooth() function), it works, so I'm not sure what exactly is going on here!

    Any help would be appreciated! I'm not sure if it's something in the header file, or something I'm doing fundamentally wrong. I have also tried putting a loop in the sendBluetooth() function, to keep sending the message in case it doesn't connect in time, but still fails.

    Qt 5.13.2 on Windows 10 compiling for Android Note 7P (Android 9) with C++/QML.

    // backend.cpp
    #include "backend.h"
    #include <QDebug>
    #include <QString>
    #include <QThread>
    #include <QProcess>
    #include <QtCore>
    #include <QtBluetooth>
    #include <unistd.h>
    #include <stdio.h>
    
    BackEnd::BackEnd(QObject *parent) :
        QObject(parent)
    {
    qDebug("INITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINIT");
    setLastName("Hi");
    setConnectionStatus("Waiting or User Selection...");
    }
    
    QString BackEnd::connectionStatus()
    {
        return m_connectionStatus;
    }
    
    QString BackEnd::lastName()
    {
        return m_lastName;
    }
    
    void BackEnd::setConnectionStatus(const QString &connectionStatus)
    {
        if (connectionStatus == m_connectionStatus)
            return;
    
        m_connectionStatus = connectionStatus;
        emit connectionStatusChanged();
        qDebug("emit connectionStatusChanged()");
    }
    
    void BackEnd::setLastName(const QString &lastName)
    {
        if (lastName == m_lastName)
            return;
    
        m_lastName = lastName;
        emit lastNameChanged();
        qDebug("emit lastNameChanged()");
    }
    
    void BackEnd::selectBluetooth() // Removed from QML, button goes straight to connectBluetooth() now
    {
    qDebug("SELECT BLUETOOTH ()");
    setConnectionStatus("Initializing Connection...");
    connectBluetooth();
    }
    
    void BackEnd::selectWifi()
    {
    qDebug("SELECT WIFI ()");
    }
    
    void BackEnd::connectBluetooth()
    {
    qDebug("connectBluetooth() has been run!");
    qDebug("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Connecting to Bluetooth");
    
    int numberOfAttempts = 0;
    
            if (numberOfAttempts >= 5)
            {
                qDebug("Bluetooth connect failed 5 times, show error message and stop loop!");
                setConnectionStatus("Bluetooth connect failed 5 times. Please close and retry the app!");
                socket->close();
                return;
            }
            else if (numberOfAttempts > 0)
                qDebug("Bluetooth connect failed, attempting again...!");
            setConnectionStatus("Could not connect to Bluetooth, trying again...");
    
            connect(agent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
                    this, SLOT(deviceDiscovered(QBluetoothDeviceInfo)));
    
            qDebug("Starting Bluetooth Agent...");
            numberOfAttempts++;
            agent->start(); //Start Bluetooth Agent
            setConnectionStatus("Bluetooth Agent Started...");
            qDebug("Agent Started,  Creating");
            socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
            setConnectionStatus("Connecting to Service...");
            qDebug("Connecting to Service...");
    
            static const QString serviceUuid(QStringLiteral("00001101-0000-1000-8000-00805F9B34FB")); // Normal Service UUID
    
       socket->connectToService(QBluetoothAddress("B8:27:EB:60:8F:84"), QBluetoothUuid(serviceUuid), QIODevice::ReadWrite); 
    
    qDebug("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@CONNECT Bluetooth Function Finished.");
    
    //socket->waitForReadyRead(10000);
    qDebug("Running sendBluetooth().....");
    sendBluetooth();
    }
    
    void BackEnd::sendBluetooth()
    {
     qDebug("sendBluetooth() has been run!");
        qDebug("HEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHERE");
    
     sleep(2);
    
        /*while ( socket->state() != QBluetoothSocket::ConnectedState )
            {
                qDebug() << "sendBluetooth(): Bluetooth not in connected state!";
                sleep(1);
            }
        qDebug("socket->state() == Connected.");*/
    
        char astring[] = "1,1,1,1";
        char *ptrToString = astring; //work
    
      int writeStatus = 0;
    
      writeStatus = socket->write(ptrToString, 128);
     qDebug("writeStatus: %d",writeStatus);
    
    qDebug("COMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETE");
    }
    
    // backend.h
    #ifndef BACKEND_H
    #define BACKEND_H
    
    #include <QObject>
    #include <QString>
    #include <QBluetoothSocket>
    #include <QBluetoothDeviceDiscoveryAgent>
    #include <QDebug>
    
    class BackEnd : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QString connectionStatus READ connectionStatus WRITE setConnectionStatus NOTIFY connectionStatusChanged)
        Q_PROPERTY(QString lastName READ lastName WRITE setLastName NOTIFY lastNameChanged)
    
    public:
        explicit BackEnd(QObject *parent = nullptr);
        QString connectionStatus();
        QString lastName();
        void setConnectionStatus(const QString &connectionStatus);
        void setLastName(const QString &lastName);
        QBluetoothDeviceDiscoveryAgent *agent = new QBluetoothDeviceDiscoveryAgent;
        QBluetoothSocket *socket;
    
    signals:
        void connectionStatusChanged();
        void lastNameChanged();
        void connectClicked();
        void sendClicked();
        void selectBluetooth();
        void selectWifi();
           
    private:
        QString string;
        QString m_connectionStatus;
        QString m_lastName;
    
    public slots:
        void connectBluetooth();    
        void sendBluetooth();
        void deviceDiscovered(QBluetoothDeviceInfo);
    };
    #endif // BACKEND_H
    
    // main.cpp
    
    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include <QQuickView>
    #include "backend.h"
    
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
    
        qmlRegisterType<BackEnd>("io.qt.examples.backend", 1, 0, "BackEnd"); // QML > C++
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        return app.exec();
    }
    
    // main.qml
    import QtQuick 2.9
    import QtGraphicalEffects 1.12
    import QtQuick.Window 2.2
    //import QtQuick.Controls 2.0
    //import QtQuick.Controls 2.13
    import QtQuick.Controls 2.12
    import io.qt.examples.backend 1.0
    import QtQuick.Layouts 1.11
    
    ApplicationWindow
    {
        id: root
        color: "#000000"
        visible: true
    
        property int home: 0
        property int loadingBluetooth: 1
        property int loadingWifi: 2
        property int connectedBluetooth: 3
    
        function pageToShow (page) {
            switch (page) {
    
            case home:
                buttonBluetooth.opacity = 1;
                buttonWifi.opacity = 1;
                rectangleLoading.opacity = 0;
                rectangleConnected.opacity = 0;
                break;
    
            case loadingBluetooth:
                buttonBluetooth.opacity = 0;
                buttonWifi.opacity = 0;
                rectangleLoading.opacity = 1;
                break;
    
            case loadingWifi:
                buttonBluetooth.opacity = 0;
                buttonWifi.opacity = 0;
                break;
    
            case connectedBluetooth:
                 rectangleLoading.opacity = 0;
                rectangleConnected.opacity = 1;
                break;
            }
        }
    
        BackEnd
        {
            id: backend
        }
    
        Button {
            id: buttonBluetooth
            x: 13
            y: 55
            width: 147
            height: 132
            text: qsTr("Bluetooth")
            onClicked:{
                backend.connectBluetooth()
                //backend.keepAlive()
                pageToShow(loadingBluetooth)
            }
        }
    
        Button {
            id: buttonWifi
            x: 242
            y: 55
            width: 147
            height: 132
            text: qsTr("Wifi")
            onClicked: {
                backend.selectWifi()
                pageToShow(loadingWifi)
            }
        }
    
        Button {
            id: buttonReset
            x: 239
            y: 207
            width: 150
            height: 40
            text: qsTr("Reset")
            onClicked: {
                print("Reset button pressed.")
                pageToShow(home)
            }
        }
    
        Rectangle {
            id: rectangleLoading
            x: 30
            y: 168
            width: 112
            height: 79
            color: "#c8c8c8"
            opacity: 0
            z: 1
    
            BusyIndicator {
                id: busyIndicator
                x: 26
                y: 19
                z:2
            }
    
            Label {
                id: label
                x: 24
                y: 3
                text: qsTr("Connecting...")
            }
        }
    
        Rectangle {
            id: rectangleConnected
            x: 30
            y: 266
            width: 112
            height: 79
            color: "#c8c8c8"
    
            Label {
                id: label1
                x: 24
                y: 3
                text: qsTr("Connected!")
            }
            z: 1
            opacity: 0
        }
    
        TextField {
            id: textField
            x: 13
            y: 207
            text: qsTr("Text Field")
        }
    
        // this function is our QML slot
        function setTextField(text){
            console.log("setTextField: " + text)
            textField1.text = text
        }
    
        Text {
            id: username
            width: 292
            height: 30
            color: "#fffff3"
            text: backend.connectionStatus
            opacity: 1
            anchors.verticalCenterOffset: -109
            anchors.horizontalCenterOffset: -41
            anchors.centerIn: parent
    
            onTextChanged: backend.connectionStatus = text
        }
    
        Text {
            id: lastname
            x: -4
            y: 4
            width: 120
            height: 30
            color: "#ffff00"
            text: backend.lastName
            opacity: 1
            anchors.verticalCenterOffset: -60
            anchors.horizontalCenterOffset: -127
            anchors.centerIn: parent
            onTextChanged: backend.lastName = text
        }
    
        Label {
            id: label2
            x: 13
            y: 25
            width: 107
            height: 18
            color: "#ebfa3c"
            text: qsTr("Drink Selected")
        }
    
        Button {
            id: sendDebug
            x: 239
            y: 266
            width: 150
            height: 40
            text: qsTr("Send Debug")
            onClicked: {
             backend.sendBluetooth()
            }
        }
    } // Application Window