CLAUDE LABEN
FABLE5 — Claude Fable 5が公開(6/9)。Opusを上回るMythosクラス初の一般提供モデルで、100万トークンコンテキスト・128k出力・常時適応思考を搭載FREE-WINDOW — Fable 5は6/22までPro/Max/Team/Enterpriseに無料同梱。6/23以降はusage creditsが必要。APIは入力$10/出力$50 per MTokSAFEGUARDS — Fable 5は高リスク領域の質問をOpus 4.8へ自動フォールバック(発動はセッションの5%未満)。制限解除版のMythos 5は審査済み組織限定IPO — AnthropicがIPOを機密申請(6/1)。直近調達$65B・評価額$965B・年換算売上$47Bと報道BILLING — 6/15の課金変更まで残り3日。Agent SDK・headless Claude Code・GitHub Actions・他社エージェントがAPIレート準拠の月次クレジットへ移行しますPLATFORM — Claude Developer PlatformにManaged Agentsのスケジュールデプロイ・vault環境変数クレデンシャル・セッションスレッドWebhookが追加FABLE5 — Claude Fable 5が公開(6/9)。Opusを上回るMythosクラス初の一般提供モデルで、100万トークンコンテキスト・128k出力・常時適応思考を搭載FREE-WINDOW — Fable 5は6/22までPro/Max/Team/Enterpriseに無料同梱。6/23以降はusage creditsが必要。APIは入力$10/出力$50 per MTokSAFEGUARDS — Fable 5は高リスク領域の質問をOpus 4.8へ自動フォールバック(発動はセッションの5%未満)。制限解除版のMythos 5は審査済み組織限定IPO — AnthropicがIPOを機密申請(6/1)。直近調達$65B・評価額$965B・年換算売上$47Bと報道BILLING — 6/15の課金変更まで残り3日。Agent SDK・headless Claude Code・GitHub Actions・他社エージェントがAPIレート準拠の月次クレジットへ移行しますPLATFORM — Claude Developer PlatformにManaged Agentsのスケジュールデプロイ・vault環境変数クレデンシャル・セッションスレッドWebhookが追加
記事一覧/Claude Code
Claude Code/2026-06-12中級

Android の戻るボタン広告ゲートを入れ子から並列独立構造へ — Claude Code と進めた終了フロー再設計の記録

戻るボタンの広告が「出ない」と「出すぎる」を同時に起こした原因は、入れ子分岐に埋め込まれた暗黙の優先度でした。壁紙アプリ v2.1.0 で広告ゲートを並列独立構造へ作り直した過程を、Kotlin実装・Claude Codeへの依頼内容・テストまで含めて記録します。

claude-code114android9admobkotlin3refactoring

プレミアム記事

2026年5月、運営している壁紙アプリの Android 版 v2.1.0 を準備していたとき、相反する2つのシグナルが同時に届きました。ストアレビューには「終了するたびに広告が出る」という声。一方で AdMob の管理画面を見ると、終了時インタースティシャルの表示回数は想定の半分ほどしかありません。「出すぎている」と「出ていない」が、同じバージョンに対して同時に報告されている状態です。

この時点で、原因が広告 SDK 側ではなく自分のコードの分岐ロジックにあることをほぼ確信しました。実際の犯人は、戻るボタンの処理に何年もかけて積み重なっていた入れ子の条件分岐です。ここに記録するのは、その入れ子をゲート単位の並列構造へ作り直し、分岐パスの棚卸しとテスト生成を Claude Code に任せた約2週間の作業内容です。同じように「終了時の広告まわりだけ誰も触りたがらない」状態になっているアプリは少なくないと思いますので、設計の考え方と移行の手順をそのまま共有します。

症状 — 「出ない」と「出すぎる」が同じ終了フローから生まれていた

問題の画面はアプリのトップ画面です。ここで戻るボタンが押されたとき、アプリは次の5つの問いに答える必要がありました。

  • 広告非表示ユーザーか: 買い切りの広告除去を購入済みか、リワード広告視聴による一時的な広告フリー期間中か
  • 他のモーダルが出ていないか: レビュー誘導やお知らせダイアログと重ならないか
  • レビュー誘導を出す条件を満たしているか: 起動回数や前回表示からの経過日数
  • 表示間隔の上限に達していないか: 終了時広告のフリークエンシーキャップ
  • インタースティシャルがロード済みか: 未ロードなら何も出せない

5つと書くと整理されて見えますが、実際のコードではこれらが約10年分の機能追加の順番どおりに、入れ子の if 文として埋まっていました。そして観測された不具合は2系統です。ひとつは、レビュー誘導の表示フラグが立ったまま降りない経路があり、その状態に入ったユーザーには終了時広告が一切出なくなるもの。もうひとつは、広告が未ロードだった場合の素通し経路でフリークエンシーキャップの計測が更新されず、次回セッションで本来の間隔を無視して広告が出るものです。前者が AdMob レポート上の「出ない」を、後者がレビュー欄の「出すぎる」を作っていました。

原因 — 入れ子の if は優先度を暗黙のうちに固定する

リファクタリング前のコードを、変数名だけ整えて簡略化するとこういう形でした。

// Before: 戻るボタン処理に積み重なっていた入れ子分岐(実物を簡略化)
override fun onBackPressed() {
    if (!billingManager.isPurchased) {
        if (interstitialAd != null) {
            if (!reviewInduction.isShowing) {
                if (frequencyCap.canShow()) {
                    interstitialAd?.show(this)      // ようやく広告表示
                } else {
                    super.onBackPressed()           // 上限到達 → 素通し
                }
            }
            // reviewInduction.isShowing == true のときは何もしない(バグの温床)
        } else {
            super.onBackPressed()                   // 未ロード → 素通し(計測漏れ)
        }
    } else {
        super.onBackPressed()                       // 課金済み → 素通し
    }
}

このコードの問題は、バグが2件あることそのものではありません。構造として次の3つの性質を持ってしまっていることです。

第一に、優先度がネストの深さに埋め込まれていて、仕様として読めないことです。「課金判定はレビュー誘導より強い」「レビュー誘導は広告より強い」という業務上の優先順位が、コードの字面からは「たまたまその順に書かれている」ようにしか見えません。新しい条件を足すとき、どの深さに差し込むべきかを判断する材料がコードの中にないのです。

第二に、条件が1つ増えるたびに経路が倍々で増えることです。boolean の条件が5つあれば理論上の状態は32通りで、そのすべてに「何が起きるべきか」の答えがあるはずですが、入れ子構造では書かれていない組み合わせが else の谷間に落ちます。落ちた先が super.onBackPressed() なのか「何もしない」なのかは、たまたまどの else に拾われるか次第です。

第三に、素通しの経路が無言であることです。広告が出なかったとき、それが課金済みだからなのか、未ロードだからなのか、キャップ到達なのかをログから区別できませんでした。「出ない」系の不具合調査が毎回難航していた直接の理由です。

個人開発を2014年から続けてきて、この種の「動いているから触らない」コードが一番高くつくことは身に染みているのですが、終了フローは確認の手間が大きく、後回しにし続けていました。今回 Claude Code に分岐パスの列挙を任せられたことが、重い腰を上げるきっかけになりました。

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

この記事の続きを読む

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

この記事で得られること
戻るボタン広告の「出ない・出すぎる」をゲート単位で切り分け、ログから数分でどのゲートが原因かを特定できるようになる
入れ子の if 文を「優先度リスト + 先勝ち評価」の並列独立ゲートへ置き換える Kotlin 実装と、5つの移行手順を持ち帰れる
isAdFree || isRewardAdFree を単一の Source of Truth に集約し、課金とリワード解除の判定ずれを構造的に防げるようになる
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

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

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

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

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

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

関連記事

Claude Code2026-06-12
Android でペイウォールとレビュー誘導が重なって表示される競合を ModalGate で解決した実装メモ
ペイウォール・レビュー誘導・リワード広告案内の3つのダイアログが同時に表示される競合を、優先度付きの中央ゲート(ModalGate)で解決した実装メモです。Claude Code とのレビューで見つかった閉じ漏れの3経路と Kotlin 実装例を紹介します。
Claude Code2026-05-16
Claude Code でAndroid の RecyclerView クラッシュを28日間で根治した記録
Beautiful HD Wallpapersのv2.0.0リリース後、RecyclerViewのIndexOutOfBoundsExceptionが28日で50ユーザー以上に発生。Claude Codeとの対話で防御的コピーによる根治法を発見した実録。
Claude Code2026-05-27
Claude Code で Glide 5.0.5 の Java 8 API クラッシュを1行で消した話
Beautiful HD Wallpapers v2.0.0 で Android 6.0.1 ユーザーが全員 3 秒以内にクラッシュ。Claude Code との対話で coreLibraryDesugaringEnabled の 1 行だけが足りていなかったことに辿り着いた実体験です。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →