ストアスクリーンショット
目的
コンバージョンに貢献し、アプリに忠実で、ストアが要求するすべてのスロットに適合するスクリーンショットを、スクリプトで生成することで、UI が変更されても数分で再生成できるようにします。
前提条件
- このリリースで UI が確定したビルド。
- アプリ内に、決定的なデモデータで画面をレンダリングできるキャプチャハーネス(Flutter golden/integration テスト、XCUITest、Espresso/Compose スクリーンショットテスト、または Fastlane snapshot)。
- Node.js 18+ およびレンダリング用の Chrome/Chromium(
scripts/でnpm i)。 - アップロード用の API 認証情報(
accounts-and-tax)。
原則
- モックアップではなく、実際のキャプチャを使用する。 フレーム内のすべての電話画面は、出荷されたアプリのキャプチャです。再描画または「改善」された UI は誤解を招き(ガイドライン 2.3)、すぐに古くなります。
- 数値はアプリと一致しなければならない。 フレームに「1,850 歩」や「12 分」と表示されている場合、アプリはデモデータに対して正確にそれを生成する必要があります。ハーネスでデモデータを生成し、同じテストでアサーションを行います。
- スクリーンショットがアプリで実行できないことを示している場合は、どちらかを修正する。 機能を構築するか、フレームを変更します。ギャップを出荷しないでください。
- フレーム内に他のプラットフォームを含めない。 iOS に Android のステータスバー/ナビゲーションバーを表示したり、Play に Apple の UI や「App Store」を表示したりしないでください(2.3.10)。
- すべてのロケールとすべてのデバイスで同じフレーム順序を維持する。
デバイスマトリクス
論理サイズと API 識別子の完全なテーブルは、references/device-matrix.md を参照してください。概要(Apple スクリーンショット仕様 と Play プレビューアセット で確認してください):
| スロット | ピクセル(縦向き) | 必須? |
|---|---|---|
| iPhone 大 Dynamic Island(6.9 インチ) | 1320×2868(1290×2796、1260×2736 も可) | 推奨メインセット |
| iPhone 中 Dynamic Island | 1206×2622 または 1179×2556 | 少なくとも 1 つのスクリーンショットが必要 |
| iPhone Duo 外部ディスプレイ | 1398×2034 | iOS 27.1 SDK 以降でビルドされたアプリでは 2027 年 4 月から必須。「iPhone Duo 最適化」バッジが追加されます |
| iPhone Duo 内部ディスプレイ | 2007×2853 | 外部ディスプレイと同じ |
| iPad 13 インチ | 2064×2752(または 2048×2732) | アプリが iPad で動作する場合のみ必須(iPhone 専用アプリでは不要) |
| Play スマートフォン | 例 1080×1920 または 1080×2160(辺 320~3840 px、長辺 ≤ 短辺の 2 倍) | 公開には ≥ 2 のスクリーンショットが必要。≥ 4 で ≥ 1080 px 推奨 |
| Play 7 インチおよび 10 インチタブレット | 1080~7680 px、9:16 または 16:9 | アプリがタブレットをサポートする場合に推奨 |
| Play フィーチャーグラフィック | 1024×500 | 必須 |
| Play アイコン | 512×512、32 ビット PNG | 必須 |
Apple:各サイズ最大 10 枚。PNG または JPEG。アルファチャンネルまたは透明度は不可。 Play:各デバイスタイプ最大 8 枚。JPEG または 24 ビット PNG(アルファなし)。
App Store 商品ページクリエイティブアセット(新しい App Store Connect、「Header and Search Results」タブ):
- ヘッダー:商品ページ上部のワイド画像、3840×1646 または 5244×2950。オプション(なくても提出は通ります)。
- 検索結果:5244×2950、3840×2560、または 1920×1280。空の場合、スクリーンショットとプレビューが使用されます。
- バージョンページまたはアセットライブラリ(クリエイティブアセットをアップロード)からアップロードし、「アセットを参照」で選択します。ライブラリにアップロードされたアセットは後で再利用できます。
- デザインノート:ストアはヘッダーの一部にアイコン、名前、入手ボタンを重ねるため、コンソールプレビューで結果を確認してください。
- これらのスロットは、バージョンが「審査待ち」の間ロックされています。提出前に追加してください。
手順
1. ストーリーを計画する(ストーリーボードの承認)
5~8 フレームのストーリーボードを作成します。各フレームには、1 つの見出し(6 語以内)、1 つの補足テキスト、1 つのキャプチャを含めます。オプションの「パノラマ」レイアウト(バンドルされたテンプレートが行うもの):フレームは 1 つのワイドキャンバスのスライスであり、形状がフレームの端をまたいで続きます。レイアウトに関係なく、表示されるオファー(無料スタート、トライアル)は真実でなければなりません。
2. 実際の画面をキャプチャする
各画面を、ターゲットデバイスの論理サイズ × ピクセル比でキャプチャします。これにより、テキストとレイアウトがそのデバイスに表示されるものと正確に一致します。Flutter の例(widget/golden テスト):
// 6.9 インチ iPhone: 440 x 956 論理ポイント @3x = 1320 x 2868 px
tester.view.physicalSize = const Size(1320, 2868);
tester.view.devicePixelRatio = 3.0;
await tester.pumpWidget(App(demo: DemoData.storeShots(locale: 'en')));
await tester.pumpAndSettle();
expect(find.text('1,850 steps'), findsOneWidget); // 見出しの数値が本物であること
await expectLater(find.byType(App), matchesGoldenFile('captures/en/iphone69/01_home.png'));
- テストでフォントを読み込んでください(そうしないと、テストフォントでボックスがレンダリングされます)。
- 時計を固定し、デモデータを固定し、ネットワークは使用しないでください。
- デバッグバナーを非表示にし、ステータスバーをクリーンな状態に設定します(またはトリミングして何も描画しない)。
- ロケールごとに個別にキャプチャします。ローカライズされたフレーム内に英語の UI を配置しないでください。
3. フレームを合成する
テンプレート:templates/panorama.html、レンダラー:scripts/render.mjs。
cd scripts && npm i
node render.mjs ../templates/frames.example.json out/
レンダラーは、すべてのフレームを 1 つのキャンバス(幅 = フレーム数 × フレーム幅)に配置し、キャプチャを読み込み、フォントの準備ができるのを待ち、各フレームスライスを正確なピクセルサイズで、設定内のすべてのデバイスについてスクリーンショットします。また、1024×500 のフィーチャーグラフィックもレンダリングします。
4. チェック
node check-images.mjs out/
以下の場合に失敗します:フォルダのデバイスに対して寸法が間違っている、アルファチャンネルが存在する(PNG カラータイプ 4/6 または tRNS チャンク)、ファイルが 10(Apple)/ 8(Play)を超えている、番号に欠落がある。その後、すべての画像を 100% ズームで確認します:テキストの切り捨て、他プラットフォームの UI、プレースホルダー文字列、古い数値がないか。
5. API 経由でアップロードする(ライブセットを置き換える前に承認が必要)
- App Store Connect — scripts/upload-asc.mjs:編集可能な
appStoreVersionを見つける → そのappStoreVersionLocalizations→screenshotDisplayTypeごとのappScreenshotSets→ 古いスクリーンショットを削除 → 予約(POST /v1/appScreenshotsにfileName、fileSizeを指定) →uploadOperationsからパーツをアップロード → コミット(PATCHでuploaded: trueと MD5sourceFileChecksumを指定) → セットのappScreenshotsリレーションで順序を設定。ドキュメント:Uploading assets。 - Google Play — scripts/upload-play.mjs:
edits.insert→edits.images.deleteall(言語と画像タイプごと) →edits.images.upload(phoneScreenshots、sevenInchScreenshots、tenInchScreenshots、featureGraphicの順) →edits.commit。ドキュメント:edits.images.upload。
両方のスクリプトはデフォルトでドライランになります。書き込みを行うには DRY_RUN=0 を設定します。
6. 読み返し
ロケールとデバイスごとにアップロードされたアセットをリストし(両方の API)、ローカルフォルダと数と順序を比較します。Apple のアップロードは非同期で処理されます。すべてのアセットが COMPLETE 配信状態になるまで待機します。
人間の承認が必要な判断ポイント
ストーリーボードと見出し、最終的なビジュアル方向性、ライブのスクリーンショットセットの差し替え、Play 編集のコミット。
検証
check-images.mjsが成功すること。すべての必須 Apple スロットに少なくとも 1 つの画像があること。Play にスマートフォンショットとフィーチャーグラフィックがあること。- 読み返しの順序が一致すること。失敗したアセット状態がないこと。
- フレーム内のすべての数値と機能がビルドと照合されていること。
よくある落とし穴
- 6.9 インチのみをアップロードし、必須の iPhone 中 Dynamic Island スロットを忘れる。
- アルファチャンネル付きで PNG をエクスポートする(デザインツールや、透過背景のヘッドレスブラウザからよく発生します。常に不透明な body 背景を設定してください)。
- 6.9 インチ 1320×2868 の画像を Play で使用する:そのアスペクト比は Play の 2:1 制限を超えています。Play 専用のサイズでレンダリングしてください。
- iPhone 専用アプリで iPad のスクリーンショットを撮る(不要)— または、アプリが iPad で動作するのにスクリーンショットがない。
- アプリに存在しない設定行や結果を表示するフレーム。
- 見出しは翻訳されているが、キャプチャは英語のまま。