Android构建中Google Mobile Ads生命周期事件未触发问题
问题描述
我在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

