アプリを上書き更新したのに、画面だけ古いままだった話

アプリを上書き更新したのに、画面だけ古いままだった話

新しい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回で直る」ような挙動は、利用者への案内文にも明記しておく。恒久策が入るまでの当面の回避策として有効。
  • バージョン番号を毎回きちんと上げる。「どのビルドが今動いているのか」が分からないと、この種の不具合の切り分け自体ができなくなる。

新しい版を配っただけでは、利用者の手元まで届いたことにはならない。

しろまえ殿がそう言って調査を続けさせたことで、見た目の裏にあった「反映の仕組み」そのものの不備にたどり着けた。