アプリを上書き更新したのに、画面だけ古いままだった話
アプリを上書き更新したのに、画面だけ古いままだった話
新しいAPK(Androidアプリのインストール用ファイル)を入れたはずなのに、画面が変わらない。
しろまえ殿は、配布しているAndroidアプリを更新するたびに、この症状に悩まされていた。
インストールログを見る限り、更新自体はできている。バージョンも上がっている。
なのに、開くと前のままの画面が出る。
「3回試したけど直らない」
しろまえ殿は、そう言ってクルーに調査を頼んだ。
疑うところを間違えていた
最初、クルーはビルドの取り違えを疑った。
このアプリは、Webブラウザ向けのビルドと、アプリ向けのビルドの2種類を作り分けていた。
どちらか片方を間違えて詰め込んでいないか、まずそこを確認した。
結果は白だった。ビルドは正しいものが入っていた。
しろまえ殿は、次に「上書きインストールの仕組みそのもの」を疑うようディレクションした。
このアプリは、PWA(Webページをアプリのように動かす仕組み)の技術をベースに、Capacitor(Webの技術でネイティブアプリを作る枠組み)を使ってアプリ化したものだった。
裏側では、Service Worker(ブラウザやアプリの中で常駐し、通信やキャッシュを肩代わりする仕組み)が動いている。
「起動時に1回登録するだけ」の罠
Service Workerの初期設定を読み直すと、register()(Service Workerを有効にする関数)を1回呼ぶだけの、最小限の書き方になっていた。
これは、更新を検知した後の「リロードして反映する」処理を、そもそも持っていなかった。
普通のWebブラウザなら、タブを開き直せば新しいService Workerに切り替わる。
ところが、アプリのWebView(アプリの中でWebページを表示する部品)には、この「タブを開き直す」機会がない。
アプリを完全に終了して、もう一度開くまで、register()は再実行されない。
つまり、新しいService Workerは裏側で静かにインストールされ、有効になっている。だが、今表示されている画面は、古いJavaScriptのまま動き続けている。
たとえば、旅館の裏で新しい料理長に交代していても、すでにホールへ運ばれた皿は、前の料理長が作ったものがそのまま出てくる。客が新しい料理を食べるには、次の注文(=アプリの再起動)を待つしかない。
だから「1回開いただけでは直らない、2回開いてやっと反映される」という、利用者にとって分かりにくい挙動になっていた。
直し方は、登録の仕方を変えること
しろまえ殿は、自動まかせの設定から、明示的に制御する書き方へ変更させた。
自動登録をオフにし、アプリの起動コードの中で、更新検知後に自動でリロードしてくれる仕組みを、明示的に呼び出す形にした。
これで、新しいService Workerへの切り替わりを検知した際、今開いている画面自身が自動でリロードされるようになった。
新規インストール時にはリロードが走らないことも確認し、初回起動の体験を壊していないことも確かめた。
気をつけたいこと
- Service Workerの初期設定は「動いているように見える」だけでは足りない。更新検知後にリロードまで面倒を見る設定になっているかを確認する。
- WebViewには、ブラウザの「タブの開き直し」に相当する自然な操作が無い。ネイティブアプリ化する際は、この前提の違いを忘れない。
- 「1回では直らないが2回で直る」ような挙動は、利用者への案内文にも明記しておく。恒久策が入るまでの当面の回避策として有効。
- バージョン番号を毎回きちんと上げる。「どのビルドが今動いているのか」が分からないと、この種の不具合の切り分け自体ができなくなる。
新しい版を配っただけでは、利用者の手元まで届いたことにはならない。
しろまえ殿がそう言って調査を続けさせたことで、見た目の裏にあった「反映の仕組み」そのものの不備にたどり着けた。