You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android构建中Google Mobile Ads生命周期事件未触发问题

Unity Google Mobile Ads插屏广告Android打包后生命周期事件失效问题

问题描述

我在Unity项目中集成Google Mobile Ads SDK实现插屏广告,编辑器运行时广告的生命周期事件(如OnAdFullScreenContentOpened、OnAdFullScreenContentClosed)能正常触发,代码功能完全符合预期;但打包为Android构建后,这些事件完全无法触发,广告无法按逻辑执行。

我添加了调试日志:Requesting Interstitial ad.在发起广告加载请求时打印,Interstitial ad loaded.在广告加载成功时打印。编辑器中能正常看到后者,确认广告加载完成;但Android打包后,仅能看到前者,加载成功的回调代码块似乎未执行。奇怪的是,移动端能正常显示Google官方测试广告,但就是无法触发任何生命周期事件,也看不到加载成功的日志。

代码实现

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GoogleMobileAds.Api;
using GoogleMobileAds.Common;
using System;
using UnityEngine.Events;

public class interstitialAd : MonoBehaviour
{
    public GameObject adFailedUI;
    public gameBehavior gamebehavior;

    public UnityEvent OnAdOpeningEvent;
    public UnityEvent OnAdClosedEvent;

    private InterstitialAd interstitial;
    private bool adLoaded = false;

    void Start()
    {
        RequestInterstitial();
    }

    void Update()
    {
    }

    #region HELPER METHODS
    private AdRequest CreateAdRequest()
    {
        return new AdRequest.Builder().Build();
    }
    #endregion

    public void RequestInterstitial()
    {
        MonoBehaviour.print("Requesting Interstitial ad.");

        string adUnitId = "ca-app-pub-3940256099942544/1033173712";

        if (interstitial != null)
        {
            interstitial.Destroy();
            interstitial = null;
        }

        InterstitialAd.Load(adUnitId, CreateAdRequest(),
            (InterstitialAd ad, LoadAdError loadError) =>
            {
                if (loadError != null)
                {
                    MonoBehaviour.print("Interstitial ad failed to load with error: " +
                        loadError.GetMessage());
                    return;
                }
                else if (ad == null)
                {
                    MonoBehaviour.print("Interstitial ad failed to load.");
                    return;
                }

                MonoBehaviour.print("Interstitial ad loaded.");
                interstitial = ad;
                RegisterEventHandlers(interstitial);
            });
    }

    private void RegisterEventHandlers(InterstitialAd ad)
    {
        ad.OnAdFullScreenContentOpened += () =>
        {
            MonoBehaviour.print("Interstitial ad opening.");
            OnAdOpeningEvent.Invoke();
        };
        ad.OnAdFullScreenContentClosed += () =>
        {
            MonoBehaviour.print("Interstitial ad closed.");
            OnAdClosedEvent.Invoke();
            RequestInterstitial();
        };

        ad.OnAdImpressionRecorded += () =>
        {
            MonoBehaviour.print("Interstitial ad recorded an impression.");
        };
        ad.OnAdClicked += () =>
        {
            MonoBehaviour.print("Interstitial ad recorded a click.");
        };
        ad.OnAdFullScreenContentFailed += (AdError error) =>
        {
            RequestInterstitial();
            adFailedUI.SetActive(true);
            MonoBehaviour.print("Interstitial ad failed to show with error: " +
                        error.GetMessage());
        };
        ad.OnAdPaid += (AdValue adValue) =>
        {
            string msg = string.Format("{0} (currency: {1}, value: {2}",
                                       "Interstitial ad received a paid event.",
                                       adValue.CurrencyCode,
                                       adValue.Value);
            MonoBehaviour.print(msg);
        };
    }

    public void ShowAd()
    {
        if (this.interstitial.CanShowAd() && interstitial != null)
        {
            this.interstitial.Show();
        }
    }

    public void DestroyAd()
    {
        interstitial.Destroy();
    }

    public void OnDestroy()
    {
        DestroyAd();
    }
}

解决方案

1. 线程调度修复

Google Mobile Ads的加载回调和事件可能在后台线程触发,而Unity的MonoBehaviour.print、UnityEvent调用必须在主线程执行。编辑器会自动处理线程切换,但Android打包后不会,导致代码看似未执行。

添加主线程调度逻辑:

// 类内新增主线程任务队列
private static readonly Queue<Action> _mainThreadActions = new Queue<Action>();

void Update()
{
    lock (_mainThreadActions)
    {
        while (_mainThreadActions.Count > 0)
        {
            _mainThreadActions.Dequeue().Invoke();
        }
    }
}

// 封装主线程执行方法
private void RunOnMainThread(Action action)
{
    lock (_mainThreadActions)
    {
        _mainThreadActions.Enqueue(action);
    }
}

修改加载回调和事件处理,将所有Unity相关操作放入RunOnMainThread:

// 示例:修改加载成功逻辑
InterstitialAd.Load(adUnitId, CreateAdRequest(),
    (InterstitialAd ad, LoadAdError loadError) =>
    {
        if (loadError != null)
        {
            RunOnMainThread(() => MonoBehaviour.print("Interstitial ad failed to load with error: " + loadError.GetMessage()));
            return;
        }
        else if (ad == null)
        {
            RunOnMainThread(() => MonoBehaviour.print("Interstitial ad failed to load."));
            return;
        }

        RunOnMainThread(() => 
        {
            MonoBehaviour.print("Interstitial ad loaded.");
            interstitial = ad;
            RegisterEventHandlers(interstitial);
        });
    });

// 示例:修改广告打开事件
ad.OnAdFullScreenContentOpened += () =>
{
    RunOnMainThread(() =>
    {
        MonoBehaviour.print("Interstitial ad opening.");
        OnAdOpeningEvent.Invoke();
    });
};

2. ProGuard混淆规则添加

Android打包时ProGuard可能会混淆Google Mobile Ads的类,导致回调被剥离。在proguard-user.txt中添加以下规则:

-keep class com.google.android.gms.ads.** { *; }
-keep class com.google.android.gms.common.** { *; }
-keep class com.google.android.gms.tasks.** { *; }
-keep class com.google.android.ump.** { *; }

确保Unity打包时启用了自定义ProGuard配置并包含该文件。

3. 广告对象生命周期检查

检查OnDestroy中的DestroyAd是否过早调用,或场景切换时未正确处理广告对象。确保在广告加载完成并注册事件前,不要销毁interstitialAd脚本所在的GameObject;场景切换时先销毁广告对象,进入新场景后重新加载。

4. SDK版本兼容性验证

检查Google Mobile Ads SDK版本与Unity版本是否兼容,尝试更新至最新稳定版SDK。

验证步骤

  • 打包Android时勾选Development Build和Script Debugging,通过Android Studio的Logcat查看详细报错日志。
  • 继续使用Google官方测试ID,避免真实广告的加载限制。

内容的提问来源于stack exchange,提问作者Hououin Kyoma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 15:22:14