【PWA ServiceWorker】Webサイトにインストールボタンを表示させる

はじめに

PWAの機能の一つに、スマホでWebサイトを閲覧した際、インストールバナーを画面下部にポップアップさせるというのがあります。

ただ、あのポップアップ、個人的には好きじゃありません。

画面狭くなって邪魔だし、広告みたいだし。

というわけで、今回はインストールバナーの代わりにインストールボタンを表示させる方法を、紹介したいと思います。

スポンサーリンク

前提条件

まず、インストールボタンを表示するために必要な条件について確認します。

このボタン表示機能は、バナー表示の代わりに行われる機能です。そのためバナー表示が行われる条件をまずは満たす必要があります。

というわけで以下の条件が最低限必要となります。

  • Chromeブラウザが使われていること
  • サイトがHTTPSなこと

それではさっそく、インストールボタンを表示できるようにしてみましょう!

インストールボタンを表示させる

とりあえずサンプルがないと説明しづらいので、サンプルを用意しながら説明していきます。

0.index.htmlを用意する

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>swSample</title>
</head>
<body>
  <h1>インストールボタンを表示する</h1>
</body>

ほぼ空っぽのhtmlファイルです。
このページをサンプルにして、PWA化していきます。

1.manifestの作成と読み込み

まず、Androidスマホに表示されるサイトアイコンなどの設定ファイル(manifest.json)を作ります。

manifest.json

{
  "name": "アプリ名",
  "short_name": "アプリ名",
  "theme_color": "#eeeeee",
  "background_color": "#eeeeee",
  "display": "standalone",
  "Scope": "/apps/swSample/",
  "start_url": "/apps/swSample/index.html",
  "icons": [
   {
    "src": "images/icons/icon-192x192.png",
    "sizes": "192x192",
    "type": "image/png"
   },
   {
    "src": "images/icons/icon-512x512.png",
    "sizes": "512x512",
    "type": "image/png"
   }
  ],
  "splash_pages": null
}

各種値は、ご自分の環境に合わせて設定してください。
(iconサイズは、192×192と512×512を最低限用意します)

ちなみにこれらの作業が面倒な方はこのサイトを利用するとはかどります。

manifest.jsonファイルの生成や、画像の複製を自動でやってくれるサイトです。

解説されているサイトはこちらにあります

そして、manifest.jsonの読み込みをhtmlのheadに追加します。

index.html

<link rel="manifest" href="manifest.json"><!-- manifestの読み込み -->

2.ServiceWorkerの登録

ServiceWorkerとは、簡単に言うとPWAの機能を提供してくれるAPIです。
ServiceWorkerを使うことでインストールバナー表示が行えるようになります。

ServiceWorkerについて詳しく知りたい方はこちらを参照ください

それではさっそくServiceWorkerを使ってみましょう。

ServiceWorker用のjsファイル「sw.js」を作成します。

self.addEventListener('fetch', function(e) {
  //空でOK
})

‘fetch’イベントとは、Webページの更新などが行われた際に発生するイベントです。
最低限このイベントを追加すれば、ServiceWorkerが使えるようになります。

次に、htmlファイルから「sw.js」を読み込みます。

<script>
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('sw.js')
      .then((reg) => { console.log('SW registered.', reg); });
  }
</script>

ここまでの対応で、以下のようにインストールバナーが表示されるようになるはずです。

banner-picture

バナーが表示されるようになったので、次はインストールボタンを表示できるようにしてみましょう。

3.インストールボタンを表示する

表示するボタンをhtmlに追加します。

<button id="InstallBtn" style="display:none">
  アプリをインストールする
</button>

最初は非表示にしておきたいので、styleには、display:none; を指定しておきます

JavaScriptの処理を追加します。
やることは以下の二つです。

  • インストールバナー表示イベントを乗っ取り、
    バナーの代わりにインストールボタンを表示する
  • インストールボタンクリック時に、インストールダイアログを表示する
//バナーの代わりに表示するボタンを登録する
registerInstallAppEvent(document.getElementById("InstallBtn"));

//バナー表示をキャンセルし、代わりに表示するDOM要素を登録する関数
//引数1:イベントを登録するHTMLElement
function registerInstallAppEvent(elem){
  //インストールバナー表示条件満足時のイベントを乗っ取る
  window.addEventListener('beforeinstallprompt', function(event){
    console.log("beforeinstallprompt: ", event);
    event.preventDefault(); //バナー表示をキャンセル
    elem.promptEvent = event; //eventを保持しておく
    elem.style.display = "block"; //要素を表示する
    return false;
  });
  //インストールダイアログの表示処理
  function installApp() {
    if(elem.promptEvent){
      elem.promptEvent.prompt(); //ダイアログ表示
      elem.promptEvent.userChoice.then(function(choice){
        elem.style.display = "none";
        elem.promptEvent = null; //一度しか使えないため後始末
      });//end then
    }
  }//end installApp
  //ダイアログ表示を行うイベントを追加
  elem.addEventListener("click", installApp);
}//end registerInstallAppEvent

これでボタンが表示されるようになりました。
そしてボタンをクリックするとダイアログが表示されます。

installBtn-picturedialog-picture

以上で、Webサイトにインストールボタンを表示することができるようになりました

実際のアプリに適用した例

上記ボタン表示機能を、実際にアプリに適用してみました。

end-Picture

「ホーム画面に追加」というのがインストールボタンです。
実際に見てみたい方は、こちらで公開しています

JavaScriptで簡単なゲームアプリを作ってみた
JavaScriptで超簡単なゲームアプリを作ってみました。 制限時間付きでクリックしまくるゲームです。 こちらでプレイできます。

ちなみに、このアプリはオフライン対応もしています。
ホーム画面に追加ボタンで一度このアプリをインストールすると
以降はオフラインでもプレイできるようになります。

このオフライン対応を実現するためには、ServiceWorkerの処理をもう少し追加する必要があります。

アプリをオフラインで使用可能にする

sw.jsに処理を追加します。

主な処理内容は以下です。

  • キャッシュするファイルの登録
  • キャッシュしたファイルの更新処理
  • サイトアクセス時に、キャッシュファイルを利用する処理の追加

なお、処理の詳細についてはこちらをお読みください。

sw.js

//キャッシュの設定
var CACHE_NAME = 'Counter-cash';
var urlsToCache = [
  '/apps/Counter/app.html',
  '/apps/Counter/app.css',
  '/apps/Counter/app.js',
];

//インストール
self.addEventListener('install', function(event) {
  event.waitUntil(caches.open(CACHE_NAME).then(function(cache){
    console.log('Opened cache');
    return cache.addAll(urlsToCache);
  }));
});

//古いキャッシュの削除
self.addEventListener('activate', function(event) {
  var cacheWhitelist = [CACHE_NAME, ];
  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(cacheNames.map(function(cacheName) {
        console.log('delete old cache');
        if (cacheWhitelist.indexOf(cacheName) === -1){
          return caches.delete(cacheName);
        }
      }));
    })
  );
});

//キャッシュの利用
self.addEventListener('fetch', function(event) {
  console.log('fetch');
  event.respondWith(caches.match(event.request).then(function(response){
    // Cache hit - return response
    if(response){
      return response;
    }
    var fetchRequest = event.request.clone();
    return fetch(fetchRequest).then(function(response){
      // Check if we received a valid response
      if(!response || response.status !== 200 || response.type !== 'basic') {
        return response;
      }
      var responseToCache = response.clone();
      caches.open(CACHE_NAME).then(function(cache) {
        cache.put(event.request, responseToCache);
      });
      return response;
    }));
  }));
});

これでアプリをオフラインでも使用できるようになりました。

先ほど紹介したアプリを「ホーム画面に追加」して、機内モードで起動してみてください。

きちんとプレイできるのが分かると思います。

 

以上です。

コメント

タイトルとURLをコピーしました