◉RORK LABEN
●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●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 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…
記事一覧/開発ツール
⬡ 開発ツール/2026-05-10中級

Rork で expo-image-picker が起動しない — Info.plist と権限まわりで詰まった実例

Rork で生成したアプリの画像ピッカーボタンを押しても何も起こらない。Info.plist のキー不足、権限取得の順番、iOS 14 以降の Limited Photo Access、Android 13+ のメディア権限まで、実際に詰まった原因と解決策を整理しました。

expo-image-pickerInfo.plist6権限7iOS115Android55トラブルシューティング85

Rork が生成したアプリの「画像を選ぶ」ボタンを押しても、シミュレータでは反応するのに、TestFlight のビルドだとボタンを押しても何も起こらありません。先日、ちょうどそのパターンで丸一日溶かしました。

私は2014年から壁紙系のアプリを中心に個人開発を続けていて、累計5,000万DLを超えるアプリ群の中でも画像ピッカーは10本以上のアプリで使っています。それでも、Rork の AI が出してくる expo-image-picker のコードをそのまま信じて Info.plist の存在を忘れていると、毎回同じ場所で止まります。原因は概ね4つに集約できますので、上から順に潰していくと多くのケースで動くようになります。

原因1: Info.plist のキーが入っていない(iOS で最初に詰まる場所)

iOS 10 以降、フォトライブラリやカメラへのアクセスには Info.plist に「使用理由の文字列」が必須です。Expo / Rork で生成されたアプリでも、最初にビルドした段階ではキー自体が入っていないことが普通にあります。

詰まり方の特徴は、シミュレータでは動くのに実機(特に TestFlight 経由のビルド)でボタンを押すと無反応、もしくはアプリがそのままクラッシュするというものです。

app.json に以下のように infoPlist を書き足します。

{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSPhotoLibraryUsageDescription": "プロフィール画像を選ぶためにフォトライブラリへのアクセスを許可してください。",
        "NSCameraUsageDescription": "プロフィール写真を撮影するためにカメラへのアクセスを許可してください。",
        "NSPhotoLibraryAddUsageDescription": "アプリで作成した画像をフォトライブラリへ保存するために必要です。"
      }
    }
  }
}

書き換えただけでは反映されません。Expo Go なら開発サーバ再起動、ネイティブビルドの場合は EAS Build でビルドし直す必要があります。「app.json を変えたのに変わらない」という相談をいただくとき、9割はビルドし直していないだけ、というのが私の経験則です。

原因2: 権限を先に取らずに launchImageLibraryAsync を呼んでいる

Rork が生成するコードでよく見かけるのが、権限ダイアログを出さずにいきなり launchImageLibraryAsync を呼ぶパターンです。プラットフォームによっては「権限がないので無言で結果なしを返す」挙動になり、ボタンを押しても何も起きないように見えます。

正しい呼び出し順は次の通りです。

import * as ImagePicker from 'expo-image-picker';
import { Alert, Linking } from 'react-native';
 
async function pickImage() {
  // 1. 先に権限を要求する(拒否時はガイドを出して return)
  const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
 
  if (status !== 'granted') {
    Alert.alert(
      '写真へのアクセスが許可されていません',
      '設定アプリから写真へのアクセスを許可してください。',
      [
        { text: 'キャンセル', style: 'cancel' },
        { text: '設定を開く', onPress: () => Linking.openSettings() },
      ]
    );
    return;
  }
 
  // 2. 権限が取れたあとでピッカーを起動する
  const result = await ImagePicker.launchImageLibraryAsync({
    mediaTypes: ImagePicker.MediaTypeOptions.Images,
    allowsEditing: true,
    quality: 0.8,
  });
 
  if (!result.canceled) {
    // 期待する出力: result.assets[0].uri に file:// から始まる画像のURIが入る
    console.log(result.assets[0].uri);
  }
}

特に重要なのは、権限が拒否されたときに「設定アプリへ誘導するダイアログを出す」ことです。一度「許可しない」を選んだユーザーは、その後二度とOSの権限ダイアログが出てこないので、アプリ側で道筋を示してあげる必要があります。これを忘れると「ボタンを押しても何も起こらない」というレビュー☆1がそのままアプリに刻まれます。私の壁紙アプリでも、AdMob の月収ピーク時にこのレビューが付いたことが何度かあり、対応漏れの怖さを身に染みて学びました。

原因3: iOS 14 以降の Limited Photo Access の罠

iOS 14 で「写真の一部だけ許可する」モード(Limited Photo Access)が追加されました。ユーザーが「選択した写真のみ」を選ぶと、アプリ側からは許可された写真だけしか見えません。

requestMediaLibraryPermissionsAsync() は Limited のときも granted を返すので、コード上は「許可された」ことになります。ただし、ユーザー側から見ると「写真がほとんど表示されない」状態になります。これに気付かず「画像ピッカーが壊れた」と判定して問い合わせが来るパターンを、私自身も何度か経験しました。

Limited のときに「すべての写真へのアクセスに変更する」ためのフローを追加したい場合は、iOS のネイティブ API である PHPhotoLibrary.shared().presentLimitedLibraryPicker(from:) を呼ぶ必要があります。Expo の純正モジュールでは抽象化されていないため、個人開発の現場では「ユーザーが Limited を選んでもアプリの体験が崩れない設計」にする方が現実的だと考えています。

具体的には次のような対応が安全です。

  • 結果が空でも「写真が選択されていません」と説明文を出す
  • 設定画面から「すべての写真」へ変更する手順をスクショ付きで案内する
  • アプリのオンボーディングで「すべての写真」を推奨する文言を入れる

権限まわりの設計の根本的な考え方については、Rork のアプリで権限ダイアログが表示されないときの確認ポイント も合わせて参考になります。

原因4: Android 13+ のメディアアクセス権限の変化

Android 12 までは READ_EXTERNAL_STORAGE で写真にアクセスできていましたが、Android 13(API レベル 33)以降は READ_MEDIA_IMAGES / READ_MEDIA_VIDEO / READ_MEDIA_AUDIO に分割されました。

Expo SDK 49 以降の expo-image-picker は内部的に新しい権限へ追従してくれますが、app.json の android.permissions を旧いまま書いているとビルド段階で警告が出たり、Play Store の審査で「不要な権限を要求している」と指摘されたりします。

{
  "expo": {
    "android": {
      "permissions": [
        "android.permission.READ_MEDIA_IMAGES",
        "android.permission.READ_MEDIA_VIDEO"
      ]
    }
  }
}

注意したいのは、Android 13+ で導入された「Photo Picker」(システム提供のピッカー)を使うとそもそもこれらの権限が不要になる点です。Expo の expo-image-picker は Android 13+ で自動的に Photo Picker を使う設計になっているので、シンプルなプロフィール写真の選択だけなら権限要求を完全に省略できます。launchImageLibraryAsync の呼び出しだけで動くため、起動しないと感じたときは「そもそも権限要求が走っていない」可能性も視野に入れていただきたいところです。

Expo のネイティブビルド全体の構造を見直したいときは Expo の prebuild とカスタムネイティブモジュールの取り扱い と Rork で環境変数を扱うときの設定エラー対処 もあわせて確認しておくと、「Info.plist だけの問題ではなかった」と後から気付くケースを減らせます。

まずやること1つだけ

長くなりましたが、画像ピッカーが起動しないと感じたら、最初にやるべきは「app.json の ios.infoPlist に NSPhotoLibraryUsageDescription を書き足してから EAS Build をかけ直す」ことです。私自身、もう何度この一手で解決してきたか分かりません。

権限ダイアログ周りの設計は、React Native の入門書では薄く扱われがちな領域です。

同じ場所で詰まっている方の作業時間が、少しでも短くなれば嬉しいです。お読みいただきありがとうございました。

シェア

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

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

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

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

関連記事

⬡ 開発ツール2026-05-18
Rork で Linking.canOpenURL が iOS だけ false を返す ─ LSApplicationQueriesSchemes 設定漏れの直し方
TikTok や X、LINE 公式アカウントへ飛ばす実装が iOS の本番ビルドだけで動かない症状を、LSApplicationQueriesSchemes の追加と EAS Build の再生成手順で確実に解消します。
⬡ 開発ツール2026-10-07
日本語の見出しだけ太字にならない — Android で fontWeight が効かないときの切り分けと直し方
Rork で作ったアプリで、iPhone では太字なのに Android では日本語の見出しが細いままになる症状の切り分け記事です。原因の見分け方、fontFamily を重みごとに分ける直し方、確認用コードを載せています。
⬡ 開発ツール2026-09-21
exit code 0 で止まるビルド — ログを黙らせていた設定と、空ファイルを通した存在チェック
eas build --local が exit code 0 but produced no further output で止まる件と、0 バイトのスタブが埋め込まれず dyld で落ちる件。どちらも原因は出力を減らす設定でした。自分のスクリプトを棚卸しする手順まで書き残します。