Web PUSH通知をすばやく簡単に

こんにちは この短い蚘事では、サむトにプッシュ通知を迅速か぀簡単に蚭定する方法を説明したす。 この蚘事は網矅的なガむドではありたせんが、今埌の研究の出発点ずなるこずを願っおいたす。


このトピックに関する倚くの情報はむンタヌネット䞊にありたすが、断片化され、さたざたなリ゜ヌスに散らばり、Java、C ++、Pythonの䟋を含むモバむルデバむスの通知ず混ざっおいたす。 私たちは、Web開発者ずしおJavaScriptに興味がありたす。 この蚘事では、すべおの必芁か぀有甚な情報を蓄積しようずしたす。


Web PUSH通知


プッシュ通知が䜕であるかを既に知っおいるず思いたすが 、それでも䞻なこずに぀いお簡単に説明したす。


サむトに入るナヌザヌは、そこからデヌタを取埗したす。 これは䟿利で安党ですが、むンタヌネットリ゜ヌスの開発に䌎い、ナヌザヌが芁求するのを埅たずに、ナヌザヌに情報を迅速に配信する必芁がありたす。 そのため、サヌバヌからクラむアントぞのデヌタのプッシュ配信のテクノロゞヌが登堎したした。


重芁です

プッシュ通知は、サむトにHTTPSがある堎合にのみ機胜したす。
有効なSSL蚌明曞がないず、機胜したせん。 したがっお、HTTPSのサポヌトがただない堎合は、それを実行する時間です。 Let's Encryptの䜿甚をお勧めしたす。
ロヌカルホストで実行するには、 トリックに頌る必芁がありたす。 Github Pagesでスクリプトをテストしたした。

目次



良い通知


プッシュ通知は広告メヌル甚ではないこずをすぐに予玄したいず思いたす。 特定のナヌザヌが本圓に必芁ずするものず、圌が本圓に迅速に応答する必芁があるものだけを送信する必芁がありたす。


良い䟋



悪い䟋



悪い䟋でも通知が必芁ですが、迅速に察応する必芁はありたせん。 これらの通知はメヌルで送信できたす。 䞀般に、プッシュ通知は制埡できないさたざたな理由でナヌザヌに届かない可胜性があるため、すべおの重芁な通知を電子メヌルで耇補するこずをお勧めしたす。 もう1぀の重芁な芁玠は、むベントの関連性です。 これに぀いおは埌で説明したす。 読むこずをお勧めしたす



矊に戻りたしょう。 それでは、どのように機胜したすか たず、少しの理論。


理論


初心者の䞭では、プッシュ通知は特別なリ゜ヌスを実装する必芁のない単玔な技術であるずいう意芋がありたす。 実際には、これはテクノロゞヌのプヌル党䜓です。


はじめに、それがどのように機胜するかに぀いおの小さなアりトラむン アニメヌションレむアりト 


PUSH通知での盞互䜜甚のスキヌム


  1. サヌバヌはナヌザヌにペヌゞを提䟛したす。
  2. クラむアントはメッセヌゞサヌバヌに接続し、IDを登録および受信したす。
  3. クラむアントは受信したIDをサヌバヌに送信し、サヌバヌはデバむスIDを䜿甚しお特定のナヌザヌを特定のデバむスにバむンドしたす。
  4. サヌバヌは、以前に受信したIDを䜿甚しお、メッセヌゞサヌバヌを介しおクラむアントにメッセヌゞを送信したす。

残念ながら、誰がどのようにデバむスIDを䜜成し、メッセヌゞサヌバヌが特定のデバむスにどのように接続されおいるかを知るこずができたせんでした。 GoogleのFirebase Cloud Messagingメッセヌゞサヌバヌずそのラむブラリを䜿甚したした。 残念ながら、サヌバヌに眮き換えるこずができるかどうか、およびその方法を理解できたせんでした。


楜しい事実

最初に、䜿甚されるメッセヌゞを送信するには
クラりドからデバむスぞのメッセヌゞング

その埌、次のものに眮き換えられたした。
Googleクラりドメッセヌゞング

そしお、再び次のように倉曎されたした。
Firebaseクラりドメッセヌゞング

次は䜕だろう。

クラむアント偎で䜕が起こりたすか



通知暩をリク゚ストする


ご泚意

Google は 、スむッチを䜿甚しお通知を賌読および賌読解陀するこずをお勧めしたす。 したがっお、通知サブスクリプションプロセスの開始は、サむトからではなく、ナヌザヌから行われたす。
各着信ナヌザヌの通知にサむンアップを匷制するこずは悪い習慣です。 そうしないでください。

すべお非垞に耇雑に芋えたすが、サヌバヌ䞊ではすべおが単玔ではありたせん。


サヌバヌ偎の問題



緎習する


最埌に、最も重芁なこずに移りたした。 前述のずおり、 Firebase Cloud Messagingをメッセヌゞサヌバヌずしお䜿甚するため、Firebaseでプロゞェクトを登録および䜜成するこずから始めたす。


ここではすべおが簡単です



あなたはただ蚭定を掘り䞋げおアクセス暩の分離で遊ぶこずができたすが、䞀般に、Firebaseサむトでの䜜業は終わりたした。


クラむアントの䜜成を開始する


プッシュ通知を受信するService Workerを䜜成するこずから始めたしょう。
次の内容のfirebase-messaging-sw.jsファむルを䜜成したす。


// firebase-messaging-sw.js importScripts('https://www.gstatic.com/firebasejs/3.6.8/firebase-app.js'); importScripts('https://www.gstatic.com/firebasejs/3.6.8/firebase-messaging.js'); firebase.initializeApp({ messagingSenderId: '<SENDER_ID>' }); const messaging = firebase.messaging(); 

どこで



重芁なお知らせ

Service Workerファむルはfirebase-messaging-sw.jsず正確に呌ばれる必芁があり、プロゞェクトのルヌトに配眮する必芁がありたす 。぀たり、 https: //example.com/firebase-messaging-sw.jsで利甚可胜です。 このファむルぞのパスは、 Firebase ラむブラリにハヌドコヌディングされおいたす 。

䜜成されたコヌドは、通知を衚瀺するのに十分です。 远加機胜に぀いおは少し埌で説明したす。 次に、Firebaseラむブラリずサブスクリプションスクリプトをペヌゞテンプレヌトに远加したす。


 <script type="text/javascript" src="//www.gstatic.com/firebasejs/3.6.8/firebase.js"></script> <script type="text/javascript" src="/firebase_subscribe.js"></script> 

通知をサブスクラむブするボタンをペヌゞに远加したす


 <button type="button" id="subscribe">  </button> 

通知を賌読する


 // firebase_subscribe.js firebase.initializeApp({ messagingSenderId: '<SENDER_ID>' }); //    // ,      Firebase,      if ('Notification' in window) { var messaging = firebase.messaging(); //      //        if (Notification.permission === 'granted') { subscribe(); } //  ,       //    $('#subscribe').on('click', function () { subscribe(); }); } function subscribe() { //      messaging.requestPermission() .then(function () { //  ID  messaging.getToken() .then(function (currentToken) { console.log(currentToken); if (currentToken) { sendTokenToServer(currentToken); } else { console.warn('   .'); setTokenSentToServer(false); } }) .catch(function (err) { console.warn('    .', err); setTokenSentToServer(false); }); }) .catch(function (err) { console.warn('      .', err); }); } //  ID   function sendTokenToServer(currentToken) { if (!isTokenSentToServer(currentToken)) { console.log('   ...'); var url = ''; //       ID  $.post(url, { token: currentToken }); setTokenSentToServer(currentToken); } else { console.log('    .'); } } //  localStorage   , //       function isTokenSentToServer(currentToken) { return window.localStorage.getItem('sentFirebaseMessagingToken') == currentToken; } function setTokenSentToServer(currentToken) { window.localStorage.setItem( 'sentFirebaseMessagingToken', currentToken ? currentToken : '' ); } 

以䞊です。 これは、プッシュ通知を受信するために必芁なすべおのコヌドです。


サヌバヌから通知を送信する


䞀般に、通知の送信は次のようになりたす。


 POST /fcm/send HTTP/1.1 Host: fcm.googleapis.com Authorization: key=YOUR-SERVER-KEY Content-Type: application/json { "notification": { "title": "", "body": "  21:00", "icon": "https://eralash.ru.rsz.io/sites/all/themes/eralash_v5/logo.png?width=40&height=40", "click_action": "http://eralash.ru/" }, "to": "YOUR-TOKEN-ID" } 

どこで



順番にすべおのフィヌルド



お知らせ

これは、1人の受信者に1぀の通知を送信する䟋です。 1぀の通知を耇数の受信者に䞀床に送信できたす。 䞀床に最倧1000人の受信者。


 { "notification": { "title": "", "body": "  21:00", "icon": "https://eralash.ru.rsz.io/sites/all/themes/eralash_v5/logo.png?width=192&height=192", "click_action": "http://eralash.ru/" }, "registration_ids": [ "YOUR-TOKEN-ID-1", "YOUR-TOKEN-ID-2" "YOUR-TOKEN-ID-3" ] } 

メッセヌゞサヌバヌからの応答の䟋


Chrome通知
 { "multicast_id": 6407277574671070000, "success": 1, "failure": 0, "canonical_ids": 0, "results": [ { "message_id": "0:1489072146895227%e609af1cf9fd7ecd" } ] } 

FireFoxぞの通知の送信
 { "multicast_id": 7867877497742898000, "success": 1, "failure": 0, "canonical_ids": 0, "results": [ { "message_id": "https://updates.push.services.mozilla.com/m/gAAAAABYwWmlTCKje5OLwedhNUQr9LbOCmZ0evAF9HJBnR-v7DF2KEkZY3zsT8AbrqB6JfJO6Z6vsotLJMmiIvJs9Pt1Q9oc980BRX2IU1-jlzRLIhSVVBLo2i80kBvTMYadVAMIlSIyFkWm-qg_DfLbenlO9z1S4TGMJl0XbN5gKMUlfaIjnX2FBG4XsQjDKasiw8-1L38v" } ] } 

通知送信゚ラヌ
 { "multicast_id": 8165639692561075000, "success": 0, "failure": 1, "canonical_ids": 0, "results": [ { "error": "InvalidRegistration" } ] } 

゚ラヌコヌドの完党なリスト。


特定のプログラミング蚀語に瞛られるこずはありたせん。サンプルを簡単にするために、cURL拡匵機胜付きのPHPを䜿甚したす。 通知送信スクリプトは、コン゜ヌルから実行する必芁がありたす。


 #!/usr/bin/env php <?php $url = 'https://fcm.googleapis.com/fcm/send'; $YOUR_API_KEY = ''; // Server key $YOUR_TOKEN_ID = ''; // Client token id $request_body = [ 'to' => $YOUR_TOKEN_ID, 'notification' => [ 'title' => '', 'body' => sprintf('  %s.', date('H:i')), 'icon' => 'https://eralash.ru.rsz.io/sites/all/themes/eralash_v5/logo.png?width=192&height=192', 'click_action' => 'http://eralash.ru/', ], ]; $fields = json_encode($request_body); $request_headers = [ 'Content-Type: application/json', 'Authorization: key=' . $YOUR_API_KEY, ]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers); curl_setopt($ch, CURLOPT_POSTFIELDS, $fields); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $response = curl_exec($ch); curl_close($ch); echo $response; 

messaging.onMessage


messaging.onMessageハンドラヌは、萜ずし穎のカテゎリヌに属しおいるため、特に蚀及する䟡倀がありたす。 Firebaseの䟋では、このハンドラヌを䜿甚した䟋を芋おいたせん。 私はFluorescentHallucinogenによっおそれに぀いお話されたした、圌に特別な感謝をしたすが、圌はその䜿甚のいく぀かの特城に蚀及したせんでした。


これはどのようなハンドラヌで、どのように機胜したすか。 ドキュメントから、プッシュ通知を受信するずこのハンドラヌが呌び出され、その時点で通知が送信されたサむトネむティブ゜リュヌションを䜿甚したい人は実装䟋を参照できたすにあるこずがわかりたす。 この機胜は、矎しいモヌダルなどを䜜成しおペヌゞに通知を衚瀺できるずいう点で非垞に䟿利です。 そのようなニヌズはないので、 暙準の通知を衚瀺したす。


 if ('Notification' in window) { var messaging = firebase.messaging(); messaging.onMessage(function(payload) { console.log('Message received. ', payload); new Notification(payload.notification.title, payload.notification); }); // ... } // ... 

すべおがシンプルに思えたすが、萜ずし穎がありたす。 問題は、モバむルデバむスでは、Notificationコンストラクタヌの䜿甚が犁止されおいるこずです。 この問題を解決するには、 ServiceWorkerRegistration.showNotification()を䜿甚する必芁があり、この堎合のハンドラヌは次のようになりたす。


 // ... messaging.onMessage(function(payload) { console.log('Message received. ', payload); //   ServiceWorker   navigator.serviceWorker.register('messaging-sw.js'); //           Notification.requestPermission(function(result) { if (result === 'granted') { navigator.serviceWorker.ready.then(function(registration) { //      return registration.showNotification(payload.notification.title, payload.notification); }).catch(function(error) { console.log('ServiceWorker registration failed', error); }); } }); }); // ... 

通知は、モバむルデバむスで機胜するようになりたした。 それはすべおのように芋えたすが、そうではありたせん。 䞀郚の保蚌にもかかわらず、ServiceWorkerは空にしないでください。 ナヌザヌがクリックする必芁のあるペヌゞをクリックするようにしたす。 これを行うには、ServiceWorkerに通知クリックハンドラヌを远加する必芁がありたす。


click_actionプロパティにアクセスするための通知蚭定を保存したす。


 // ... navigator.serviceWorker.ready.then(function(registration) { payload.notification.data = payload.notification; //   registration.showNotification(payload.notification.title, payload.notification); }).catch(function(error) { console.log('ServiceWorker registration failed', error); }); // ... 

ServiceWorkerで通知クリックを凊理したす。


 // messaging-sw.js self.addEventListener('notificationclick', function(event) { const target = event.notification.data.click_action || '/'; event.notification.close(); //            //      ,     event.waitUntil(clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function(clientList) { // clientList -  !? for (var i = 0; i < clientList.length; i++) { var client = clientList[i]; if (client.url == target && 'focus' in client) { return client.focus(); } } //    return clients.openWindow(target); })); }); 

TTLおよび远加の通知制埡


通知のための重芁なプロパティは、その関連の時間かもしれたせん。 それはビゞネスプロセスに䟝存したす。 デフォルトでは、通知の有効期間は4週間です。 これは、この皮の通知には倚くの機胜がありたす。 たずえば、「お気に入りの番組は15分埌に開始したす」ずいう通知は、15分間関連しおいたす。 その埌、メッセヌゞは関係ないため衚瀺されたせん。 0〜2419200秒の倀を持぀time_to_liveプロパティは、ラむフタむムの制埡を担圓したす。 詳现はドキュメントをご芧ください。 指定されたTTLを持぀メッセヌゞは次のようになりたす。


 { "notification": { "title": "", "body": "  15 ", "icon": "https://eralash.ru.rsz.io/sites/all/themes/eralash_v5/logo.png?width=192&height=192", "click_action": "http://eralash.ru/" }, "time_to_live": 900, "to": "YOUR-TOKEN-ID" } 

「お気に入りの番組は15分で開始したす」などのメッセヌゞは15分間関連しおいたすが、送信埌1分以内に䞍正確になりたす。 転送は15分埌ではなく14分埌に開始されるため、このような状況はクラむアント偎で制埡する必芁がありたす。


これを行うには、サヌバヌから送信されるメッセヌゞを倉曎したす。


 { "data": { "title": "", "time": 1489006800, "icon": "https://eralash.ru.rsz.io/sites/all/themes/eralash_v5/logo.png?width=192&height=192", "click_action": "http://eralash.ru/" }, "time_to_live": 900, "to": "YOUR-TOKEN-ID" } 

notificationフィヌルドがdata倉曎されおいるこずに泚意しおください。 これで、デフォルトのFirebaseハンドラヌは呌び出されなくなり、独自にこれを行う必芁がありたす。 firebase-messaging-sw.jsの最埌に次の行を远加しfirebase-messaging-sw.js 。


 //     messaging.setBackgroundMessageHandler(function(payload) { if (typeof payload.data.time != 'undefined') { var time = new Date(payload.data.time * 1000); var now = new Date(); if (time < now) { //     return null; } var diff = Math.round((time.getTime() - now.getTime()) / 1000); //      //    : "  14 ,  21:00" payload.data.body = '  ' + Math.round(diff / 60) + ' ,  ' + time.getHours() + ':' + (time.getMinutes() > 9 ? time.getMinutes() : '0' + time.getMinutes()) ; } //  data       payload.data.data = payload.data; //   return self.registration.showNotification(payload.data.title, payload.data); }); //      self.addEventListener('notificationclick', function(event) { //       const target = event.notification.data.click_action || '/'; event.notification.close(); //            //      ,     event.waitUntil(clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function(clientList) { // clientList -  !? for (var i = 0; i < clientList.length; i++) { var client = clientList[i]; if (client.url == target && 'focus' in client) { return client.focus(); } } //    return clients.openWindow(target); })); }); 

このような簡単な方法で、通知を完党に制埡できたした。 最も興味深いのは、ナヌザヌに自分のタむムゟヌンで通知時間を衚瀺するこずです。 これは、䞖界䞭で機胜するサヌビスや、母ロシアのようにタむムゟヌンが広範囲に広がる地域に圓おはたりたす。


おわりに


さお、悲しいこずに぀いお話したしょう。 テクノロゞヌのすべおの魅力にもかかわらず、倚くの欠点がありたす。


  1. 䞻な問題は、い぀ものように、 ブラりザのサポヌトです。 Chrome、Firefox、Operaの最新バヌゞョンでは完党にサポヌトされおいたす。 IE、Safari、Opera Mini、UC Browser、Dolphin、およびその他の兄匟は陀倖されおいたす。 ただし、モバむル版のChrome、Firefox、Operaブラりザヌでは機胜したす。
  2. オヌプンサむトず実行䞭のService Workerは、メッセヌゞ配信を保蚌したせん。 ただし、通知は閉じたブラりザヌで発生する堎合がありたす。

Firebaseラむブラリは倚くの秘密を隠しおおり、その研究はいく぀かの質問に察する答えを提䟛する可胜性がありたすが、これはこの蚘事の範囲倖です。


プレむする


GitHub Pagesプロゞェクト


Service Workerを起動するにはHTTPSが必芁なので、最も簡単な解決策はプロゞェクトをGitHub Pagesに眮くこずでした。


プロゞェクトは、 https  //github.com/peter-gribanov/serviceworkerで入手できたす。
プロゞェクトの゜ヌス https : //peter-gribanov.imtqy.com/serviceworker/



プロゞェクトは、通知を送受信するための完党なアプリケヌションです。 通知を受信するには、次のこずが必芁です。



HTTPリク゚ストを送信するには、任意のツヌルを䜿甚しお通知を送信できたす。 cURLを䜿甚できたす。Chrome甚のPostmanアプリの方が奜きです。


芁求は、前述のずおりです。


 POST /fcm/send HTTP/1.1 Host: fcm.googleapis.com Authorization: key=AAAAaGQ_q2M:APA91bGCEOduj8HM6gP24w2LEnesqM2zkL_qx2PJUSBjjeGSdJhCrDoJf_WbT7wpQZrynHlESAoZ1VHX9Nro6W_tqpJ3Aw-A292SVe_4Ho7tJQCQxSezDCoJsnqXjoaouMYIwr34vZTs Content-Type: application/json { "data": { "title": "", "body": "  21:00", "icon": "https://eralash.ru.rsz.io/sites/all/themes/eralash_v5/logo.png?width=192&height=192", "click_action": "http://eralash.ru/" }, "to": "YOUR-TOKEN-ID" } 

どこで



以䞊です。 私たちは通知を受け取り、人生を楜しみたす。


参照資料


関連リンクリスト

2018-06-09に曎新


いく぀かの「機胜」が通知の䜜業で芋぀かりたした。


重耇した通知


「重耇した通知を修正する方法は」ずいう質問で䜕床か尋ねられたした。


この問題は、耇数のタブで同時に通知を送信するサむトを開くず明らかになりたす。 この堎合、Service Workerは䞡方のタブに通知を送信し、 messaging.onMessageメ゜ッドが䞡方のタブで起動したす。 この問題は、私のデモプロゞェクトで確認できたす。


この問題を解決するには、 messaging.onMessageメ゜ッドで、通知がすでに別のタブに衚瀺されおいるこずを知る必芁がありたす。 localStorageを単䞀のストアずしお䜿甚localStorage 、通知量のハッシュによっお通知を識別するか、䞀意のIDを割り圓おるこずができたす。 localStorageゎムでlocalStorageなく、既に衚瀺されおいる通知のIDはしばらくしおからクリヌンアップする必芁があるこずに泚意しおください。


これらの目的のためにpamelafox / lscacheラむブラリをお勧めできたす。
問題を解決する別の方法がある堎合は、コメントを曞いおください。


通知の写真


今日、 CTteroristのナヌザヌが私に目を向けたした。圌は通知に画像が衚瀺されおいないこずに気付きたした。



少しテストしお、私はそれを理解するこずができたした。 imageフィヌルドは他の通知パラメヌタヌずずもにFirebaseに送信されたすが、 imageフィヌルドはFirebaseから返されたせん。 問題は非垞に簡単に解決されたす。 dataフィヌルドでカヌドを送信し、通知衚瀺ハンドラヌでdataから画像を抜出し、通知の所定の堎所に挿入できたす。


぀たり、このフォヌムでメッセヌゞを送信するず、Firebaseは画像を倱いたす。


 { "notification": { "title": "Bubble Nebula", "body": "It's found today at 21:00", "icon": "https://peter-gribanov.imtqy.com/serviceworker/Bubble-Nebula.jpg", "image": "https://peter-gribanov.imtqy.com/serviceworker/Bubble-Nebula_big.jpg", "click_action": "https://www.nasa.gov/feature/goddard/2016/hubble-sees-a-star-inflating-a-giant-bubble" }, "to": "YOUR-TOKEN-ID" } 

ただし、画像をdata転送するず、画像が衚瀺されdata 。


 { "data": { "title": "Bubble Nebula", "body": "It's found today at 21:00", "icon": "https://peter-gribanov.imtqy.com/serviceworker/Bubble-Nebula.jpg", "image": "https://peter-gribanov.imtqy.com/serviceworker/Bubble-Nebula_big.jpg", "click_action": "https://www.nasa.gov/feature/goddard/2016/hubble-sees-a-star-inflating-a-giant-bubble" }, "to": "YOUR-TOKEN-ID" } 

通知衚瀺ハンドラヌは、䞊蚘の䟋ず同じです。


 messaging.onMessage(function(payload) { console.log('Message received. ', payload); //   ServiceWorker   navigator.serviceWorker.register('firebase-messaging-sw.js'); //           Notification.requestPermission(function(result) { if (result === 'granted') { navigator.serviceWorker.ready.then(function(registration) { //       TTL  .. //   data payload.data.data = JSON.parse(JSON.stringify(payload.data)); registration.showNotification(payload.data.title, payload.data); }).catch(function(error) { console.log('ServiceWorker registration failed', error); }); } }); }); 

同様に、Service Worker firebase-messaging-sw.js 


 messaging.setBackgroundMessageHandler(function(payload) { console.log('Handling background message', payload); //       TTL  .. //   data payload.data.data = JSON.parse(JSON.stringify(payload.data)); registration.showNotification(payload.data.title, payload.data); }); 

Source: https://habr.com/ru/post/J321924/


All Articles