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

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
  • 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 17 Sept 2018, 12:16 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 17 Sept 2018, 12:25
    0
    • R Robin Hood
      17 Sept 2018, 12:16

      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 17 Sept 2018, 12:25 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

      1/2

      17 Sept 2018, 12:16

      • Login

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