知識ゼロからSafariのWebPushを実装してみた:SDKのサポートつまづき編

2023/04/18に公開

前置き

先日(2023/03/27)Safariでのプッシュ通知実装がついに解禁されました。

プッシュ通知がSafariにも来る…かもと話していたのが4年前だったと記憶しているので、ついにリリースされてやったね🎉という気持ちです。

また最近ではTwitterのAPIもえげつない料金設定を引っ提げてきて、クライアントアプリで収益を得ている方にとっては阿鼻叫喚となった出来事がありましたね。私もお気に入りのクライアントアプリが召されて悲しかったです。

さて、今回はこちらのプッシュ通知を使って「モチベーション爆上げアプリ」を作ります。
匿名多数のネットの通りすがりの方が、押せば押すほどアプリ作成者(主に使用中する私)のモチベが上がっていく(?)アプリです。
※昔はやってたWeb拍手みたいなものをイメージしてます。

上の図は若干悪意がありますが、モチベーションが下がり気味な開発者に対して「応援してるぞ!」と背中を押すような効果が得られるものを作りたいですね。
それでは調査、実装編へどうぞ。

調査編

Appleの公式からドキュメントを読み込みます。
https://developer.apple.com/documentation/usernotifications

Safari はWeb プッシュ(クロスブラウザーの Push API、通知 API、および Service Worker 標準を使用するプッシュ通知) をサポートします。

とあるため、まずはPush API、通知 API、Service Workerについて抑えておきましょう。

MDNより抜粋

✨Push API

Push API を使用すると、プッシュ サービスを介して Web アプリケーションにプッシュ メッセージを送信できます。
アプリケーション サーバーは、Web アプリケーションまたはユーザー エージェントが非アクティブであっても、いつでもプッシュ メッセージを送信できます。
プッシュ サービスは、ユーザー エージェントへの確実で効率的な配信を保証します。プッシュ メッセージは、Web アプリケーションのオリジンで実行される Service Worker に配信されます。この Service Worker は、メッセージ内の情報を使用して、ローカルの状態を更新したり、ユーザーに通知を表示したりできます。
この仕様は、アプリケーション サーバーまたはユーザー エージェントがプッシュ サービスと対話する方法を説明する Web プッシュ プロトコルで使用するために設計されています。

✨通知 API

通知 API は、ウェブページやアプリからシステムレベルでページ外部に表示される通知を送ることを可能にします。これにより、アプリケーションがアイドルやバックグラウンドの状態であっても、アプリからユーザーに情報を送信することができます。

過去にプッシュ通知が悪用されることがあったため、ウェブブラウザーや開発者はこの問題を緩和するための対策を実装し始めています。通知を表示することの許可を求めるのは、ユーザーの操作 (ボタンをクリックするなど) の反応として行うべきです。

このように公式様もおっしゃっているので、私の人権が守られるような設計が必要なようですね!

加えて、 Chrome と Firefox では、サイトが安全なコンテキスト (すなわち HTTPS) ではない限り通知を要求することができず、また別オリジンの <iframe> から要求された通知を許可することができなくなりました。

✨Service Worker

サービスワーカーは、基本的にウェブアプリケーション、ブラウザー、そして(もし繋がっていれば)ネットワークの間に介在するプロキシサーバーのように振る舞います。これは、よりよいオフラインの操作性を可能にするように意図されており、ネットワークのリクエストに介在してネットワークの使用可否の状況に基づいて適切な対応を取ったり、サーバー上にある資産を更新したりします。また、プッシュ通知やバックグラウンド同期の API 群へのアクセスもできるようになります。

ちなみに、

Apple Developer Program に参加する必要はありません。

とのことなので、無償で実装できる予定です。ヤッタネ

実装編

手軽に実装できそうだったので、今回はflutterを使っていきます。
flutterの設定なんぞ2年以上前から触っていませんが、環境変数を通し直せばすぐに動くでしょう。多分。


…flutter doctorの結果からは目を逸らして、FCMでウェブ認証情報を作ってしまいましょう。
ここで作成した、ウェブプッシュ証明書がFirebaseのトークン取得時に必要になります。

flutter update / brew upgrade dart / firebase login など必要だったりしますが、
各々で苦しんでセットアップしてください🙏
このガイドに沿ってやればどうにかなります。
https://firebase.google.com/docs/flutter/setup?hl=ja&platform=web

デモアプリの内容に対してトークンの設定をすればおおむね完了です👍
web/firebase-messaging-sw.jsについては、ファイルがないとコンソールエラーが吐かれるので、messaging apiのみを使用する場合でも作っておいておきましょう。

lib/main.dart
void main() async {
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  // 前段でウェブプッシュ証明書にて取得した鍵を設定する
  final fcmToken = await FirebaseMessaging.instance.getToken(vapidKey: 'your_vapid_key');
  FirebaseMessaging.instance.onTokenRefresh
    .listen((fcmToken) {
      logger.v("fcmToken: $fcmToken");
    })
    .onError((err) {
      // Error getting token.
      logger.v("err: ${err}");
    });
  runApp(const MyApp());
}

コードの全体はこちらです。
https://github.com/ixap2i/push_notification

コードの実装が完了したら、キャンペーンを登録してデモ通知を送ってみましょう。
ほぼ時間通り(設定時間からおおむね5分後)に素敵な通知が来ました。

おまけ

サブミッションとして、Safariでのプッシュ通知実装がありましたので、試しに動かしてみます。

ワクワク…

あれ、動かないぞ…
https://firebase.google.com/docs/web/environments-js-sdk?hl=ja

_人人人人人人人人人人人人人人人_
>    Cloud Messaging    <
> Safari非対応(2023年4月現在) <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄
	
デプロイするまで挑戦は続く…
	

Overview URL
https://web.dev/push-notifications-overview/

終わりに

ということで、途中から手段と目的が入れ替わってしまった話でした🙏笑
技術選定は下調べをしっかりとやりましょう!(己への戒め)


株式会社クロスビットでは、デスクレスワーカーのためのHR管理プラットフォームを開発しています。
一緒に開発を行ってくれる各ポジションのエンジニアを募集中です。
https://x-bit.co.jp/recruit/
https://herp.careers/v1/xbit
https://note.com/xbit_recruit

クロスビットテックブログ

Discussion