ANTIGRAVITY LABEN
記事一覧/アプリ開発
アプリ開発/2026-07-09上級

バックグラウンド更新は来ないことがある — 実行機会を測り、鮮度から設計をやり直した記録

BGTaskScheduler と WorkManager の実行機会は申請すれば得られるものではありません。実行率をログで測り、鮮度をSLOとして定義し、来ない前提の三層フォールバックへ組み直した設計を、計測コードとともに残します。

BGTaskSchedulerWorkManagerバックグラウンド処理Antigravity316アプリ設計2

プレミアム記事

壁紙アプリの利用者から「もう三日も同じ絵のままです」という連絡をいただいたのは、深夜のことでした。

私の手元の端末では、毎朝きちんと絵が切り替わっています。再現しません。ログを引き出して、ようやく事情が飲み込めました。バックグラウンド更新のタスクは、確かに登録されていました。ただ、一度も実行されていなかったのです。

登録は申請にすぎません。実行されるかどうかは、OS が決めます。頭では理解していたはずのその一行が、実際の端末の上ではまったく違う重みを持っていました。

「毎朝更新される」という前提が崩れていた

私が組んでいたのは、素朴な設計でした。深夜に BGAppRefreshTask を予約し、翌朝の起動前に次の壁紙を用意しておく。Android 側は PeriodicWorkRequest で 24 時間ごとに同じことをする。ウィジェットは、そうして用意された画像を読むだけ。

シミュレータでは完璧に動きます。私の iPhone でも動きます。私は毎日そのアプリを開き、充電しながら寝る人間だからです。

利用者は違いました。低電力モードを常用する方。アプリを週に一度しか開かない方。バッテリー最適化の対象にアプリを入れている方。そうした端末では、タスクは予約されたまま順番が回ってこず、ウィジェットは何日も前の画像を表示し続けます。

不具合ではありません。仕様どおりの挙動です。設計が現実を見誤っていただけでした。

実行機会は、申請ではなく抽選である

iOS と Android で言葉づかいは違いますが、構造はよく似ています。アプリは「やりたいこと」を宣言し、OS は端末の状態を見て、実行してよい瞬間を割り当てます。割り当てられない日もあります。

観点 iOS(BGTaskScheduler) Android(WorkManager)
最短間隔 earliestBeginDate は下限の希望。上限の保証はない PeriodicWorkRequest の最短は 15 分。実行は Doze の窓に依存
実行時間 App Refresh は概ね 30 秒程度で expirationHandler が呼ばれる Worker は 10 分。超えると isStopped が立つ
抑制する主因 低電力モード、アプリの起動頻度、充電・通信状態 Doze、App Standby Bucket、メーカー独自の最適化
再起動後 予約は保持される(アプリ更新時は再登録が必要) 永続化されるが、強制停止後は再登録まで動かない
失敗の可視性 実行されない事実はどこにも記録されない WorkInfo に状態は残るが、間引きの理由は残らない

最後の行が、この問題のいちばん厄介なところです。実行された記録は残ります。実行されなかった記録は、どこにも残りません。だから気づけません。

Android の App Standby Bucket は、その端末でのアプリの使われ方に応じて active / working_set / frequent / rare / restricted と段階が下がっていきます。週に一度しか開かれないアプリが rare に落ちれば、定期実行の窓は一日に一度あるかどうかまで狭まります。私のアプリはまさにそこにいました。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
実行機会の実測ログを取る Swift / Kotlin の最小実装と、そこから読み取れた実行率の傾向
「鮮度SLO」として p50 / p90 の経過時間を定義し、コードではなく契約でバックグラウンド更新を語る方法
更新が来ない前提で崩れない三層フォールバック設計と、計測をエージェントに委ねる際の境界線
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

アプリ開発2026-07-06
端末を熱くしないライブ壁紙 — WallpaperService の描画ループを電力予算から設計する
ライブ壁紙は常時描画のせいで電池を削りがちです。可視性・アイドル・熱状態の3軸で描画を止める WallpaperService.Engine の設計と、適応フレームレート制御による消費電力の実測を、個人開発の壁紙アプリの文脈でまとめました。
アプリ開発2026-07-05
自己デバッグのエージェントに、本番の広告を叩かせない — AdMob 無効トラフィックを断つ三層の遮断
Antigravity 2.0 の実ブラウザ自己デバッグが本番の AdMob 広告を描画すると、無効なトラフィックとして計上されます。テスト広告の強制・ネットワーク遮断・preflight ゲートの三層で、広告に触れない検証環境を作る手順を、実測値とともにまとめました。
アプリ開発2026-07-04
課金済みなのに広告が消えない — StoreKit 2 の Transaction.updates を起動直後に取りこぼす競合を Antigravity と塞いだ記録
起動直後に届く StoreKit 2 のトランザクションを取りこぼす競合を、View 寿命ではなくアプリ寿命にリスナーを固定して塞いだ実装記録。currentEntitlements での照合、finish() の徹底、StoreKitTest での回帰テスト化まで。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →