朝日ネット 技術者ブログ

朝日ネットのエンジニアによるリレーブログ。今、自分が一番気になるテーマで書きます。

PWAでwebプッシュ通知を作る (5) - 締切通知システムの設計とブログデザイン変更について

はじめに

watanabeです。 前回の予告では今回の記事でバックグラウンドで通知を受け取れるように実装する予定でしたが FCM用のJSをインポートする部分でバージョンを統一したところ

  • ブラウザ上だと、ウェブページを閉じた状態
  • スマホだとブラウザを閉じた状態

両方でプッシュ通知を受け取ることができました。(変更箇所は後述)

今回は、今までの実装を生かしてプッシュ通知を実際に締め切り通知のようなリマインダとして使用する場合のシステムの設計を考えてみます。

バックグラウンドで通知を受け取るための修正について

firebase-messaging-sw.jsの一部を以下のように書き換えました。

変更前

importScripts('/__/firebase/4.10.0/firebase-app.js');
importScripts('/__/firebase/4.10.0/firebase-messaging.js');
importScripts('/__/firebase/init.js');

var messaging = firebase.messaging();

 importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js');
 importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js');

変更後 ↓

importScripts('/__/firebase/5.0.0/firebase-app.js');
importScripts('/__/firebase/5.0.0/firebase-messaging.js');
importScripts('/__/firebase/init.js');

var messaging = firebase.messaging();

 importScripts('https://www.gstatic.com/firebasejs/5.0.0/firebase-app.js');
 importScripts('https://www.gstatic.com/firebasejs/5.0.0/firebase-messaging.js');

スマホでブラウザを起動していない状態で受け取ったプッシュ通知は以下になります。

検証端末:(701SH、Android 8.0 、Chrome70.0.3538.64)

f:id:watanabe06:20181030174454p:plain

締切通知システムの設計について

引き続き、実際に締め切り通知のようなリマインダとしてプッシュ通知を使用する場合のシステムの設計を考えてみます。

現在実装済なのは以下の部分です。

  • PWAの仕組みでバックグラウンドで通知を受け取る設定をできるようにする。
  • FCMで送り先の端末用のトークンを取得する
  • FCMのAPIをCurlコマンドで叩くことでトークンを取得した端末あてにプッシュ通知を送る

そこに時間指定でプッシュ通知を送られるようにするためには以下の手順が必要になります。

  1. PWAの仕組みでバックグラウンドで通知を受け取る設定をできるようにする。
  2. FCMで送り先の端末用のトークンを取得する
  3. サーバを用意し、Webページから登録したい日時とトークンを送り、サーバのデータベースに保存する。
  4. サーバが指定された日時にAPIを叩くことでプッシュ通知が送られる

図にすると以下のようになります。

f:id:watanabe06:20181102102934p:plain

今回は設計のみで実装はしませんが、今後システムにプッシュ通知を組み込む時の選択肢に入れる予定です。

最後に(ブログのデザイン変更について)

10/26よりブログのデザインが新しくなりました。

変更点は以下になります。

  1. ヘッダーにイラストを配置
  2. ヘッダーにASAHIネットへのリンクを追加
  3. スマホ版のスタイルをPC版と同様のものに変更
  4. サイドバーに表示する採用情報へのリンクをバナーに変更

1.ヘッダーにイラストを配置

イラストはレスポンシブデザインに対応しているので現在閲覧している画面の幅に合わせて表示されます。

f:id:watanabe06:20181029150721p:plain

2.ヘッダーにASAHIネットへのリンクを追加

ヘッダーのロゴをクリックすることでASAHIネットのサービス紹介ページに飛べるようにしました。 はてなブログでは現在、タイトル部分より上にHTMLの部品を挿入することができないため CSSで調整しています。

管理画面のデザイン変更>ヘッダ から追加したHTML

<div class="header-logo">
   <a href="https://asahi-net.jp" target="_blank"><img src="バナーURL" alt="朝日ネットホームページ"></a>
  </div>

ヘッダーにmarginで上にロゴを入れるスペースを追加

#blog-title {
    margin-top: 65px;
...

HTMLのスタイル(position:absoluteで上部に移動)

.header-logo {
    text-align: left;
    margin: 0 auto;
    padding: 15px 15px 10px;
    position: absolute;
    top: 0;
}

3.スマホ版のスタイルをPC版と同様のものに変更

今までは最低限の文字サイズの大小の違いのみだったのを 前述の通り、レスポンシブデザイン対応をしているので PC版と同様の見易いデザインで閲覧できるようになりました。

4.サイドバーに表示する採用情報へのリンクをバナーに変更

採用サイトへのリンクをバナーに置き換えました。 クリックで各採用サイトを表示します。

新デザインでパワーアップしたブログを今後もよろしくお願いいたします。

採用情報

朝日ネットでは新卒採用・キャリア採用を行っております。

オリジナルの音声アシスタントを作ろう (4) - Dialogflow 前編

はじめに

こんにちは。朝日ネットでWebアプリケーションの開発を行っている tommy です。

前回 は Google の Cloud Speech API を使って音声認識をしてテキストデータを得るプログラムを作成しました。 今回は実際に会話をする部分の作成に入っていこうと思います。

※本記事のスクリーンショットは記事執筆時のものです。今後画面や仕様が変更になる可能性があります。また結果は機械学習によるものなので、同じように入力しても同じ結果を得られない可能性があります。

  • はじめに
  • 会話API
    • Dialogflow
  • 用語
    • Agent
    • Intent
    • Entity
    • Context
    • Dialog
  • 実際に使ってみる
    • Agent 作成
    • Intent の作成
    • Entity を結びつける
    • Response
    • Action and parameters
  • LINEとの連携
    • LINE Developer にてチャネルを作成
    • Dialogflow との連携
    • LINE で会話をする
  • Trainingで精度を上げる
  • おわりに
  • 採用情報
続きを読む

論理式をランダムに生成する

こんにちは。株式会社朝日ネット開発部のxfuzzyです。 数学や関数型言語に興味があります。 前回の記事では、Haskellを使って、論理式を表す型を定義し、ヒルベルト流の推論を定義しました。 今回は論理式をランダムに生成する関数を作ってみたいと思います。 そのような関数を作ろうとした理由は、ランダムに生成した論理式の中から定理を見つけることができたら面白いのではないかと思ったからです。

  • 概要
  • Haskellのrandom関数の説明
  • 論理式をランダムに生成する方法
  • Haskellでの実装
  • 実行例
  • まとめ
  • 採用情報
続きを読む

Word2vec や fastText を Java のコードに適用して “add + map - list = put” のような結果を得たい

はじめに

開発部の tasaki です。 2013 年の Word2vec や 2016 年の fastText など、自然言語処理の分野には単語をベクトル(分散表現)に変換する手法がいくつかあります。 一旦分散表現に変換してしまえば加減算などの線形代数的な操作、 例えば “king - man + woman = queen” (王から男性を引き算し、女性を足し算すると女王になる)というような単語同士の演算が可能となります。 これを自然言語ではなくプログラムのコード(を元にした文書)に適用すればどうなるかということが気になったので gensim という Python のライブラリを使って実装をしてみました。

  • はじめに
  • 動作確認環境
  • 全ソースコード
  • Java のコードを文書に変換する
  • gensim を使う
  • 実行例
    • 対象
    • Word2vec
    • fastText
  • おわりに
  • 採用情報
続きを読む

PWAでwebプッシュ通知を作る (4) - FirebaseとCurlを使用して特定の端末に通知を送る

はじめに

watanabeです。 前回の記事ではデバッグ機能からプッシュ通知を送信して受け取ったときの処理を実装しましたが 今回は受信する端末ごとに異なるトークンを取得して、特定の端末にプッシュ通知を送れるようにします。

実装の手順

  1. Firebase Cloud Messaging(FCM)で必要な値を取得する
  2. 端末ごとのトークンを取得して表示する仕組みを作る
  3. コマンドをCurlで送信してプッシュ通知を受け取る

1.Firebase Cloud Messagingで必要な値を取得する

Firebaseに新規プロジェクトを登録し、設定画面から 以下の値・コードを取得します。

  • HTMLに貼り付ける、Firebaseを追加するスクリプト
  • サーバーキー
  • 送信者ID

参考) f:id:watanabe06:20180926144051p:plain

2.端末ごとのトークンを取得して表示する仕組みを作る

前回までで作成したすでにPWA化されたWebページ(タップでしゃべる招き猫)に変更を加えて プッシュ通知送信に必要な個々のトークンを確認できるようにします。 画面下部の「許可する」をクリックするとプッシュ通知受信の許可するかどうかの確認をして、許可をした場合に 同時に招き猫のフキダシにトークンを表示します。 (一度許可をした後でもトークンはボタンを押すことで何度でも表示できます。)

必要なファイル

  • PWA化するwebページ一式(HTMLファイル、画像、jsファイル、CSS)
  • JSONファイル
  • Service WorkerのJavaScript

イメージ) f:id:watanabe06:20180926144405p:plain

index.html(メインのHTML)

Firebase公式ガイドを参考に、

  • 1.で取得したFirebase追加のためのコード
  • プッシュ通知許可確認のコード
  • トークン表示のスクリプト

を追加します。

また、Service Workerのファイル名はFCMを使用する場合「firebase-messaging-sw.js」固定なので 読み込むService Worker部分も変更します。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-Control" content="no-cache">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="style.css">
    <link rel="apple-touch-icon" href="iconV2.png">
    <link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
    <link rel="manifest" href="manifest.json">
    <script src="jquery.js"></script>
    <script src="main.js"></script>
    <title>ランダムでしゃべる招き猫</title>
  </head>
  <body>
    <div class="container">
      <div class="fukidashi">招き猫をタップしてね</div>
      <div class="fukidashi_fuchi">
        <img src="img/fukidashi_fuchi.png" alt="">
      </div>
      <img src="img/cat.png" alt="タップでしゃべる" onclick="msg();" class="cat">
      <!--新たに許可・トークン表示ボタンを追加-->
      <br><input type="button" onclick="requestPermission() ;" value="許可する">
    </div>

    <script  type="application/javascript">
 //Service Workerの読み込み
  if('serviceWorker' in navigator){
   navigator.serviceWorker
    .register('/firebase-messaging-sw.js')
    .then(function(){
      console.log('Service Worker Registered');
   });

  }
  </script>
    <script src="https://www.gstatic.com/firebasejs/5.4.2/firebase.js"></script>
    <script>
  //FCMで取得したコードをコピー&ペーストする部分
  // Initialize Firebase
  var config = {
    apiKey: "******",
    authDomain: "******",
    databaseURL: "******",
    projectId: "******",
    storageBucket: "******",
    messagingSenderId: "******"
  };
  firebase.initializeApp(config);
const messaging = firebase.messaging();

  function requestPermission() {
   //プッシュ通知の許可をする処理
    console.log('Requesting permission...');
    // [START request_permission]
    messaging.requestPermission().then(function() {
      console.log('Notification permission granted.');
      // TODO(developer): Retrieve an Instance ID token for use with FCM.
      // [START_EXCLUDE]
      // In many cases once an app has been granted notification permission, it
      // should update its UI reflecting this.
      viewToken();
      // [END_EXCLUDE]
    }).catch(function(err) {
      console.log('Unable to get permission to notify.', err);
    });
    // [END request_permission]
  }


function viewToken(){
  messaging.getToken().then(function(currentToken) {
    if (currentToken) {
      msg02('トークンにゃ : '+ currentToken);//フキダシにトークンを表示。functionはmain.jsに定義。
    } else {
      // Show permission request.
      console.log('No Instance ID token available. Request permission to generate one.');
      // Show permission UI.
      updateUIForPushPermissionRequired();
      setTokenSentToServer(false);
    }
  }).catch(function(err) {
    console.log('An error occurred while retrieving token. ', err);
    showToken('Error retrieving Instance ID token. ', err);
    setTokenSentToServer(false);
  });
}
  </script>
  </body>
</html>
main.js(メインページで読み込むjs)

新たにフキダシに指定したメッセージを表示するfunction追加

function msg02(message) {
  $(".fukidashi").text(message);
}
manifest.json(PWA化に必要なManifestファイル)

下部に以下の定義を追加(※FCMを使用する場合は「103953800507」の固定の値となります。)

  "gcm_sender_id": "103953800507"
firebase-messaging-sw.js(新たに作成したService Worker)

今までのService Workerのスクリプトに追記・一部変更します。 Firebase用のスクリプトを読み込み、 プッシュ通知を受け取ったときの処理を記述します。

importScripts("/__/firebase/4.10.0/firebase-app.js");
importScripts("/__/firebase/4.10.0/firebase-messaging.js");
importScripts("/__/firebase/init.js");

var messaging = firebase.messaging();

importScripts("https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js");

firebase.initializeApp({
  messagingSenderId: "<送信者ID>"
});

self.addEventListener("push", function(event) {
  //送られたプッシュ通知の本文を表示
  if (Notification.permission == "granted") {
    console.log("Push Notification Recieved", event);
    event.waitUntil(
      self.registration
        .showNotification(event.data.json().notification.title, {
          body: event.data.json().notification.body
        })
        .then(
          function(showEvent) {},
          function(error) {
            console.log(error);
          }
        )
    );
  }
});

3.コマンドをCurlで送信してプッシュ通知を受け取る

2.で実装したwebページをFirebaseでデプロイ後 実際にページ動かし、トークンを表示します。

トークンと、Firebaseで取得したサーバーキーを以下のスクリプトに貼り付けて コマンドラインからCurlのコマンドで送信します。

curl "https://fcm.googleapis.com/fcm/send" \
     -X POST \
     -H "Content-Type: application/json" \
     -H "Authorization: key=<サーバーキー>" \
     -d '{
         "notification": {
            "title": "プッシュ通知タイトル",
            "body": "プッシュ通知本文",
            "click_action": "<プッシュ通知をクリックしたときに移動先にするURL>",
          },
          "to": "<ここにトークン>" 
        }'

プッシュ通知が送信されました。 コマンドラインで「"success":1」を含むJSONデータが出力されていて プッシュ通知が実際にデスクトップに表示されていれば成功です。

(確認ブラウザ:Windowsの Firefox62.2、 Google Chrome 69.0)

f:id:watanabe06:20180926145953p:plain

次回予告

次回はバックグラウンド(ページ非表示時)でもプッシュ通知を受け取れるようにします。

採用情報

朝日ネットでは新卒採用・キャリア採用を行っております。