Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. Can you suggest code to get my Android Client app to continue working when minimized?
Forum Updated to NodeBB v4.3 + New Features

Can you suggest code to get my Android Client app to continue working when minimized?

Scheduled Pinned Locked Moved Unsolved Mobile and Embedded
4 Posts 2 Posters 373 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
    SMEG
    wrote on last edited by
    #1

    Hello, I am trying to create apps that automatically synchronize clipboards between Android phones and linux computers that are on the same network. The server and client software I did for the linux computer work fine. I will add windows later and make it available for free.

    My problem is with the Android app on the phone. This app sends clipboard content to the serveur when phone clipboard has changed. It also update the phone clipboard when it receives a new one from the server. The problem is nothing works when the app is minimized. Re-opening the app after the phone clipboard has changed or for getting the clipboard from the linux computer becomes mandatory and annoying. I know it is a restriction from Android not to overload Phone's CPU.

    I have searched the internet to find a solution but found this is a very difficult problem for a newbie like me. Threads, processes, services, etc are no easy concepts.

    Can anyone give me a start on how to modify my code to resolve this problem?

    I am developing on Qt in C++ for Android.

    Thanks in advance, Marc.

    Here is all my code:

    the .h

    #ifndef FENCLIENT_H
    #define FENCLIENT_H
    
    #include <QtWidgets>
    #include <QtNetwork>
    #include <QClipboard>
    #include "ui_fenclient.h"
    
    
    class FenClient : public QWidget, private Ui::FenClient
    {
        Q_OBJECT
    
        public:
            FenClient();
    
        private slots:
            void on_boutonConnexion_clicked();
            void on_boutonEnvoyer_clicked();
            void on_message_returnPressed();
            void donneesRecues();
            void connecte();
            void deconnecte();
            void erreurSocket(QAbstractSocket::SocketError erreur);
            void copiage();
    
        private:
            QTcpSocket *socket; // Représente le serveur
            quint16 tailleMessage;
            QClipboard *clipBoard;
    
    };
    
    
    #endif // FENCLIENT_H
    

    the .cpp

    #include "fenclient.h"
    
    using namespace std;
    #include<iostream>
    #include <ostream>//sinon cout marche pas
    
    FenClient::FenClient()
    {
        setupUi(this);
    
        socket = new QTcpSocket(this);
        connect(socket, SIGNAL(readyRead()), this, SLOT(donneesRecues()));
        connect(socket, SIGNAL(connected()), this, SLOT(connecte()));
        connect(socket, SIGNAL(disconnected()), this, SLOT(deconnecte()));
        connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(erreurSocket(QAbstractSocket::SocketError)));
    
        tailleMessage = 0;
    
        clipBoard = QGuiApplication::clipboard();//Ca a été long mais il me faut ca...pas tout compris
        //QClipboard *clipBoard = QGuiApplication::clipboard();// Bad because it shadows FenClient::clipBoard
        connect(clipBoard, SIGNAL(dataChanged()), this, SLOT(copiage()));//serait mieux connect(clipBoard, &QClipboard::dataChanged, this, &FenClient::copiage);
    }
    
    // Tentative de connexion au serveur
    void FenClient::on_boutonConnexion_clicked()
    {
        // On annonce sur la fenêtre qu'on est en train de se connecter
        listeMessages->append(tr("<em>Tentative de connexion en cours...</em>"));
        boutonConnexion->setEnabled(false);
    
        socket->abort(); // On désactive les connexions précédentes s'il y en a
        socket->connectToHost(serveurIP->text(), serveurPort->value()); // On se connecte au serveur demandé
    }
    
    // Envoi d'un message au serveur
    void FenClient::on_boutonEnvoyer_clicked()
    {
        QByteArray paquet;
        QDataStream out(&paquet, QIODevice::WriteOnly);
    
        // On prépare le paquet à envoyer
        QString messageAEnvoyer = message->text();//on enlève tr("<strong>") + pseudo->text() +tr("</strong> : ") +
    
        out << (quint16) 0;
        out << messageAEnvoyer;
        out.device()->seek(0);
        out << (quint16) (paquet.size() - sizeof(quint16));
    
        socket->write(paquet); // On envoie le paquet
    
        message->clear(); // On vide la zone d'écriture du message
        message->setFocus(); // Et on remet le curseur à l'intérieur
    }
    
    // Appuyer sur la touche Entrée a le même effet que cliquer sur le bouton "Envoyer"
    void FenClient::on_message_returnPressed()
    {
        on_boutonEnvoyer_clicked();
    }
    
    // On a reçu un paquet (ou un sous-paquet)
    void FenClient::donneesRecues()
    {
        /* Même principe que lorsque le serveur reçoit un paquet :
        On essaie de récupérer la taille du message
        Une fois qu'on l'a, on attend d'avoir reçu le message entier (en se basant sur la taille annoncée tailleMessage)
        */
        QDataStream in(socket);
    
        if (tailleMessage == 0)
        {
            if (socket->bytesAvailable() < (int)sizeof(quint16))
                 return;
    
            in >> tailleMessage;
        }
    
        if (socket->bytesAvailable() < tailleMessage)
            return;
    
    
        // Si on arrive jusqu'à cette ligne, on peut récupérer le message entier
        QString messageRecu;
        in >> messageRecu;
    
        // On affiche le message sur la zone de Chat
        listeMessages->append(messageRecu);
    
        //clipBoard->disconnect();
        //disconnect(clipBoard, SIGNAL(dataChanged()), this, SLOT(copiage()));
        //on met dans le clipBoard
        //QObject::disconnect(clipBoard);//cela cause un changement du clipboard et ca marche pas
        cout << "Avant " << endl;
        QString temporaire=clipBoard->text();
        if (messageRecu == temporaire)
    
        {
        }
        else
            {
            clipBoard->QObject::blockSignals(true);
            clipBoard->setText(messageRecu);
            clipBoard->QObject::blockSignals(false);
            }
        //connect(clipBoard, SIGNAL(dataChanged()), this, SLOT(copiage()));
        cout << "Après " << endl;
    
        // On remet la taille du message à 0 pour pouvoir recevoir de futurs messages
        tailleMessage = 0;
    }
    
    // Ce slot est appelé lorsque la connexion au serveur a réussi
    void FenClient::connecte()
    {
        listeMessages->append(tr("<em>Connexion réussie !</em>"));
        boutonConnexion->setEnabled(true);
    }
    
    // Ce slot est appelé lorsqu'on est déconnecté du serveur
    void FenClient::deconnecte()
    {
        listeMessages->append(tr("<em>Déconnecté du serveur</em>"));
    }
    
    // Ce slot est appelé lorsqu'on que le presse-papiers change
    void FenClient::copiage()
    {   cout << "Copiage= " << endl;
    
        QString textCopie;
    
        //clipBoard->blockSignals(true);
        textCopie = clipBoard->text();
        //clipBoard->blockSignals(false);
    
        QByteArray paquet;
        QDataStream out(&paquet, QIODevice::WriteOnly);
    
        // On prépare le paquet à envoyer
        QString messageAEnvoyer = textCopie;
    
        out << (quint16) 0;
        out << messageAEnvoyer;
        out.device()->seek(0);
        out << (quint16) (paquet.size() - sizeof(quint16));
    
        socket->write(paquet); // On envoie le paquet
    
        //message->clear(); // On vide la zone d'écriture du message
        //message->setFocus(); // Et on remet le curseur à l'intérieur
    
    }
    
    
    
    // Ce slot est appelé lorsqu'il y a une erreur
    void FenClient::erreurSocket(QAbstractSocket::SocketError erreur)
    {
        switch(erreur) // On affiche un message différent selon l'erreur qu'on nous indique
        {
            case QAbstractSocket::HostNotFoundError:
                listeMessages->append(tr("<em>ERREUR : le serveur n'a pas pu être trouvé. Vérifiez l'IP et le port.</em>"));
                break;
            case QAbstractSocket::ConnectionRefusedError:
                listeMessages->append(tr("<em>ERREUR : le serveur a refusé la connexion. Vérifiez si le programme \"serveur\" a bien été lancé. Vérifiez aussi l'IP et le port.</em>"));
                break;
            case QAbstractSocket::RemoteHostClosedError:
                listeMessages->append(tr("<em>ERREUR : le serveur a coupé la connexion.</em>"));
                break;
            default:
                listeMessages->append(tr("<em>ERREUR : ") + socket->errorString() + tr("</em>"));
        }
    
        boutonConnexion->setEnabled(true);
    }
    

    the main.cpp

    #include <QApplication>
    #include "fenclient.h"
    
    int main(int argc, char* argv[])
    {
        QApplication app(argc, argv);
    
        FenClient fenetre;
        fenetre.show();
    
        return app.exec();
    }
    
    
    jsulmJ 1 Reply Last reply
    0
    • S SMEG

      Hello, I am trying to create apps that automatically synchronize clipboards between Android phones and linux computers that are on the same network. The server and client software I did for the linux computer work fine. I will add windows later and make it available for free.

      My problem is with the Android app on the phone. This app sends clipboard content to the serveur when phone clipboard has changed. It also update the phone clipboard when it receives a new one from the server. The problem is nothing works when the app is minimized. Re-opening the app after the phone clipboard has changed or for getting the clipboard from the linux computer becomes mandatory and annoying. I know it is a restriction from Android not to overload Phone's CPU.

      I have searched the internet to find a solution but found this is a very difficult problem for a newbie like me. Threads, processes, services, etc are no easy concepts.

      Can anyone give me a start on how to modify my code to resolve this problem?

      I am developing on Qt in C++ for Android.

      Thanks in advance, Marc.

      Here is all my code:

      the .h

      #ifndef FENCLIENT_H
      #define FENCLIENT_H
      
      #include <QtWidgets>
      #include <QtNetwork>
      #include <QClipboard>
      #include "ui_fenclient.h"
      
      
      class FenClient : public QWidget, private Ui::FenClient
      {
          Q_OBJECT
      
          public:
              FenClient();
      
          private slots:
              void on_boutonConnexion_clicked();
              void on_boutonEnvoyer_clicked();
              void on_message_returnPressed();
              void donneesRecues();
              void connecte();
              void deconnecte();
              void erreurSocket(QAbstractSocket::SocketError erreur);
              void copiage();
      
          private:
              QTcpSocket *socket; // Représente le serveur
              quint16 tailleMessage;
              QClipboard *clipBoard;
      
      };
      
      
      #endif // FENCLIENT_H
      

      the .cpp

      #include "fenclient.h"
      
      using namespace std;
      #include<iostream>
      #include <ostream>//sinon cout marche pas
      
      FenClient::FenClient()
      {
          setupUi(this);
      
          socket = new QTcpSocket(this);
          connect(socket, SIGNAL(readyRead()), this, SLOT(donneesRecues()));
          connect(socket, SIGNAL(connected()), this, SLOT(connecte()));
          connect(socket, SIGNAL(disconnected()), this, SLOT(deconnecte()));
          connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(erreurSocket(QAbstractSocket::SocketError)));
      
          tailleMessage = 0;
      
          clipBoard = QGuiApplication::clipboard();//Ca a été long mais il me faut ca...pas tout compris
          //QClipboard *clipBoard = QGuiApplication::clipboard();// Bad because it shadows FenClient::clipBoard
          connect(clipBoard, SIGNAL(dataChanged()), this, SLOT(copiage()));//serait mieux connect(clipBoard, &QClipboard::dataChanged, this, &FenClient::copiage);
      }
      
      // Tentative de connexion au serveur
      void FenClient::on_boutonConnexion_clicked()
      {
          // On annonce sur la fenêtre qu'on est en train de se connecter
          listeMessages->append(tr("<em>Tentative de connexion en cours...</em>"));
          boutonConnexion->setEnabled(false);
      
          socket->abort(); // On désactive les connexions précédentes s'il y en a
          socket->connectToHost(serveurIP->text(), serveurPort->value()); // On se connecte au serveur demandé
      }
      
      // Envoi d'un message au serveur
      void FenClient::on_boutonEnvoyer_clicked()
      {
          QByteArray paquet;
          QDataStream out(&paquet, QIODevice::WriteOnly);
      
          // On prépare le paquet à envoyer
          QString messageAEnvoyer = message->text();//on enlève tr("<strong>") + pseudo->text() +tr("</strong> : ") +
      
          out << (quint16) 0;
          out << messageAEnvoyer;
          out.device()->seek(0);
          out << (quint16) (paquet.size() - sizeof(quint16));
      
          socket->write(paquet); // On envoie le paquet
      
          message->clear(); // On vide la zone d'écriture du message
          message->setFocus(); // Et on remet le curseur à l'intérieur
      }
      
      // Appuyer sur la touche Entrée a le même effet que cliquer sur le bouton "Envoyer"
      void FenClient::on_message_returnPressed()
      {
          on_boutonEnvoyer_clicked();
      }
      
      // On a reçu un paquet (ou un sous-paquet)
      void FenClient::donneesRecues()
      {
          /* Même principe que lorsque le serveur reçoit un paquet :
          On essaie de récupérer la taille du message
          Une fois qu'on l'a, on attend d'avoir reçu le message entier (en se basant sur la taille annoncée tailleMessage)
          */
          QDataStream in(socket);
      
          if (tailleMessage == 0)
          {
              if (socket->bytesAvailable() < (int)sizeof(quint16))
                   return;
      
              in >> tailleMessage;
          }
      
          if (socket->bytesAvailable() < tailleMessage)
              return;
      
      
          // Si on arrive jusqu'à cette ligne, on peut récupérer le message entier
          QString messageRecu;
          in >> messageRecu;
      
          // On affiche le message sur la zone de Chat
          listeMessages->append(messageRecu);
      
          //clipBoard->disconnect();
          //disconnect(clipBoard, SIGNAL(dataChanged()), this, SLOT(copiage()));
          //on met dans le clipBoard
          //QObject::disconnect(clipBoard);//cela cause un changement du clipboard et ca marche pas
          cout << "Avant " << endl;
          QString temporaire=clipBoard->text();
          if (messageRecu == temporaire)
      
          {
          }
          else
              {
              clipBoard->QObject::blockSignals(true);
              clipBoard->setText(messageRecu);
              clipBoard->QObject::blockSignals(false);
              }
          //connect(clipBoard, SIGNAL(dataChanged()), this, SLOT(copiage()));
          cout << "Après " << endl;
      
          // On remet la taille du message à 0 pour pouvoir recevoir de futurs messages
          tailleMessage = 0;
      }
      
      // Ce slot est appelé lorsque la connexion au serveur a réussi
      void FenClient::connecte()
      {
          listeMessages->append(tr("<em>Connexion réussie !</em>"));
          boutonConnexion->setEnabled(true);
      }
      
      // Ce slot est appelé lorsqu'on est déconnecté du serveur
      void FenClient::deconnecte()
      {
          listeMessages->append(tr("<em>Déconnecté du serveur</em>"));
      }
      
      // Ce slot est appelé lorsqu'on que le presse-papiers change
      void FenClient::copiage()
      {   cout << "Copiage= " << endl;
      
          QString textCopie;
      
          //clipBoard->blockSignals(true);
          textCopie = clipBoard->text();
          //clipBoard->blockSignals(false);
      
          QByteArray paquet;
          QDataStream out(&paquet, QIODevice::WriteOnly);
      
          // On prépare le paquet à envoyer
          QString messageAEnvoyer = textCopie;
      
          out << (quint16) 0;
          out << messageAEnvoyer;
          out.device()->seek(0);
          out << (quint16) (paquet.size() - sizeof(quint16));
      
          socket->write(paquet); // On envoie le paquet
      
          //message->clear(); // On vide la zone d'écriture du message
          //message->setFocus(); // Et on remet le curseur à l'intérieur
      
      }
      
      
      
      // Ce slot est appelé lorsqu'il y a une erreur
      void FenClient::erreurSocket(QAbstractSocket::SocketError erreur)
      {
          switch(erreur) // On affiche un message différent selon l'erreur qu'on nous indique
          {
              case QAbstractSocket::HostNotFoundError:
                  listeMessages->append(tr("<em>ERREUR : le serveur n'a pas pu être trouvé. Vérifiez l'IP et le port.</em>"));
                  break;
              case QAbstractSocket::ConnectionRefusedError:
                  listeMessages->append(tr("<em>ERREUR : le serveur a refusé la connexion. Vérifiez si le programme \"serveur\" a bien été lancé. Vérifiez aussi l'IP et le port.</em>"));
                  break;
              case QAbstractSocket::RemoteHostClosedError:
                  listeMessages->append(tr("<em>ERREUR : le serveur a coupé la connexion.</em>"));
                  break;
              default:
                  listeMessages->append(tr("<em>ERREUR : ") + socket->errorString() + tr("</em>"));
          }
      
          boutonConnexion->setEnabled(true);
      }
      

      the main.cpp

      #include <QApplication>
      #include "fenclient.h"
      
      int main(int argc, char* argv[])
      {
          QApplication app(argc, argv);
      
          FenClient fenetre;
          fenetre.show();
      
          return app.exec();
      }
      
      
      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @SMEG You will need to create a background service, there is no other way.
      See https://doc.qt.io/qt-5/android-services.html

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      S 1 Reply Last reply
      3
      • jsulmJ jsulm

        @SMEG You will need to create a background service, there is no other way.
        See https://doc.qt.io/qt-5/android-services.html

        S Offline
        S Offline
        SMEG
        wrote on last edited by
        #3

        @jsulm

        Hello,
        Following you recommendation, I was able to add an Android manifest file to my project. Now I am trying to follow the steps described here: https://www.kdab.com/qt-android-create-android-service-using-qt/
        but I block right at the first step!
        It is not clear to me where the author is asking to put these lines of code:

        package com.kdab.training;
        import org.qtproject.qt5.android.bindings.QtService;
        public class MyService extends QtService
        {
        }
        

        Can you tell me where these lines should go?
        It seems the project needs a java file somewhere but I have no clue about where.
        Thanks for your help.

        jsulmJ 1 Reply Last reply
        0
        • S SMEG

          @jsulm

          Hello,
          Following you recommendation, I was able to add an Android manifest file to my project. Now I am trying to follow the steps described here: https://www.kdab.com/qt-android-create-android-service-using-qt/
          but I block right at the first step!
          It is not clear to me where the author is asking to put these lines of code:

          package com.kdab.training;
          import org.qtproject.qt5.android.bindings.QtService;
          public class MyService extends QtService
          {
          }
          

          Can you tell me where these lines should go?
          It seems the project needs a java file somewhere but I have no clue about where.
          Thanks for your help.

          jsulmJ Offline
          jsulmJ Offline
          jsulm
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @SMEG In the article you link there is a link to whole source code of that example project: https://github.com/KDAB/android

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          3

          • Login

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