WebEngine Push-Benachrichtigungen Beispiel
Zeigt, wie man sich für Push-Benachrichtigungen anmeldet und sie abmeldet.
In diesem Beispiel werden wir Push-Benachrichtigungen von einem Web-Push-Dienst an den Benutzer senden. Dies ist ein typisches Szenario, bei dem Nachrichten vom Anwendungsserver, d. h. dem Website-Backend, über einen Push-Dienst eines Drittanbieters gesendet werden, um schließlich in Form von Benachrichtigungen im Browser des Benutzers anzukommen. Zur Veranschaulichung dieses Ablaufs werden wir eine einfache Push-Service-Server-Anwendung implementieren, bei der sich der Benutzer für den Empfang von Ping-Nachrichten anmelden kann.
Wie bereits erwähnt, sind an einem solchen Arbeitsablauf drei verschiedene Parteien beteiligt:
- der Webbrowser des Benutzers, in dem er Push-Benachrichtigungen empfängt
- der Push-Dienst eines Drittanbieters, der durch einen Abonnement-Endpunkt definiert wird und Teil der Push-Dienst-Implementierung eines Browsers ist
- Anwendungsserver, der die Abonnements des Nutzers speichert und Push-Nachrichten über einen Abonnement-Endpunkt initiiert
Der Benutzer besucht eine Website, auf der eine JavaScript-Webanwendung die JavaScript-Push-API verwendet, um ein Abonnement für Push-Benachrichtigungen zu erstellen. Der Benutzer wird dann gebeten, eine Genehmigung für den Empfang und die Anzeige von Push-Benachrichtigungen zu erteilen. Sobald die Genehmigung erteilt ist, richtet die Push-API einen Push-Kanal mit einem Push-Dienst eines Drittanbieters ein, im Fall von QtWebEngine ist dies Firebase Cloud Messaging (FCM). Es wird ein eindeutiges Push-Abonnement erstellt, das die URL des Abonnement-Endpunkts enthält. Der Browser sendet dann eine Abonnementnachricht an den Anwendungsserver und leitet die Endpunkteinrichtung weiter. Der Anwendungsserver kann nun den Abonnement-Endpunkt verwenden, um Benachrichtigungen an den Browser zu senden. Die Implementierung des Browser-Push-Dienstes liefert eine Push-Nachricht. Um sie anzuzeigen, muss jedoch ein Service Worker registriert werden. Da der Service Worker im Hintergrund läuft, können die Benachrichtigungen auch dann angezeigt werden, wenn die Website, auf der er installiert wurde, nicht mehr geöffnet ist.
Gehen wir nun näher auf die Implementierung ein. Wir beginnen mit der Implementierung unseres benutzerdefinierten Push-Dienstes unter Verwendung von NodeJS mit zwei Modulen:
- web-push - stellt die Implementierung des Web-Push-Protokolls bereit
- express - stellt das Webanwendungs-Framework bereit
Initialisieren wir ein neues Projekt und installieren die erforderlichen Module im Stammverzeichnis dieses Beispiels:
npm init -y npm install web-push express
Diese Befehle sollten package.js erstellen, die den Startbefehl definiert:
"start": "node server.js"
Gehen wir nun zur Implementierung des Push-Service-Backends in server.js über.
Wir beginnen mit der Einbindung der erforderlichen Module und der grundlegenden Einrichtung des Express-Frameworks, das wir zur Erstellung unseres benutzerdefinierten Push-Servers verwenden. Der Einfachheit halber werden wir jeweils nur ein Abonnement bearbeiten. Dazu müssen wir VAPID-Schlüssel erstellen, die wir mit den Web-Push-Libs generieren werden. Der öffentliche Schlüssel wird vom Front-End verwendet, um sich beim Dienst zu authentifizieren.
const express = require('express'); const webpush = require('web-push'); // setup server const port = 5000; const server = express(); server.use(express.json()); server.use(express.static('content')); // we support only one subscription at the time var subscription = null; // setup vapid keys const vapidKeys = { publicKey : "BNO4fIv439RpvbReeABNlDNiiBD2Maykn7EVnwsPseH7-P5hjnzZLEfnejXVP7Zt6MFoKqKeHm4nV9BHvbgoRPg", privateKey : "HqhrzsRfG5-SB3j45lyUmV7cYZuy-71r2Bb0tgaOefk" }; // set vapid keys for webpush libs webpush.setVapidDetails('mailto:push@qt.io', vapidKeys.publicKey, vapidKeys.privateKey);
Hinweis: Die Verschlüsselung von Nachrichten wird in diesem Beispiel nicht behandelt.
Zum Erzeugen von Schlüsseln können wir das mit der web-push lib gelieferte Tool verwenden, das von npm
in das Stammverzeichnis unseres Beispiels installiert wird.
./node_modules/.bin/web-push generate-vapid-keys
Nun fügen wir dem Push-Server zwei routes
hinzu. Eine zu subscribe
und eine zu unsubscribe
, so dass unser Front-End eine HTTP-POST-Anfrage senden kann, um das Push-Abonnement zu bearbeiten. In der Abo-Anforderung erhalten wir subscription
im Anforderungskörper und wir rufen auch die benutzerdefinierte Kopfzeile ping-time
ab, die definiert, wie oft die Ping-Nachrichten an den Benutzer gesendet werden sollen. Wir behalten den subscription
, um später Push-Benachrichtigungen senden zu können. Zur Bestätigung senden wir den Statuscode 201 und planen die erste Push-Benachrichtigung basierend auf dem Wert ping-time
. Die Anfrage unsubscribe
entfernt einfach ein Abonnement.
// add subscribe route server.post('/subscribe', (req, res) => { // subscription request subscription = req.body; const delay = req.headers['ping-time']; console.log('Got subscription with endpoint: ' + subscription.endpoint); console.log('Ping delay is at: ' + delay); // confirm resource created res.status(201).json({}); // schedule notification setTimeout(() => { sendNotification(delay) }, delay * 1000); }); // add unsubscribe route server.post('/unsubscribe', (req, res) => { console.log('Got unsubscribe with endpoint: ' + req.body.endpoint); subscription = null; res.status(201).json({}); });
Die Funktion sendNotication()
sendet Push-Nachrichten mit Hilfe der web-push lib. Wir erstellen die Nutzlast mit der Nachricht, die wir einem Benutzer präsentieren wollen, und planen die nächste Push-Nachricht.
function sendNotification(delay) { if (!subscription) return; // create payload text const payload = JSON.stringify({ title : 'Ping !', text : 'Visit qt.io', url : 'www.qt.io' }); // send notification console.log('Sending notification !'); webpush.sendNotification(subscription, payload).catch(err => console.error(err)); // schedule next notification setTimeout(() => { sendNotification(delay) }, delay * 1000); }
Zum Schluss starten wir den Server, um auf dem angegebenen Port zu lauschen.
server.listen(port, () => console.log(`Push server started at port ${port}`));
Kommen wir nun zu unserem Frontend. Wir erstellen eine einfache Seite index.html, auf der der Benutzer eingeben kann, wie oft er Ping-Benachrichtigungen erhalten möchte. Wir werden zwei Schaltflächen haben: Ping Me zum Abonnieren von Push-Benachrichtigungen und Clear zum Abbestellen. Zum Schluss laden wir ping.js, das wir als nächstes behandeln.
<body> <h1>Push Notification Using NodeJS and QtWebEngine</h1> <div id="app"> <div id="ping-setup"> <form> <div> Ping Me Every [sec]: </div> <div class="ping-input"> <input type="number" name="seconds" min="0" max="3600" required=""> </div><button>Ping Me</button> </form> </div> <div id="ping-clear"> <div id="ping-text"></div><button id="ping-clear-button">Clear</button> </div> </div> <script src="ping.js"></script> </body>
Der letzte Teil ist die Erstellung der Logik für das Push-Abonnement innerhalb des Frontends. Hier haben wir zwei Funktionen, setup
und clear
, um die Abonnements zu verwalten. Wenn der Benutzer auf die Schaltfläche Ping Me klickt, wird setup
aufgerufen. Um Benachrichtigungen empfangen zu können, wird der Service Worker benötigt. Auf diese Weise kann der Benutzer die Website verlassen und wird trotzdem benachrichtigt, da der Service Worker im Hintergrund arbeitet und eingehende Nachrichten bearbeitet. Um das zu erreichen, müssen wir zunächst einen registrieren:
const register = await navigator.serviceWorker.register('/worker.js', { scope : '/' });
Der Aufruf von cpushManager.subscribe()
löst eine Erlaubnisabfrage aus, die dem Benutzer angezeigt wird. Wenn die Erlaubnis erteilt wird, wird das Push-Abonnement zurückgegeben. Es enthält einen URL-Endpunkt, der das Senden von Benachrichtigungen an den Browser ermöglicht, wo der registrierte Service Worker auf Push-Nachrichten wartet.
var subscription = await register.pushManager.subscribe( { userVisibleOnly : true, applicationServerKey : publicVapidKey });
Wie bereits erwähnt, wird das Abonnement für FCM erstellt und sollte nun mit einer HTTP-POST-Anfrage an unseren benutzerdefinierten Server gesendet werden. Außerdem fügen wir dem Post-Request den HTTP-Header mit dem ping-time
hinzu, den der Benutzer auf unserer Website eingegeben hat.
await fetch('/subscribe', { method : 'POST', body : JSON.stringify(subscription), headers : { 'content-type' : 'application/json', 'ping-time' : delay } });
Der Aufruf der Funktion clear
meldet sich zuerst von unserem Push-Server ab, indem er eine HTTP-POST-Anfrage sendet, und später vom Push-Dienst eines Drittanbieters (FCM).
const register = await navigator.serviceWorker.getRegistration(); var subscription = await register.pushManager.getSubscription(); ... await fetch('/unsubscribe', { method : 'POST', body : JSON.stringify(subscription), headers : { 'content-type' : 'application/json' } }); ... await subscription.unsubscribe();
Der Rest des Codes in ping.js ist nur Boilerplate-Code, um einen vom Benutzer eingegebenen Wert zu lesen und setup()
oder clear()
aufzurufen.
Als letzten Teil des Frontends sehen wir uns ein Service-Worker-Skript an, in dem wir einfach einen Event-Listener für Push-Ereignisse registrieren.
self.addEventListener('push', event => { const data = event.data.json(); self.registration.showNotification(data.title, { body : data.text }); });
Wenn ein Push-Ereignis eintritt, verwenden wir einfach die Notification JavaScript API, um eine Benachrichtigung anzuzeigen.
Hinweis: QtWebEngine Notification Example zeigt, wie Sie einen eigenen Handler bereitstellen und das Aussehen einer Benachrichtigung anpassen können.
Nach der Implementierung können wir den Server auf localhost mit dem Port 5000 starten. Dazu können wir einfach die Konsole im Stammverzeichnis des Projekts aufrufen:
npm start
Jetzt können wir uns die Push-Benachrichtigungs-Browseranwendung ansehen, die auf dem WebEngine Notifications Example basiert:
int main(int argc, char *argv[]) { QCoreApplication::setOrganizationName("QtExamples"); QApplication app(argc, argv); const QString name = QString::fromLatin1("push-notifications.%1").arg(qWebEngineChromiumVersion()); QScopedPointer<QWebEngineProfile> profile(new QWebEngineProfile(name)); QWebEngineView view(profile.data()); auto popup = new NotificationPopup(&view); QObject::connect(view.page(), &QWebEnginePage::permissionRequested, [&](QWebEnginePermission permission) { if (permission.permissionType() != QWebEnginePermission::PermissionType::Notifications) return; permission.grant(); }); profile->setPushServiceEnabled(true); profile->setNotificationPresenter([&](std::unique_ptr<QWebEngineNotification> notification) { popup->present(notification); }); view.resize(640, 480); view.setUrl(QUrl("http://localhost:5000")); view.show(); return app.exec(); }
Diese Anwendung öffnet einfach die Seite http:\\localhost:5000
. Wir gehen hier nicht im Detail darauf ein, wie eine Benachrichtigung geöffnet wird, da dies hier dokumentiert ist. Allerdings müssen Sie die Anwendung in zweierlei Hinsicht ändern. Erstens kann QWebEngineProfile
nicht auf "off-the-record" eingestellt werden, weil dann Push-Nachrichten deaktiviert wären. Daher wird, wie Sie oben sehen können, QWebEngineProfile
mit dem Namen initialisiert. Zweitens müssen Sie das Push-Messaging mit dem Aufruf QWebEngineProfile::setPushServiceEnabled für die erstellte profile
aktivieren.
Wenn die Anwendung läuft, wird sie angezeigt:
Nach Erteilung der Genehmigung können wir unsere Ping-Anfrage senden:
Wir sollten die kommende Push-Benachrichtigung sehen:
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.