JOURNAL

スマホのブラウザ通知が「届いたり届かなかったり」する理由を調べてみた

正直に告白すると、これはSPLIT TIMERを作っていたとき一番泣かされた問題です。「通知、届くときと届かないときあるな…」というのに気づいたのが夜11時ぐらいで、その日は結局解決しないまま寝ました。次の日改めて調べ直して分かったことを、備忘録がてらまとめておきます。

まずOSを疑った

スマホは基本、バッテリーを守るために裏で動いてるタブの処理をがんがん間引きます。こっちがどれだけ丁寧に通知を送るコードを書いても、OSが「まあ後でいいでしょ」と判断すれば普通に後回しにされる。

ここに関してはWeb側にできることはほぼありません。

正直「そういうものだと諦める」以外の選択肢がありませんでした。

次はブラウザの差を疑った

特にモバイルSafariが厄介で、WebからのPush通知対応が他よりだいぶ遅れて入った経緯があるらしく、「同じサイトなのに、iPhoneだと通知の挙動が違う」みたいな現象にちょくちょく出くわします。テストしてるときに「あれ、さっきAndroidでは鳴ったのに」と一人でぶつぶつ言いながら検証していたのを覚えています。

犯人はtagだった

あと地味に厄介だったのが、Notifications APIのtagという仕組み。同じtagの通知は「重複」扱いされて、古いのが新しいのに差し替わったり、そもそも出なかったりします。短時間に似た通知を連発すると起きる現象で、これに気づくまで「なんでたまに通知が消えるんだ…」と原因不明のバグとして半日ぐらい格闘していました。

原因が分かった瞬間の「そういうことか」感はちょっと快感でした。同時に「先にドキュメント読んどけよ自分」とも思いました。

結論:音に頼るしかない

通知ごとにIDを変えたりrequireInteractionを指定したりと、コード側でできる工夫は一通り入れました。それでも、最終的にはOSとブラウザの気分次第という部分がどうしても残ります。

100%は無理。

だからSPLIT TIMERでは、許可も不要で確実に鳴ってくれる「音」をメインの通知手段に据えて、画面通知はあくまでオマケ扱いにしました。この結論にたどり着くまでに丸2日溶かしたので、同じ沼にハマってる人がいたら「音に頼るのが正解です」とだけ伝えたいです。

原因 やったこと
OS側のバックグラウンド間引き 諦めて音をメイン手段に
モバイルSafariのPush対応の遅れ ブラウザ差を前提に設計
tagによる重複抑制 通知ごとに識別子を分ける

もっと詳しく仕様を追いたい人は、MDNのNotifications APIのページが一番まとまっています。