RORK LABEN
NATIVE — Rork Max では AR / LiDAR スキャン、Metal を使った 3D、Dynamic Island、Siri Intents、HealthKit、NFC、App Clips、Core ML まで届きますIOS27 — iOS 27 Developer Beta 4 で Siri AI の対象が iPhone 15 Pro / 15 Pro Max・16 シリーズ・17 系へ広がり、応答が初期ベータより明確に速くなりましたDESIGN — iOS・iPadOS・macOS 27 向けの Apple 純正デザインキットが Figma と Sketch 向けに公開されました。新 OS の UI を組む段階で参照できますCANARY — Android 17(Cinnamon Bun)は従来の Developer Preview を廃し、継続更新される Canary ビルドへ移行しました。検証のタイミング設計が変わりますSPARK — Android 17 の Gemini Spark は、アプリを直接操作して配車の予約や注文といった複合的な作業を自動化しますSCALE — Rork は a16z から $2.8M を調達し、月間訪問は74万件規模まで伸びていますNATIVE — Rork Max では AR / LiDAR スキャン、Metal を使った 3D、Dynamic Island、Siri Intents、HealthKit、NFC、App Clips、Core ML まで届きますIOS27 — iOS 27 Developer Beta 4 で Siri AI の対象が iPhone 15 Pro / 15 Pro Max・16 シリーズ・17 系へ広がり、応答が初期ベータより明確に速くなりましたDESIGN — iOS・iPadOS・macOS 27 向けの Apple 純正デザインキットが Figma と Sketch 向けに公開されました。新 OS の UI を組む段階で参照できますCANARY — Android 17(Cinnamon Bun)は従来の Developer Preview を廃し、継続更新される Canary ビルドへ移行しました。検証のタイミング設計が変わりますSPARK — Android 17 の Gemini Spark は、アプリを直接操作して配車の予約や注文といった複合的な作業を自動化しますSCALE — Rork は a16z から $2.8M を調達し、月間訪問は74万件規模まで伸びています
記事一覧/開発ツール
開発ツール/2026-06-14上級

アプリを開かなくても更新される、を Expo で実際に届ける — Background Task の現実的な設計

Rork が生成する Expo アプリで『毎朝コンテンツが更新される』体験を作ろうとすると、iOS のバックグラウンド実行は思ったほど律儀に動きません。expo-background-task の最小実装と、実行されない前提で破綻しない設計をまとめました。

Rork525Expo156Background TaskBGTaskScheduler3iOS109個人開発191

プレミアム記事

壁紙アプリを個人開発で運用していて、いちばん要望が多かったのが「毎朝、開かなくても新しい壁紙に変わっていてほしい」でした。素朴に考えれば、バックグラウンドで定期実行して画像を差し替えればよさそうです。ところが iOS でこれを真面目に作ると、「昨日は更新されたのに今日は変わっていない」という再現性のない不具合報告に悩まされることになります。

原因は実装のバグではなく、iOS のバックグラウンド実行そのものが「いつ走るか分からない」前提で設計されているからです。Rork が生成するのは Expo アプリですが、その下では iOS の BGTaskScheduler が動いており、ここの気まぐれさを理解しないまま作ると、ユーザー体験が運任せになります。実行されない前提で破綻しない更新体験の作り方を、配線と判断の両面で、私自身が壁紙アプリで踏んだ落とし穴とともに追っていきます。

「毎朝更新されるはず」が更新されない理由

iOS のバックグラウンドタスクは、開発者が時刻を指定して必ず走らせられるものではありません。システムが、端末の使用パターン・バッテリー・ネットワーク状況を見て「今なら走らせてよい」と判断したときにだけ実行されます。

つまり、毎日アプリを開くユーザーには比較的よく走り、ほとんど開かないユーザーにはめったに走りません。皮肉なことに、いちばん「開かなくても更新されてほしい」休眠ユーザーほど、バックグラウンドが回らないのです。この非対称を最初に受け入れないと、設計を間違えます。

expo-background-task の最小登録

現在の Expo では、非推奨になった expo-background-fetch ではなく expo-background-task(内部で BGTaskScheduler / WorkManager を使う)を用います。タスク本体は expo-task-manager で定義します。

import * as TaskManager from "expo-task-manager";
import * as BackgroundTask from "expo-background-task";
 
const REFRESH_TASK = "daily-wallpaper-refresh";
 
TaskManager.defineTask(REFRESH_TASK, async () => {
  try {
    const updated = await fetchAndCacheTodaysWallpaper();
    // 成功・失敗を必ず返す。返さないと iOS が将来の実行枠を絞る
    return updated
      ? BackgroundTask.BackgroundTaskResult.Success
      : BackgroundTask.BackgroundTaskResult.Failed;
  } catch {
    return BackgroundTask.BackgroundTaskResult.Failed;
  }
});
 
export async function registerRefreshTask() {
  const status = await BackgroundTask.getStatusAsync();
  if (status !== BackgroundTask.BackgroundTaskStatus.Available) return;
  await BackgroundTask.registerTaskAsync(REFRESH_TASK, {
    minimumInterval: 60 * 12, // 単位は分。ここでは12時間
  });
}

app.json 側では iOS の UIBackgroundModesprocessing を含める必要があります。Expo なら infoPlist に書きます。

{
  "expo": {
    "ios": {
      "infoPlist": {
        "UIBackgroundModes": ["fetch", "processing"],
        "BGTaskSchedulerPermittedIdentifiers": ["daily-wallpaper-refresh"]
      }
    }
  }
}

BGTaskSchedulerPermittedIdentifiers にタスク ID を書き忘れると、登録自体は通るのに実機で一度も走らない、という静かな失敗になります。私はここで半日溶かしました。

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

この記事の続きを読む

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

この記事で得られること
expo-background-task と expo-task-manager の最小登録を、UIBackgroundModes の設定込みで動く形で組めるようになります
minimumInterval が『最短間隔』であって『実行保証』ではないという iOS の挙動を、Low Power Mode・使用頻度・充電状態という具体条件で理解できます
バックグラウンドが走らなくても破綻しないフォアグラウンド補完の二段構えを、壁紙アプリの自動更新を例に実装できます
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

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

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

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

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

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

関連記事

開発ツール2026-05-28
Rork アプリで iOS の BGTaskScheduler.submit が Error Code=1 で失敗するときの切り分け手順
Rork で作った iOS アプリで BGTaskScheduler.submit が Error Code=1 (Unavailable) を返してバックグラウンド更新が動かないときに、原因をひとつずつ潰していくための実用チェックリストです。
開発ツール2026-07-27
最低サポート iOS をいつ上げるか — 利用率ではなく、コードに残った分岐の数で決める
最低サポート OS の引き上げを利用率で判断すると、毎年同じ結論になって先送りが続きます。OS 分岐に注記を付けて棚卸しし、引き上げ先ごとに消せる分岐を数えるスクリプトと、引き上げ後に見る指標をまとめました。
開発ツール2026-07-10
クラッシュとして記録されない強制終了 — Rork アプリの JetsamEvent を読む
Crashlytics には何も出ていないのにレビューで「勝手に閉じる」と書かれる。その多くはメモリ超過による OS からの強制終了です。JetsamEvent レポートの読み方と、画像中心アプリのメモリ上限を実測から設計する手順をまとめます。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →