Google Playから、「2026年8月31日までにtargetSdkVersionをAndroid 16(API 36)以上にしないと、アプリの更新が拒否される」という通知が届きました。

「ギャンブル収支管理」のcordova-androidのバージョンを15.1.0へ上げ、config.xmlのSDKバージョンを36に変更しました。

ビルドして実行したところ、問題なく起動しました。
各画面で問題が発生しないか確認していたところ、バナー広告表示のタイミングで突然アプリがクラッシュしました。

クラッシュログをClaude Codeで解析したところ、

java.lang.ClassCastException: android.widget.LinearLayout$LayoutParams cannot be cast to android.widget.FrameLayout$LayoutParams at org.apache.cordova.CordovaActivity.lambda$createViews$0(CordovaActivity.java:236)

cordova-android 15では、キーボードの表示・非表示や画面回転などによってウィンドウインセット(ステータスバーやナビゲーションバーの領域)が変化するたびに、WebViewのLayoutParamsを無条件でFrameLayout.LayoutParamsへキャストするコードが新たに追加されていました。

一方、バナー広告表示に使用しているadmob-plus-cordovaプラグインでは、アンカー型バナーを表示する際に、WebViewをLinearLayoutの中へ包み直す実装になっています(Banner.ktの244〜253行目付近)。
その結果、WebViewのLayoutParamsがLinearLayout.LayoutParamsへ変更されるため、cordova側の無条件キャストが失敗し、アプリがクラッシュしていたことが原因でした。

そこで、Claude Codeにバナー広告が正しく表示されるように修正を依頼したところ、以下のコードのようになりました。

CordovaActivity.java

修正前、236行から

FrameLayout.LayoutParams webViewParams = (FrameLayout.LayoutParams) webView.getLayoutParams();
// Only update layout margins if the values have actually changed.
// This prevents redundant layout passes and potential infinite layout loops
if (webViewParams.leftMargin != left || webViewParams.topMargin != top
        || webViewParams.rightMargin != right || webViewParams.bottomMargin != bottom) {
    webViewParams.setMargins(left, top, right, bottom);
    webView.setLayoutParams(webViewParams);
}

修正後、

// webView may have been reparented out of rootLayout (e.g. wrapped in a
// LinearLayout by an ad plugin for anchored banners), in which case its
// LayoutParams is no longer a FrameLayout.LayoutParams. Walk up to the
// direct child of rootLayout that now contains it and apply the inset
// margins there instead, so the wrapper (and therefore the webView and
// any anchored banner inside it) stays clear of the system bars.
View marginTarget = webView;
while (marginTarget.getParent() != rootLayout && marginTarget.getParent() instanceof View) {
    marginTarget = (View) marginTarget.getParent();
}

if (marginTarget.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
    ViewGroup.MarginLayoutParams marginParams =
            (ViewGroup.MarginLayoutParams) marginTarget.getLayoutParams();
    // Only update layout margins if the values have actually changed.
    // This prevents redundant layout passes and potential infinite layout loops
    if (marginParams.leftMargin != left || marginParams.topMargin != top
            || marginParams.rightMargin != right || marginParams.bottomMargin != bottom) {
        marginParams.setMargins(left, top, right, bottom);
        marginTarget.setLayoutParams(marginParams);
    }
}

現状では、cordova-androidまたはadmob-plus-cordovaプラグインの対応待ちですが、アプリの更新期限を考えると、Claude Codeで修正したCordovaActivity.javaに入れ替えた方が無難かもしれません。

Recommended Posts