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. Show Push Notifications, while my app is in the background
Forum Updated to NodeBB v4.3 + New Features

Show Push Notifications, while my app is in the background

Scheduled Pinned Locked Moved Unsolved Mobile and Embedded
2 Posts 2 Posters 1.2k Views 1 Watching
  • 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.
  • R Offline
    R Offline
    Robin Hood
    wrote on last edited by
    #1

    Hi, at the beginning I work with QT Firebase
    I have following problem:
    If my application is closed, the messages are only displayed in the message bar. And when I press the message, my application starts, but it does not receive the message itself. What can I do to see the message in my application?

    If I receive a message while my app is in the background and I click on it, then "void MessageListener :: OnMessage (const messaging :: Message & message)" will be started, but "message.notification" will be "0x0". Only "message.notification_opened" is true, whereupon the string "launchnotification" is passed, but that is useless.

    I already have learned that this problem is in other Qt Firebase projects did not occur. I do not know where should I search.

    I think, that in qtfirebasemessaging.cpp or in Main.java is a bug.

    This is the file: "qtfirebasemessaging.cpp"

    //#include "qtfirebasemessaging.h"
    
    #include <QGuiApplication>
    #include <QQmlParserStatus>
    
    #include <stdint.h>
    #include "firebase/app.h"
    #include "firebase/internal/common.h"
    #include "firebase/messaging.h"
    #include "firebase/util.h"
    
    namespace messaging = ::firebase::messaging;
    
    QtFirebaseMessaging *QtFirebaseMessaging::self = nullptr;
    
    QtFirebaseMessaging::QtFirebaseMessaging(QObject* parent)
        : QObject(parent)
        , g_listener(new MessageListener())
    {
        __QTFIREBASE_ID = QString().sprintf("%8p", this);
    
        if(!self) {
            self = this;
            qDebug() << self << "::QtFirebaseMessaging" << "singleton";
        }
    
        _ready = false;
        _initializing = false;
    
        if(qFirebase->ready()) {
            //Call init outside of constructor, otherwise signal readyChanged not emited
            QTimer::singleShot(100, this, &QtFirebaseMessaging::init);
        } else {
            connect(qFirebase,&QtFirebase::readyChanged, this, &QtFirebaseMessaging::init);
            qFirebase->requestInit();
        }
    
        connect(qFirebase,&QtFirebase::futureEvent, this, &QtFirebaseMessaging::onFutureEvent);
    }
    
    QtFirebaseMessaging::~QtFirebaseMessaging()
    {
        if(_ready) {
            messaging::Terminate();
        }
    }
    
    void QtFirebaseMessaging::classBegin()
    {
    }
    
    void QtFirebaseMessaging::componentComplete()
    {
        // Connect on componentComplete so the signals are emited in the correct order
        connect(g_listener, &MessageListener::onMessageReceived, this, &QtFirebaseMessaging::getMessage);
        connect(g_listener, &MessageListener::onTokenReceived, this, &QtFirebaseMessaging::getToken);
    }
    
    bool QtFirebaseMessaging::checkInstance(const char *function)
    {
        const bool b = (QtFirebaseMessaging::self != nullptr);
        if (!b)
            qWarning("QtFirebaseMessaging::%s: Please instantiate the QtFirebaseMessaging object first", function);
        return b;
    }
    
    void QtFirebaseMessaging::init()
    {
        if(!qFirebase->ready()) {
            qDebug() << self << "::init" << "base not ready";
            return;
        }
    
        if(!_ready && !_initializing) {
            _initializing = true;
            messaging::Initialize(*qFirebase->firebaseApp(), g_listener);
            _initializing = false;
            setReady(true);
        }
    }
    
    void QtFirebaseMessaging::onFutureEvent(const QString &eventId, const firebase::FutureBase &future)
    {
        if(!eventId.startsWith(__QTFIREBASE_ID))
            return;
    
        qDebug() << self << "::onFutureEvent" << eventId;;
    
        if(future.status() != firebase::kFutureStatusComplete)
        {
            qDebug() << this << "::onFutureEvent initializing failed." << "ERROR: Action failed with error code and message: " << future.error() << future.error_message();
            _initializing = false;
            return;
        }
        qDebug() << this << "::onFutureEvent initialized ok";
        _initializing = false;
    }
    
    void QtFirebaseMessaging::getMessage()
    {
        setData(g_listener->data());
    }
    
    void QtFirebaseMessaging::getToken()
    {
        setToken(g_listener->token());
    }
    
    bool QtFirebaseMessaging::ready()
    {
        return _ready;
    }
    
    void QtFirebaseMessaging::setReady(bool ready)
    {
        if (_ready != ready) {
            _ready = ready;
            emit readyChanged();
        }
    }
    
    QVariantMap QtFirebaseMessaging::data()
    {
        return _data;
    }
    
    void QtFirebaseMessaging::setData(const QVariantMap &data)
    {
        if (_data != data) {
            _data = data;
            emit dataChanged();
            emit messageReceived();
        }
    }
    
    QString QtFirebaseMessaging::token()
    {
        return _token;
    }
    
    void QtFirebaseMessaging::setToken(const QString &token)
    {
        if (_token != token) {
            _token = token;
            emit tokenChanged();
        }
    }
    
    MessageListener::MessageListener(QObject* parent)
        : QObject(parent)
    {
    }
    
    void MessageListener::OnMessage(const messaging::Message &message)
    {
        // When messages are received by the server, they are placed into an
        // internal queue, waiting to be consumed. When ProcessMessages is called,
        // this OnMessage function is called once for each queued message.
    
        QVariantMap data;
    
        if (message.notification) {
            if (!message.notification->title.empty()) {
                const QString key = QStringLiteral("nTitle");
                const QString value = QString::fromStdString(message.notification->title.c_str());
                data.insert(key, value);
            }
            if (!message.notification->body.empty()) {
                const QString key = QStringLiteral("nBody");
                const QString value = QString::fromStdString(message.notification->body.c_str());
                data.insert(key, value);
            }
            if (!message.notification->icon.empty()) {
                const QString key = QStringLiteral("nIcon");
                const QString value = QString::fromStdString(message.notification->icon.c_str());
                data.insert(key, value);
            }
            if (!message.notification->tag.empty()) {
                const QString key = QStringLiteral("nTag");
                const QString value = QString::fromStdString(message.notification->tag.c_str());
                data.insert(key, value);
            }
            if (!message.notification->color.empty()) {
                const QString key = QStringLiteral("nColor");
                const QString value = QString::fromStdString(message.notification->color.c_str());
                data.insert(key, value);
            }
            if (!message.notification->sound.empty()) {
                const QString key = QStringLiteral("nSound");
                const QString value = QString::fromStdString(message.notification->sound.c_str());
                data.insert(key, value);
            }
            if (!message.notification->click_action.empty()) {
                const QString key = QStringLiteral("nClickAction");
                const QString value = QString::fromStdString(message.notification->click_action.c_str());
                data.insert(key, value);
            }
        }
    
        if (message.notification_opened) {
            const QString key = QStringLiteral("launchnotification");
            data.insert(key, true);
        }
    
        for (const auto& field : message.data)
        {
            const QString key = QString::fromStdString(field.first);
            const QString value = QString::fromStdString(field.second);
    
            data.insert(key, value);
        }
    
        setData(data);
    }
    
    void MessageListener::OnTokenReceived(const char *token)
    {
        setToken(QString::fromUtf8(token));
    }
    
    void MessageListener::connectNotify(const QMetaMethod &signal)
    {
        if (signal == QMetaMethod::fromSignal(&MessageListener::onMessageReceived)) {
            _messageReceivedConnected = true;
    
            if(_notifyMessageReceived) {
                emit onMessageReceived();
                _notifyMessageReceived = false;
            }
        }
    
        if (signal == QMetaMethod::fromSignal(&MessageListener::onTokenReceived)) {
            _tokenReceivedConnected = true;
    
            if(_notifyTokenReceived) {
                emit onTokenReceived();
                _notifyTokenReceived = false;
            }
        }
    }
    
    QVariantMap MessageListener::data()
    {
        return _data;
    }
    
    void MessageListener::setData(const QVariantMap &data)
    {
        if (_data != data) {
            _notifyMessageReceived = true;
            _data = data;
    
            if(_messageReceivedConnected) {
                emit onMessageReceived();
                _notifyMessageReceived = false;
            }
        }
    }
    
    QString MessageListener::token()
    {
        return _token;
    }
    
    void MessageListener::setToken(const QString &token)
    {
        if (_token != token) {
            _notifyTokenReceived = true;
            _token = token;
    
            if(_tokenReceivedConnected) {
                emit onTokenReceived();
                _notifyTokenReceived = false;
            }
        }
    }
    
    

    This is the file: "Main.java"

    //package com.blackgrain.android.firebasetest;
    
    import org.qtproject.qt5.android.bindings.QtApplication;
    import org.qtproject.qt5.android.bindings.QtActivity;
    
    import android.util.Log;
    import android.support.v7.app.AppCompatActivity;
    
    import android.view.WindowManager;
    
    // Messaging support
    import android.os.Bundle;
    import android.content.Intent;
    import com.google.firebase.messaging.MessageForwardingService;
    
    public class Main extends QtActivity {
    
        /** Called when the activity is first created. */
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    
        }
    
    
        /**
           * Messaging example
           */
        // The key in the intent's extras that maps to the incoming message's message ID. Only sent by
        // the server, GmsCore sends EXTRA_MESSAGE_ID_KEY below. Server can't send that as it would get
        // stripped by the client.
        private static final String EXTRA_MESSAGE_ID_KEY_SERVER = "message_id";
    
        // An alternate key value in the intent's extras that also maps to the incoming message's message
        // ID. Used by upstream, and set by GmsCore.
        private static final String EXTRA_MESSAGE_ID_KEY = "google.message_id";
    
        // The key in the intent's extras that maps to the incoming message's sender value.
        private static final String EXTRA_FROM = "google.message_id";
    
        /**
           * Workaround for when a message is sent containing both a Data and Notification payload.
           *
           * When the app is in the foreground all data payloads are sent to the method
           * `::firebase::messaging::Listener::OnMessage`. However, when the app is in the background, if a
           * message with both a data and notification payload is receieved the data payload is stored on
           * the notification Intent. NativeActivity does not provide native callbacks for onNewIntent, so
           * it cannot route the data payload that is stored in the Intent to the C++ function OnMessage. As
           * a workaround, we override onNewIntent so that it forwards the intent to the C++ library's
           * service which in turn forwards the data to the native C++ messaging library.
           */
        @Override
        protected void onNewIntent(Intent intent) {
            // If we do not have a 'from' field this intent was not a message and should not be handled. It
            // probably means this intent was fired by tapping on the app icon.
    
            // TODO
            Bundle extras = intent.getExtras();
            String from = extras.getString(EXTRA_FROM);
            String messageId = extras.getString(EXTRA_MESSAGE_ID_KEY);
    
            if (messageId == null) {
                messageId = extras.getString(EXTRA_MESSAGE_ID_KEY_SERVER);
            }
    
            if (from != null && messageId != null) {
                Intent message = new Intent(this, MessageForwardingService.class);
                message.setAction(MessageForwardingService.ACTION_REMOTE_INTENT);
                message.putExtras(intent);
                startService(message);
            }
            setIntent(intent);
    
        }
    
    }
    
    

    In additional here it calls that they have a solution for that. " ... As a workaround, we override onNewIntent so that it forwards the intent to the C++ library's service which in turn forwards the data to the native C++ messaging library."
    It may be that the function is simply not called?

    Please urgently for an answer. Thank you

    K 1 Reply Last reply
    0
    • R Robin Hood

      Hi, at the beginning I work with QT Firebase
      I have following problem:
      If my application is closed, the messages are only displayed in the message bar. And when I press the message, my application starts, but it does not receive the message itself. What can I do to see the message in my application?

      If I receive a message while my app is in the background and I click on it, then "void MessageListener :: OnMessage (const messaging :: Message & message)" will be started, but "message.notification" will be "0x0". Only "message.notification_opened" is true, whereupon the string "launchnotification" is passed, but that is useless.

      I already have learned that this problem is in other Qt Firebase projects did not occur. I do not know where should I search.

      I think, that in qtfirebasemessaging.cpp or in Main.java is a bug.

      This is the file: "qtfirebasemessaging.cpp"

      //#include "qtfirebasemessaging.h"
      
      #include <QGuiApplication>
      #include <QQmlParserStatus>
      
      #include <stdint.h>
      #include "firebase/app.h"
      #include "firebase/internal/common.h"
      #include "firebase/messaging.h"
      #include "firebase/util.h"
      
      namespace messaging = ::firebase::messaging;
      
      QtFirebaseMessaging *QtFirebaseMessaging::self = nullptr;
      
      QtFirebaseMessaging::QtFirebaseMessaging(QObject* parent)
          : QObject(parent)
          , g_listener(new MessageListener())
      {
          __QTFIREBASE_ID = QString().sprintf("%8p", this);
      
          if(!self) {
              self = this;
              qDebug() << self << "::QtFirebaseMessaging" << "singleton";
          }
      
          _ready = false;
          _initializing = false;
      
          if(qFirebase->ready()) {
              //Call init outside of constructor, otherwise signal readyChanged not emited
              QTimer::singleShot(100, this, &QtFirebaseMessaging::init);
          } else {
              connect(qFirebase,&QtFirebase::readyChanged, this, &QtFirebaseMessaging::init);
              qFirebase->requestInit();
          }
      
          connect(qFirebase,&QtFirebase::futureEvent, this, &QtFirebaseMessaging::onFutureEvent);
      }
      
      QtFirebaseMessaging::~QtFirebaseMessaging()
      {
          if(_ready) {
              messaging::Terminate();
          }
      }
      
      void QtFirebaseMessaging::classBegin()
      {
      }
      
      void QtFirebaseMessaging::componentComplete()
      {
          // Connect on componentComplete so the signals are emited in the correct order
          connect(g_listener, &MessageListener::onMessageReceived, this, &QtFirebaseMessaging::getMessage);
          connect(g_listener, &MessageListener::onTokenReceived, this, &QtFirebaseMessaging::getToken);
      }
      
      bool QtFirebaseMessaging::checkInstance(const char *function)
      {
          const bool b = (QtFirebaseMessaging::self != nullptr);
          if (!b)
              qWarning("QtFirebaseMessaging::%s: Please instantiate the QtFirebaseMessaging object first", function);
          return b;
      }
      
      void QtFirebaseMessaging::init()
      {
          if(!qFirebase->ready()) {
              qDebug() << self << "::init" << "base not ready";
              return;
          }
      
          if(!_ready && !_initializing) {
              _initializing = true;
              messaging::Initialize(*qFirebase->firebaseApp(), g_listener);
              _initializing = false;
              setReady(true);
          }
      }
      
      void QtFirebaseMessaging::onFutureEvent(const QString &eventId, const firebase::FutureBase &future)
      {
          if(!eventId.startsWith(__QTFIREBASE_ID))
              return;
      
          qDebug() << self << "::onFutureEvent" << eventId;;
      
          if(future.status() != firebase::kFutureStatusComplete)
          {
              qDebug() << this << "::onFutureEvent initializing failed." << "ERROR: Action failed with error code and message: " << future.error() << future.error_message();
              _initializing = false;
              return;
          }
          qDebug() << this << "::onFutureEvent initialized ok";
          _initializing = false;
      }
      
      void QtFirebaseMessaging::getMessage()
      {
          setData(g_listener->data());
      }
      
      void QtFirebaseMessaging::getToken()
      {
          setToken(g_listener->token());
      }
      
      bool QtFirebaseMessaging::ready()
      {
          return _ready;
      }
      
      void QtFirebaseMessaging::setReady(bool ready)
      {
          if (_ready != ready) {
              _ready = ready;
              emit readyChanged();
          }
      }
      
      QVariantMap QtFirebaseMessaging::data()
      {
          return _data;
      }
      
      void QtFirebaseMessaging::setData(const QVariantMap &data)
      {
          if (_data != data) {
              _data = data;
              emit dataChanged();
              emit messageReceived();
          }
      }
      
      QString QtFirebaseMessaging::token()
      {
          return _token;
      }
      
      void QtFirebaseMessaging::setToken(const QString &token)
      {
          if (_token != token) {
              _token = token;
              emit tokenChanged();
          }
      }
      
      MessageListener::MessageListener(QObject* parent)
          : QObject(parent)
      {
      }
      
      void MessageListener::OnMessage(const messaging::Message &message)
      {
          // When messages are received by the server, they are placed into an
          // internal queue, waiting to be consumed. When ProcessMessages is called,
          // this OnMessage function is called once for each queued message.
      
          QVariantMap data;
      
          if (message.notification) {
              if (!message.notification->title.empty()) {
                  const QString key = QStringLiteral("nTitle");
                  const QString value = QString::fromStdString(message.notification->title.c_str());
                  data.insert(key, value);
              }
              if (!message.notification->body.empty()) {
                  const QString key = QStringLiteral("nBody");
                  const QString value = QString::fromStdString(message.notification->body.c_str());
                  data.insert(key, value);
              }
              if (!message.notification->icon.empty()) {
                  const QString key = QStringLiteral("nIcon");
                  const QString value = QString::fromStdString(message.notification->icon.c_str());
                  data.insert(key, value);
              }
              if (!message.notification->tag.empty()) {
                  const QString key = QStringLiteral("nTag");
                  const QString value = QString::fromStdString(message.notification->tag.c_str());
                  data.insert(key, value);
              }
              if (!message.notification->color.empty()) {
                  const QString key = QStringLiteral("nColor");
                  const QString value = QString::fromStdString(message.notification->color.c_str());
                  data.insert(key, value);
              }
              if (!message.notification->sound.empty()) {
                  const QString key = QStringLiteral("nSound");
                  const QString value = QString::fromStdString(message.notification->sound.c_str());
                  data.insert(key, value);
              }
              if (!message.notification->click_action.empty()) {
                  const QString key = QStringLiteral("nClickAction");
                  const QString value = QString::fromStdString(message.notification->click_action.c_str());
                  data.insert(key, value);
              }
          }
      
          if (message.notification_opened) {
              const QString key = QStringLiteral("launchnotification");
              data.insert(key, true);
          }
      
          for (const auto& field : message.data)
          {
              const QString key = QString::fromStdString(field.first);
              const QString value = QString::fromStdString(field.second);
      
              data.insert(key, value);
          }
      
          setData(data);
      }
      
      void MessageListener::OnTokenReceived(const char *token)
      {
          setToken(QString::fromUtf8(token));
      }
      
      void MessageListener::connectNotify(const QMetaMethod &signal)
      {
          if (signal == QMetaMethod::fromSignal(&MessageListener::onMessageReceived)) {
              _messageReceivedConnected = true;
      
              if(_notifyMessageReceived) {
                  emit onMessageReceived();
                  _notifyMessageReceived = false;
              }
          }
      
          if (signal == QMetaMethod::fromSignal(&MessageListener::onTokenReceived)) {
              _tokenReceivedConnected = true;
      
              if(_notifyTokenReceived) {
                  emit onTokenReceived();
                  _notifyTokenReceived = false;
              }
          }
      }
      
      QVariantMap MessageListener::data()
      {
          return _data;
      }
      
      void MessageListener::setData(const QVariantMap &data)
      {
          if (_data != data) {
              _notifyMessageReceived = true;
              _data = data;
      
              if(_messageReceivedConnected) {
                  emit onMessageReceived();
                  _notifyMessageReceived = false;
              }
          }
      }
      
      QString MessageListener::token()
      {
          return _token;
      }
      
      void MessageListener::setToken(const QString &token)
      {
          if (_token != token) {
              _notifyTokenReceived = true;
              _token = token;
      
              if(_tokenReceivedConnected) {
                  emit onTokenReceived();
                  _notifyTokenReceived = false;
              }
          }
      }
      
      

      This is the file: "Main.java"

      //package com.blackgrain.android.firebasetest;
      
      import org.qtproject.qt5.android.bindings.QtApplication;
      import org.qtproject.qt5.android.bindings.QtActivity;
      
      import android.util.Log;
      import android.support.v7.app.AppCompatActivity;
      
      import android.view.WindowManager;
      
      // Messaging support
      import android.os.Bundle;
      import android.content.Intent;
      import com.google.firebase.messaging.MessageForwardingService;
      
      public class Main extends QtActivity {
      
          /** Called when the activity is first created. */
      
          @Override
          public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
      
              getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
      
          }
      
      
          /**
             * Messaging example
             */
          // The key in the intent's extras that maps to the incoming message's message ID. Only sent by
          // the server, GmsCore sends EXTRA_MESSAGE_ID_KEY below. Server can't send that as it would get
          // stripped by the client.
          private static final String EXTRA_MESSAGE_ID_KEY_SERVER = "message_id";
      
          // An alternate key value in the intent's extras that also maps to the incoming message's message
          // ID. Used by upstream, and set by GmsCore.
          private static final String EXTRA_MESSAGE_ID_KEY = "google.message_id";
      
          // The key in the intent's extras that maps to the incoming message's sender value.
          private static final String EXTRA_FROM = "google.message_id";
      
          /**
             * Workaround for when a message is sent containing both a Data and Notification payload.
             *
             * When the app is in the foreground all data payloads are sent to the method
             * `::firebase::messaging::Listener::OnMessage`. However, when the app is in the background, if a
             * message with both a data and notification payload is receieved the data payload is stored on
             * the notification Intent. NativeActivity does not provide native callbacks for onNewIntent, so
             * it cannot route the data payload that is stored in the Intent to the C++ function OnMessage. As
             * a workaround, we override onNewIntent so that it forwards the intent to the C++ library's
             * service which in turn forwards the data to the native C++ messaging library.
             */
          @Override
          protected void onNewIntent(Intent intent) {
              // If we do not have a 'from' field this intent was not a message and should not be handled. It
              // probably means this intent was fired by tapping on the app icon.
      
              // TODO
              Bundle extras = intent.getExtras();
              String from = extras.getString(EXTRA_FROM);
              String messageId = extras.getString(EXTRA_MESSAGE_ID_KEY);
      
              if (messageId == null) {
                  messageId = extras.getString(EXTRA_MESSAGE_ID_KEY_SERVER);
              }
      
              if (from != null && messageId != null) {
                  Intent message = new Intent(this, MessageForwardingService.class);
                  message.setAction(MessageForwardingService.ACTION_REMOTE_INTENT);
                  message.putExtras(intent);
                  startService(message);
              }
              setIntent(intent);
      
          }
      
      }
      
      

      In additional here it calls that they have a solution for that. " ... As a workaround, we override onNewIntent so that it forwards the intent to the C++ library's service which in turn forwards the data to the native C++ messaging library."
      It may be that the function is simply not called?

      Please urgently for an answer. Thank you

      K Offline
      K Offline
      koahnig
      wrote on last edited by
      #2

      @Robin-Hood

      You might want to follow this thread

      Vote the answer(s) that helped you to solve your issue(s)

      1 Reply Last reply
      2

      • Login

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