ANTIGRAVITY LABEN
記事一覧/アプリ開発
アプリ開発/2026-06-21上級

Play Store の密度分割で、特定の端末だけ内蔵壁紙が消えた — drawable と nodpi の境界設計

App Bundle の密度分割は、密度別に分けてはいけない画像まで分けてしまうと、特定の密度バケットの端末からだけリソースを取りこぼします。bundletool で再現し、drawable-nodpi への移動か密度分割の無効化で直すまでを、判断基準ごと残しました。

Android13App Bundle個人開発73Antigravity251AdMob11

プレミアム記事

段階公開を 5% で回していたとき、レビューに「サンプルの壁紙が灰色のまま表示されない」という報告が数件だけ並びました。手元の Pixel でも、社用の中位機でも再現しません。Crashlytics にも何も出ていません。共通していたのは、報告者の端末がいずれも画面密度の低い廉価機だったことでした。クラッシュではなく、画像という静的リソースが「特定の端末群からだけ存在しないことになっている」という状態です。

原因にたどり着くまで遠回りをしました。最初はサーバー側の配信を疑い、次に難読化のリソース除去を疑い、最後に App Bundle の密度分割(density split)に行き当たりました。個人開発で壁紙アプリを長く運用してきて、密度分割の理屈は知っているつもりでしたが、「分けてはいけない画像まで分けてしまう」という落とし穴には、このとき初めて正面からぶつかりました。ここでは再現手順から修正、そして Antigravity のエージェントにどこまで任せたかまでを、判断の根拠ごと残しておきます。

なぜ「特定の端末だけ」画像が消えるのか

Android App Bundle は、1つの .aab から端末構成ごとに最適化した APK(split APK)を生成します。分割の軸は ABI(CPU)・言語・そして画面密度の3つです。端末は Play から、自分の構成に合う split だけをダウンロードします。低密度端末は低密度の split を、高密度端末は高密度の split を受け取り、不要な解像度のリソースは届きません。これがインストールサイズを小さく保つ仕組みです。

問題は、res/drawable/ に無修飾で置いた画像の扱いです。無修飾の drawable/ は内部的に mdpi 相当として扱われ、密度分割が有効だと「中密度の split」に振り分けられます。すると、その split を受け取らない密度バケットの端末では、R.drawable.sample_wallpaper の実体が手元に無い、という状態が起こり得ます。getDrawable() は端末によっては最も近い密度から代替を引いてくれますが、対象リソースがどの密度 split にも入っていない構成では取得に失敗します。私のケースでは、原寸のサンプル壁紙を drawable/ に1枚だけ置いていたことが引き金でした。

リソースの置き場所密度分割での扱い全端末へ届くか
drawable/(無修飾)mdpi split に同梱×(中密度系の端末中心)
drawable-xxhdpi/ 等各密度 split に同梱×(その密度の端末のみ)
drawable-nodpi/密度分割の対象外(base split)○(全端末)
drawable-anydpi/(ベクター等)密度分割の対象外○(全端末)

まず bundletool で再現する

推測のまま直すと、別の端末で再発します。先に「どの密度 split に何が入っているか」を自分の目で確かめます。bundletool で端末仕様を指定し、その端末がダウンロードするはずの APK セットを取り出します。

# 1) リリースと同じ .aab を用意し、端末仕様(JSON)を書く
#    低密度端末を再現するため screenDensity を低めに設定する
cat > device-ldpi.json << 'JSON'
{
  "supportedAbis": ["arm64-v8a"],
  "supportedLocales": ["ja-JP"],
  "screenDensity": 240,
  "sdkVersion": 26
}
JSON
 
# 2) その端末が受け取る APK セットだけを生成する
bundletool build-apks \
  --bundle=app-release.aab \
  --output=ldpi.apks \
  --device-spec=device-ldpi.json
 
# 3) APK セットを展開し、問題の画像が含まれているか確認する
unzip -o ldpi.apks -d ldpi_out
for apk in ldpi_out/splits/*.apk; do
  echo "== $apk =="
  unzip -l "$apk" | grep -i "sample_wallpaper" || echo "  (含まれていません)"
done

screenDensity を 240 / 320 / 480 と変えて 3 回回すと、ある密度のときだけ sample_wallpaper がどの split にも現れない、という形で再現できます。「特定の端末でだけ消える」という曖昧な症状が、「この密度 split に入っていない」という具体的な事実に変わった瞬間に、直し方は自ずと決まりました。

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

この記事の続きを読む

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

この記事で得られること
特定の端末群からだけ画像が消える現象を、bundletool で端末別 APK を取り出して自分の手で再現できるようになる
密度ごとに分けるべき画像と、全端末へ同じ1枚を届けるべき画像の線引きが分かり、drawable-nodpi と密度分割無効化を使い分けられる
ラスタ資産の走査と移動を Antigravity エージェントに任せつつ、密度判断だけは人間が握る運用設計を自分のリポジトリに移植できる
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

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

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

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

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

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

関連記事

アプリ開発2026-05-21
Firebase Remote Config と Antigravity Agent で AdMob 配置を実運用しながら微調整する設計
壁紙アプリの AdMob 収益が頭打ちになった経験から、Firebase Remote Config と Antigravity Agent を組み合わせて広告配置を実運用中に少しずつ最適化する仕組みをまとめます。
アプリ開発2026-05-14
AndroidがOSを卒業した日 — AppFunctions APIで壁紙アプリをGemini Intelligenceにつないだ実装記録
2026-05-12発表のAndroid AppFunctions APIでアプリをGemini Intelligenceに接続する実装を、累計5,000万DLの壁紙アプリ群で実際に試した記録。設計判断・Kotlin実装・Antigravity活用ワークフローを解説します。
アプリ開発2026-05-10
累計5,000万DLアプリの保守をAntigravityにどこまで任せられたか — 12年個人開発者の現場検証
2014年から個人で運用してきた累計5,000万DLの壁紙・癒し系アプリ群を題材に、Antigravityにどこまで保守を任せられるかを実測しました。任せられた領域・任せられなかった領域を、判断軸つきで共有します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →