◉RORK LABEN
●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Expo SDK 58 が 10/15 に正式リリースされました(Beta は 09/15 から)。上げる前に依存の対応状況を確認しましょう●SDK 58 ISSUE — Android ウィジェットが定期更新されない、Stripe が静的リンクになるなど初期報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Expo SDK 58 が 10/15 に正式リリースされました(Beta は 09/15 から)。上げる前に依存の対応状況を確認しましょう●SDK 58 ISSUE — Android ウィジェットが定期更新されない、Stripe が静的リンクになるなど初期報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…
記事一覧/アプリ開発
◇ アプリ開発/2026-10-21中級

iOS では動く expo-widgets が Android のビルドだけで落ちる — 版の固定と除外、どちらで逃げるかの判断

expo-widgets を 58.0.17 以降に上げると Android だけ Kotlin のコンパイルで止まる報告があります。症状の見分け方、版の固定と autolinking 除外の使い分け、手元で判定できる確認スクリプトをまとめました。

expo-widgetsExpo SDK 583Android58Gradle3トラブルシューティング90

iOS のシミュレータではウィジェットが問題なく出ているのに、npx expo run:android を実行した瞬間に Kotlin のエラーが並びます。依存を少し上げただけで、昨日まで通っていたビルドが止まってしまうのです。

そんな状況になったときのために、いま GitHub で報告されている expo-widgets の Android 側の不具合を、切り分けの手順としてまとめます。私自身はこの不具合を再現しておらず、以下は Issue の本文と、手元で動作を確かめたスクリプトに基づく内容です。

症状:どのエラーが出たら疑うか

報告されているのは expo/expo の Issue #51653 です(2026年10月16日に起票、私が確認した10月20日時点では Open)。

  • 対象は expo-widgets の 58.0.17 以降(報告者は 58.0.18 でも確認)。58.0.16 は影響なしとされています
  • Android のネイティブビルドだけで起き、iOS は影響なしとされています
  • Kotlin のコンパイルで Unresolved reference 'jakex7'、Unresolved reference 'PeekNotificationViews'、Unresolved reference 'setPeekContent' といった行が CustomNotificationBuilder.kt と CustomNotificationRenderer.kt から出ます

報告者の説明では、原因は依存の名前の食い違いです。通知まわりの新しいコードが io.github.jakex7.peek を import している一方で、build.gradle が実際に取り込んでいるのは io.github.expo.peek 側の部品(0.3.2)で、jakex7 側は Maven Central で 0.3.0 までしかなく依存にも宣言されていない、という指摘です。

つまり、アプリのコードを疑っても何も出てきません。パッケージの特定の版が Android でだけ壊れているという切り分けになります。エラーに上の参照名が含まれていれば、この件を第一候補にしてかまいません。

逃げ道は2つ:版を固定するか、Android から外すか

Issue に回避策として示されているのは autolinking からの除外です。版の固定は、58.0.16 に該当の import がないという報告から導ける手段で、Issue 自体が勧めているわけではありません。

状況選ぶ手手元で起きること
Android でもウィジェットを出したい58.0.16 に固定する報告上は影響なしの版に戻ります。次に版を上げるまで、新しい通知機能は使えません
ウィジェットは iOS だけでよいAndroid の autolinking から除外するAndroid のビルドに expo-widgets が入らなくなり、版は最新のまま使えます
どちらでもない(まだ使っていない)導入を保留するIssue が解消してから入れても遅くありません

私なら、まず「Android にウィジェットが本当に必要か」を先に決めます。壁紙アプリのように、ウィジェットが iOS 側の付加機能にすぎない場合は、除外のほうが後始末が少ないと感じています。

版を固定する場合

^ や ~ が付いたままだと、次の npm install で 58.0.17 以降に戻ってしまいます。範囲指定を外して、完全な版番号にします。

npm install expo-widgets@58.0.16 --save-exact

その後、package.json の expo-widgets が "58.0.16" のように記号なしになっていることを確認してください。Issue の再現手順にあるコンパイルタスクで、Android 側が通るかも確かめます。

npx expo prebuild -p android
cd android && ./gradlew :expo-widgets:compileDebugKotlin

Android から外す場合

iOS だけでウィジェットを使うなら、package.json に次を足します。Issue で報告者が示している回避策です。

{
  "expo": {
    "autolinking": {
      "android": {
        "exclude": ["expo-widgets"]
      }
    }
  }
}

設定を足したら、Android のフォルダを作り直します。

npx expo prebuild -p android --clean

--clean は既存の android フォルダを消してから作り直します。手でネイティブ側を書き換えている場合は、先にバックアップを取ってください。また、Android 側で expo-widgets の関数を呼んでいるコードがあれば、Platform.OS で分けておく必要があります。除外後の挙動は私の手元では確かめておらず、この点は各自のプロジェクトでの確認をお願いしたいところです。

自分のプロジェクトが対象かを一発で判定する

「いまの版がどれで、どう逃げているのか」を毎回 package.json と node_modules で見比べるのは手間です。そこで、判定だけを行う小さなスクリプトを用意しました。Node だけで動き、ネットワークには接続しません。

// check-expo-widgets-android.mjs
// 使い方: node check-expo-widgets-android.mjs [プロジェクトのパス]
import { readFileSync, existsSync } from "node:fs";
import { join, resolve } from "node:path";
 
const root = resolve(process.argv[2] ?? ".");
const readJson = (p) => JSON.parse(readFileSync(p, "utf8"));
 
const pkgPath = join(root, "package.json");
if (!existsSync(pkgPath)) {
  console.error(`package.json が見つかりません: ${pkgPath}`);
  process.exit(2);
}
const pkg = readJson(pkgPath);
const declared = { ...pkg.dependencies, ...pkg.devDependencies }["expo-widgets"];
if (!declared) {
  console.log("expo-widgets は依存に入っていません。この問題の対象外です。");
  process.exit(0);
}
 
const installedPath = join(root, "node_modules", "expo-widgets", "package.json");
if (!existsSync(installedPath)) {
  console.error("node_modules に expo-widgets がありません。先に npm install を実行してください。");
  process.exit(2);
}
const installed = readJson(installedPath).version;
const [major, minor, patch] = installed.split(/[.-]/).map(Number);
 
const excluded = (pkg.expo?.autolinking?.android?.exclude ?? []).includes("expo-widgets");
const pinned = /^\d+\.\d+\.\d+$/.test(declared); // ^ や ~ が付いていなければ固定
const brokenRange = major === 58 && minor === 0 && patch >= 17;
 
console.log(`宣言: ${declared}(${pinned ? "固定" : "範囲指定"})`);
console.log(`導入済み: ${installed}`);
console.log(`Android の autolinking から除外: ${excluded ? "はい" : "いいえ"}`);
 
if (excluded) {
  console.log("判定: OK(Android には expo-widgets を入れない設定です)");
} else if (!brokenRange) {
  console.log(
    pinned
      ? "判定: OK(報告のある 58.0.17 以降ではなく、版も固定されています)"
      : "判定: 注意(今は問題のない版ですが、範囲指定なので次回の install で 58.0.17 以降に上がる可能性があります)"
  );
  process.exit(pinned ? 0 : 1);
} else {
  console.log("判定: 要対処(58.0.17 以降です。Android のビルドで Kotlin のコンパイルエラーが報告されています)");
  process.exit(1);
}

終了コードは、問題なしが 0、対処または注意が 1、前提が足りない場合が 2 です。CI の最初の手順に置けば、依存の自動更新が 58.0.17 以降を持ち込んだ時点で、Gradle を回す前に止められます。ビルドが数分走ってから落ちるより、数秒で気づけるほうがずっと楽です。

私は 58.0.18・58.0.16・範囲指定・除外ありの4パターンの模擬プロジェクトを作り、上の4つの判定がそれぞれ想定どおりに出ることを確かめました。

もう一つ、同じ時期の報告:Android では時刻で更新されない

別の Issue(#51633)では、Android の expo-widgets で updateTimeline() が何もせず、生成される XML の updatePeriodMillis も 0 に固定されているという指摘があります。報告者の整理では、アプリが起動している間に updateSnapshot() を呼んだときだけ表示が変わる状態です。こちらも私が見た時点では Open で、メンテナーの返答は付いていませんでした。

ここから言えるのは、Android で「毎朝0時に切り替わる壁紙ウィジェット」のような時刻駆動の更新を、expo-widgets に任せる設計は今は避けたほうがよい、という判断です。どちらの Issue も状況が変わりうるので、手を入れる前に最新の状態を見ておくと安心です。

iOS 側の更新の仕組みについては、WidgetKit のタイムラインを更新予算と向き合って設計する — 壁紙アプリのウィジェットが止まった理由 に整理してあります。

まとめ:今日やること

  1. node check-expo-widgets-android.mjs を実行して、いまの状態を確かめる
  2. Android にウィジェットが必要なら 58.0.16 に固定し、不要なら autolinking から除外する
  3. 依存を上げる前に、Expo SDK 58 に上げる前に、自分のコードで消える API を一覧にしておく の確認もあわせて行う

Android のビルド失敗がキャッシュ由来のように見える場合は、EAS Build だけ「No matching variant」で落ちるとき、まず疑う手元の android/build も合わせてご覧ください。

「落ちた原因がアプリか依存の特定の版か」を、先に切り分けること。 これだけで、半日の迷子がだいぶ減ります。

出典:expo/expo Issue #51653、#51633(いずれも2026年10月20日に本文を確認)。

シェア

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

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

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

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

◇ アプリ開発2026-10-15
EAS Build だけ「No matching variant」で落ちるとき、まず疑う手元の android/build
手元の Gradle は通るのに、EAS Build の Android だけが「No matching variant of project」で止まる。GitHub の報告を読み比べ、Windows で生成した autolinking のキャッシュが Linux のビルド機へ渡っていた経路と、ビルドを投げる前に確かめる診断スクリプトをまとめました。
⬡ 開発ツール2026-10-21
iOS では時刻どおりに変わるウィジェットが、Android では「Initial」のまま動かない
expo-widgets の updateTimeline は Android では何も起こさず、生成される XML の updatePeriodMillis も 0 です。症状の見分け方、updateSnapshot で補える範囲、設計を切り替える判断と確認スクリプトをまとめました。
◇ アプリ開発2026-10-18
debug では動くのに、release の起動だけ「見つからない」で落ちました。名前の文字列で引いていた資源が、縮小で消えていたためです
release ビルドだけ、起動時に資源が見つからず落ちる。原因は、名前の文字列で引いていた画像や音がリソース縮小で消えていたことでした。keep.xml を prebuild で書き出す設定と、ビルド後に確かめる検査を組みました。