プロ生ちゃんの時報をChrome拡張機能で作ってみた。

この記事は プロ生ちゃん Advent Calendar 2016 24 日目の記事です。

経緯

プロ生ちゃんが時間を知らせてくれるアプリはいくつかあるけど、ブラウザの拡張機能として公開されているものは無いな〜 と思ったので自作してみました。

[ 参考 : プロ生ちゃんが時間を知らせてくれるアプリ ]

keisignal
制作 : AKKEYさん
筆者メモ : Mac のアプリケーションです。ミュートの有効/無効を変更したり、通知の時間指定をしたりすることができるためとても実用的です。

プロ生ちゃん時報
制作 : だるやなぎさん
筆者メモ : Windows 10  と Windows 10 Mobile で動作します。こちらも通知の ON/OFF や時間帯指定機能することができます。

atom-pronama-chan
制作 : フルメキさん
メモ : Atom の拡張機能です。プログラミングしていると時間を忘れがちなのでとても便利です。背景にプロ生ちゃんを表示することもできます。

chorome の拡張機能について

Chrome の拡張機能は、HTML と CSS と Javascript で作ることができます。
今回のアプリの場合、HTML と CSS は用いず作成することができました。

ファイル構成

ファイル構成はこのようになっています。

pronama_time
  ├ manifest.json
  ├ main.js
  ├ js
  │   └moment.js
  ├ icon
  │   ├ icon16.png
  │   ├ icon48.png
  │   ├ icon128.png
  │   └ icon128_white.png
  └ voice
    ├ kei2_voice_056.wav
    ├ kei2_voice_057.wav
    ├ kei2_voice_058.wav
     :
     :
    ├ kei2_voice_163.wav
    ├ kei2_voice_164.wav
    └ kei2_voice_165.wav

icon と voice は素材なので自分で作成した部分は、manifest.json と main.js のみになります。

全てのコードは GitHub に上げているので、ここでは部分部分を解説をしていきます。 ソースコード →pronama_time

manifest.json

chorome の拡張機能を作るためには必ず作成しなくていはいけないものです。json 形式でその拡張機能についての情報を書きます。

必須情報

拡張機能を作る際必須になるものは、 "manifest_version", "name", "version" です。

    "manifest_version": 2,
    "name": "プロ生ちゃんの時間!",
    "version": "1.0.1",

"manifest_version"は、マニフェストファイルのバージョンを指定するものです。現在作成する場合は 2 で問題ないです。
"name"はその通り、アプリ名です。公開した時の名前にもなります。 "version" はバージョンを管理するために用いる文字列です。

推奨情報

次に推奨されている情報です。

"description": "プロ生ちゃんが時間を教えてくれるよ!",
"icons": {
    "16": "icon/icon16.png",
    "48": "icon/icon48.png",
    "128": "icon/icon128.png"
},

"description"にはアプリの説明を書きます。公開時説明画像右側に表示されます。
"icons"はアイコンです。BMP、GIF、ICO、JPEG など WebKit でサポートされている形式であれば、どのような形式でも使用できます。

種別情報

この情報はどちらを使う、もしくはどちらも使わないという情報です。

  • browser_action
  • page_action

のどちらかを使います。browser_action は Google Chrome のツールバーに常駐するタイプです。一方 page_action は特定の条件にあったページにアクセスした際出て来るタイプです。

今回の拡張機能はブラウザに常駐するタイプのため、browser_action というものを用います。

"browser_action": {
    "default_icon": "icon/icon128.png",
    "default_title": "Pronama Time"
},

default_icon でアイコン画像, default_title でホバー時に出てくる名前を設定することができます。

default_title.png

必要に応じて入れる情報

permissions

chrome の API を利用する際に書きます。今回のアプリケーションでは通知を送るための "notifications" と、定期的に実行させるために "alarms" を用いました。

"permissions": [
    "notifications",
    "alarms"
],

background

拡張機能が起動している間、裏で実行される処理などを書きます。 今回のアプリケーションでは、main.js という名前のファイルを作成しそこに処理を記述していきます。 moment.js は、JavaScript で時間を簡単に扱えるようにしてくれるフレームワークです。

"scripts": [
    "js/moment.js",
    "main.js"
]

どうやら、バックグラウンドページ (Background Pages) の利用は推奨されていないようです。バックグラウンドページではなくイベントページの利用が奨められています。公式レファレンスのEvent Pagesによると、

When the event page is not actively doing something, it is unloaded, freeing memory and other system resources.

Event pages are available in the stable channel as of Chrome 22, and the performance advantages are significant, especially on low-power devices.

イベントページなら何もしていないときメモリを解放する。パフォーマンスのメリットは特に低電力デバイスで顕著である。

とのことです。

JavaScript ファイル

Chorome の API と JavaScript を用いてコードを書いていきます。

処理としては、

  1. 通知を作成する
  2. 通知したタイミングで次の通知を作成する

となっています。

また、クリックで時報の ON/OFF を切り替えることができるように alarm_flag というものを作成しました。

クリックされたときの処理

let alarm_flag = true;

chrome.browserAction.onClicked.addListener(() => {
  if (alarm_flag) {
    alarm_flag = false;
    set_property(alarm_flag);
  } else {
    alarm_flag = true;
    set_property(alarm_flag);
  }
});

初期状態では通知する設定として、クリックで alarm_flag = false; として通知しない設定にします。また、通知が OFF の状態だとすぐわかるようにアイコンを変更しています。

通知するイベントを作成する

function alarms_create() {
  const next_alarm = moment().add(1, "hour");
  next_alarm.set({ minute: 0, second: 0, millisecond: 0 });
  chrome.alarms.create("ALARM", {
    when: next_alarm.unix() * 1000
  });
}

chrome.alarms.onAlarm.addListener(alarm => {
  if (alarm.name == "ALARM" && alarm_flag) {
    run();
  }
});

通知を作成しています。chrome.alarms.create の when ではミリ秒で設定する必要があります。

行う処理をまとめる

function run() {
  const hour = moment().hour();
  const minute = moment().minute();

  notify(hour, minute);
  audio_play(hour);
}

まとめました。この関数を呼び出すと通知され、音声が流れます。

通知の作成

function notify(hour, minute) {
  const message = [
    "0時だ~日付変わっちゃった",
    "1時~そろそろ寝る~?",
    "2時! えっ? まだ寝ないよ",
    "3時でーす もしもし…",
    "4時…",
    "5時~",
    "6時",
    "7時! さぁ起きた起きた~",
    "8時! ほら早く起きなよ~",
    "9時! はりきっていこう!",
    "10時! さーこれからだー!",
    "11時! そうその調子!",
    "12時! あ~お腹減ったぁ",
    "13時 聞こえない?",
    "14時! あ~お腹いっぱい~",
    "15時…",
    "16時! さぁバリバリいくよ~",
    "17時! 日が沈んでくるかな",
    "18時! お疲れ様!",
    "19時! よーしゆっくり休むぞ~",
    "20時! あ、20時!",
    "21時! さーてプログラミングするかな~",
    "22時! テンションあがってきたー!",
    "23時! ひゃっほう!"
  ];

  const options = {
    iconUrl: "icon/icon128.png",
    type: "list",
    title: hour + "時" + minute + "分",
    message: "",
    priority: 1,
    items: [
      {
        title: message[hour],
        message: ""
      }
    ]
  };
  chrome.notifications.create("k_notification", options);
}

chrome.notifications.create で通知を作成することができます。ここでは通知の名前を  k_notification としました。

音声の再生

function audio_play(hour) {
  const time = `voice/kei2_voice_${("00" + (hour + 81)).slice(-3)}.wav`;
  const audio = new Audio(time);
  audio.play();
  audio.addEventListener(
    "ended",
    () => {
      chrome.notifications.clear("k_notification");
    },
    false
  );

  alarms_create();
}

音声が再生されたとき、次の通知を alarms_create(); で作成しています。

感想

簡単な拡張機能であれば、1 日で作成できます。ぜひ作ってみてはいかがでしょうか。 ソースコードはこちらです。pronama_time

今回作成したアプリは Chrome ウェブストアに公開しています。プロ生ちゃんの時間!

ただ、

  • 音量をアプリケーションで調整できない
  • chrome を起動していないと通知されない などの問題があるので、時報が欲しいという方は他の方々が作成したネイティブアプリなどを利用されるのが得策かと思われます。

参考

記事一覧ページへ