gplay-preflight について
gplay-preflightは、アップロード前のAPKやAABをローカルで検査するスキルです。リリース上の問題や権限、ネイティブライブラリ、秘密情報をオフラインで確認でき、ストア情報の検証やCI向けの判定にも対応します。
主な機能
- 01APKとAABのオフライン検査
- 02マニフェストと権限の確認
- 03ネイティブライブラリとサイズの検査
- 04秘密情報とSDKの検出
- 05ストア情報の任意検証
- 06JSONレポートとCIゲート
活用シーン
- 01アップロード前のAndroidビルド確認
- 02CIで重大な問題があるリリースを停止
- 03ストアの文面や画像素材の確認
- 04JSONツールで検出結果を分析
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ tamtom/ gplay-cli-skills --skill gplay-preflightインストール後、Claude Code で/gplay-preflightを入力して読み込まれたか確認します。
詳細
gplay preflight — オフラインでのビルドスキャン
gplay preflight はローカルの .aab または .apk を検査し、検出事項を報告します。API 呼び出しも認証情報も不要なため、アーティファクトが Play に一度も送信されていない段階でも、どのマシンや CI ジョブでも実行できます。
認証が必要で API にアクセスする gplay validate の前、およびアップロードの前に実行してください。Play によって数時間後に拒否される問題や、ユーザーのデバイスへのインストール時に発生する問題を検出します。
前提条件
- ビルド済みの
.aabまたは.apkがディスク上にあること。 - それ以外は不要です。
gplay auth loginも、--packageも、ネットワーク接続も必要ありません。
基本的な使い方
# Scan a bundle
gplay preflight --file app-release.aab
# Also validate the store listing in the same pass
gplay preflight --file app-release.aab --listings-dir ./fastlane/metadata/android
# Machine-readable
gplay preflight --file app-release.aab --output json --pretty
# See what scanners exist
gplay preflight --list-scanners
preflight がビルドを読み取る仕組み
preflight は AndroidManifest.xml を完全にデコードします。APK の場合はバイナリ AXML、App Bundle の場合は aapt2 の protobuf を読み取るため、部分文字列の推測ではなく、実際の型付き属性値に基づいて検出結果が示されます。
結果を解釈する際は、この点が重要です。リソース参照を指す属性(たとえば android:debuggable="@bool/isDebug")は、false ではなく「静的には判定できない」と報告されます。その場合、検出されなかったことを、不在の証拠とみなさないでください。
積極的なコード縮小によってクラスの名前が変更されたり削除されたりすることがあるため、SDK の検出漏れは、その SDK が存在しない証拠にはなりません。一方、検出された場合の信頼度は高いです。
9 つのスキャナー
各スキャナーには ID があります。--only で選択するか、--skip で除外します(カンマ区切り)。
manifest
マニフェストの正確性と、リリースを妨げるフラグを確認します。
android:debuggable="true"— エラー。デバッグ可能なビルドが出荷されます。android:testOnly="true"— エラー。Play はアップロードを拒否します。<intent-filter>を持ち、targetSdk31 以上でandroid:exportedがないコンポーネント — エラー。これは警告ではなく、Android 12 以降でのインストール失敗です。ランチャーアクティビティは対象外です。grantUriPermissionsを持つエクスポート済みの<provider>— エラー。どのアプリからでも、許可された URI にアクセスできます。targetSdk34 以上で、対応する権限がないフォアグラウンドサービスのタイプ — Android 14 では実行時にSecurityExceptionが発生します。dataSyncタイプにはFOREGROUND_SERVICE_DATA_SYNCが必要です。usesCleartextTraffic="true"— 警告。networkSecurityConfigが存在する場合は情報レベルに引き下げられます。allowBackup、requestLegacyExternalStorage、パッケージ/バージョンの妥当性。
permissions
- Play の申告フォームが必要な制限付き権限:SMS と通話履歴のグループ、
MANAGE_EXTERNAL_STORAGE、ACCESS_BACKGROUND_LOCATION、QUERY_ALL_PACKAGES、SYSTEM_ALERT_WINDOW、BIND_ACCESSIBILITY_SERVICE、USE_FULL_SCREEN_INTENT、SCHEDULE_EXACT_ALARMなど。各検出結果には Play のポリシー文書へのリンクが付いています。 - データセーフティの開示が必要な機微な権限(情報レベル)。
- レガシーストレージ:
targetSdk30 以上でmaxSdkVersionのないWRITE_EXTERNAL_STORAGE、および 33 以上でのREAD_EXTERNAL_STORAGE。 - 重複した権限と非推奨の権限。
native_libs
arm64-v8aがない — エラー。Play では 2019 年以降、64 ビットが必須です。- 実際の ELF プログラムヘッダーを読み取って確認する16 KB メモリページのアラインメント。
targetSdk35 以上ではエラー、それ未満では警告です。16 KB ページの Android 15 デバイスでは、アラインメントされていない.soファイルは読み込まれません。 x86があるのにx86_64がない、またはarmeabiのみ。- ストリップされていない
.debug_*/.symtabセクション — ダウンロードサイズの無駄です。 extractNativeLibs="true"— インストール時の占有サイズが増加します。
metadata
--listings-dir が必要です。 指定しない場合はスキップされます。Fastlane 形式のレイアウト(<dir>/<locale>/title.txt、<dir>/<locale>/images/...)を想定しています。
- タイトルは 30 文字以下、短い説明は 80 文字以下、詳細な説明は 4000 文字以下、リリースノートは 500 文字以下 — バイト数ではなくルーン単位で数えます。
- 実際のピクセル寸法:アイコンは 512×512、フィーチャーグラフィックは 1024×500、プロモーショングラフィックは 180×120、TV バナーは 1280×720。
- スクリーンショット:各辺は 320px 以上、3840px 以下、縦横比は最大 2:1。スマートフォンのスクリーンショットは 2 枚以上、フォームファクターごとに最大 8 枚、各ファイルは最大 8 MB です。
secrets
エラー:秘密鍵ブロック、AWS アクセスキー、Stripe の sk_live_、GitHub トークン、
Slack トークンと Webhook、SendGrid キー、Google OAuth クライアントシークレット、
OpenAI/Anthropic キー、サービスアカウント JSON、アプリに含まれるキーストア(.jks、
.keystore、.p12、.pfx、.pem、.ppk)、および .git/ や .env の漏えい。
警告:Google API キー(AIza…)と JWT。
Google API キーをエラーではなく警告として扱うのは、意図的です。Android アプリには、 Maps や Firebase のキーを設計上埋め込みます。対処方法は、バイナリから削除することではなく、 Cloud Console でキーの使用をパッケージ名と署名証明書に制限することです。ユーザーに削除するよう伝えないでください。
Dex バイトコードもスキャンするため、ハードコードされた文字列リテラルも検出されます。
billing
サードパーティの決済プロセッサ(Stripe、Braintree、PayPal、Adyen、Razorpay など)が
ビルドに含まれている場合は、それだけで警告になります。Play Billing も含まれている場合は情報に格下げされます。また、請求の実装がないのに com.android.vending.BILLING が宣言されている場合や、Play Billing Library を含めずに請求ラッパー(RevenueCat、Adapty、
Qonversion)がアプリに含まれている場合も検出します。
privacy
分析、アトリビューション、広告 SDK 40 種以上の一覧を表示します(情報)。AD_ID
権限との整合性を確認し、targetSdk 33 以上で広告/トラッキング SDK が存在するのに
権限がない場合は警告し、逆のケースも通知します。
policy
targetSdkVersionが Play の最低要件を下回っている場合。Google が新しい gplay リリースより先に年次の最低要件を引き上げた場合は、--min-target-sdkで上書きします。- 制限対象のサービス:アクセシビリティ、VPN、デバイス管理者、通知リスナー。
- APK と AAB のアップロード形式。
size
ダウンロードサイズの上限(--max-size)、dex ごとの上限(--max-dex)、dex の断片化、バケットごとのペイロード内訳(最大の項目を含む)。
CI ゲーティング
# Block only on hard blockers
gplay preflight --file app-release.aab --fail-on error
# Stricter: warnings fail too
gplay preflight --file app-release.aab --fail-on warning
# Narrow the gate to the scanners you care about
gplay preflight --file app-release.aab \
--only manifest,permissions,native_libs,secrets \
--fail-on warning
# Faster: skip the secrets scan on very large builds
gplay preflight --file app-release.aab --skip-secrets
終了コード:
| コード | 意味 |
|---|---|
| 0 | --fail-on 以上の検出事項なし |
| 1 | --fail-on 以上の検出事項あり |
GitHub Actions:
- name: Offline preflight
run: |
gplay preflight \
--file app/build/outputs/bundle/release/app-release.aab \
--listings-dir fastlane/metadata/android \
--fail-on error
JSON 出力
--output json は、形式、パッケージ、バージョンコードとバージョン名、
min/target SDK、スキャナーごとの実行ステータス、および check、
severity、message、entry、hint、(該当する場合は)ref ポリシー
リンクを含むすべての検出事項を含む完全なレポートを出力します。
# Just the errors
gplay preflight --file app.aab --output json | jq '[.findings[] | select(.severity=="error")]'
# Which scanners were skipped and why
gplay preflight --file app.aab --output json | jq '.scanners[] | select(.skipped)'
preflight の位置付け
| ツール | 認証が必要 | 対象範囲 |
|---|---|---|
gplay preflight | いいえ | アーティファクト自体をオフラインで確認します。マニフェスト、ライブラリ、シークレット、ストア掲載情報のファイル |
gplay validate | はい | リリース準備状況:ローカルチェックに加え、ライブトラックとストア掲載情報の状態 |
gplay checks analyze | はい | Google Checks によるプライバシー/ポリシー分析。サーバー側で非同期に実行 |
gplay release --dry-run | はい | 実際の edit に対して実行し、コミット前に破棄する完全なパイプライン |
この順序で実行してください。preflight は最も低コストで、最も多くの問題を検出します。
エージェントの動作
- アップロードまたはリリースコマンドを実行する前に
gplay preflight --file <artifact>を実行し、先に検出事項を報告してください。 - メタデータディレクトリが存在する場合は、必ず
--listings-dirを渡してください。渡さない場合、metadataスキャナーがスキップされ、ストア掲載情報の問題が報告されません。 errorの検出事項はブロッキングとして扱ってください。ユーザーが明示的に指示しない限り、 これらを無視してアップロードしないでください。- メッセージだけでなく、
hintとrefのフィールドも報告してください。実際に何を変更すべきかは hint に記載されています。 - secrets スキャナーが検出した Google API キーを削除するよう、決して勧めないでください。使用を制限するよう勧めてください。
- マニフェストをデコードできない場合やビルドが強く難読化されている場合、検出事項がないことは準拠の証明にはなりません。ビルドに問題がないと断言せず、その旨を伝えてください。
- コマンドを組み立てる前に
gplay preflight --helpでフラグを確認してください。 --onlyと--skipは、スキャナー ID をカンマ区切りで受け取ります。現在の一覧はgplay preflight --list-scannersで取得してください。
注意事項
preflightはアーカイブを一度読み込み、大きなエントリを上限付きのチャンクでストリーミングするため、大きなバンドルでもメモリ使用量は一定に保たれます。- スキャナー ID は安定しており、検出結果の
check名は JSON の利用者向けにバージョン間で維持されます。 policyスキャナーのターゲット API の下限は定数で、Google が毎年 8 月に引き上げます。古く見える場合は、--min-target-sdkを指定してください。