Show Push Notifications, while my app is in the background
-
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
-
You might want to follow this thread