diff --git a/samples/HelloWorld/Assets/Scripts/AppOpenAdController.cs b/samples/HelloWorld/Assets/Scripts/AppOpenAdController.cs index e1cb5418b..f58caebe2 100644 --- a/samples/HelloWorld/Assets/Scripts/AppOpenAdController.cs +++ b/samples/HelloWorld/Assets/Scripts/AppOpenAdController.cs @@ -90,7 +90,11 @@ public void LoadAd() RegisterEventHandlers(ad); // Inform the UI that the ad is ready. - AdLoadedStatus?.SetActive(true); + // Use MobileAdsEventExecutor to ensure the UI is updated on the main thread. + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + AdLoadedStatus?.SetActive(true); + }); }); } @@ -158,9 +162,20 @@ private void RegisterEventHandlers(AppOpenAd ad) // Raised when the ad is estimated to have earned money. ad.OnAdPaid += (AdValue adValue) => { + // This log is executed off the Unity main thread. + // Write all time-sensitive code before ExecuteInUpdate(). Debug.Log(String.Format("App open ad paid {0} {1}.", adValue.Value, adValue.CurrencyCode)); + + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + // This callback may be delayed on Android until the user + // returns to the app. Place all code that interacts with + // Unity UI and GameObjects inside this callback. + Debug.Log("App open ad paid callback " + + "invoked inside ExecuteInUpdate."); + }); }; // Raised when an impression is recorded for an ad. ad.OnAdImpressionRecorded += () => @@ -177,8 +192,11 @@ private void RegisterEventHandlers(AppOpenAd ad) { Debug.Log("App open ad full screen content opened."); - // Inform the UI that the ad is consumed and not ready. - AdLoadedStatus?.SetActive(false); + // Use MobileAdsEventExecutor to ensure the UI is updated on the main thread. + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + AdLoadedStatus?.SetActive(false); + }); }; // Raised when the ad closed full screen content. ad.OnAdFullScreenContentClosed += () => @@ -192,7 +210,13 @@ private void RegisterEventHandlers(AppOpenAd ad) ad.OnAdFullScreenContentFailed += (AdError error) => { Debug.LogError("App open ad failed to open full screen content with error : " - + error); + + error); + + // Use MobileAdsEventExecutor to ensure the UI is updated on the main thread. + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + AdLoadedStatus?.SetActive(false); + }); }; } } diff --git a/samples/HelloWorld/Assets/Scripts/BannerViewController.cs b/samples/HelloWorld/Assets/Scripts/BannerViewController.cs index a59aae4a7..e422384f7 100644 --- a/samples/HelloWorld/Assets/Scripts/BannerViewController.cs +++ b/samples/HelloWorld/Assets/Scripts/BannerViewController.cs @@ -1,6 +1,7 @@ using System; using UnityEngine; using GoogleMobileAds.Api; +using GoogleMobileAds.Common; namespace GoogleMobileAds.Sample { @@ -135,8 +136,11 @@ private void ListenToAdEvents() Debug.Log("Banner view loaded an ad with response : " + _bannerView.GetResponseInfo()); - // Inform the UI that the ad is ready. - AdLoadedStatus?.SetActive(true); + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + // Inform the UI that the ad is ready. + AdLoadedStatus?.SetActive(true); + }); }; // Raised when an ad fails to load into the banner view. _bannerView.OnBannerAdLoadFailed += (LoadAdError error) => @@ -146,9 +150,20 @@ private void ListenToAdEvents() // Raised when the ad is estimated to have earned money. _bannerView.OnAdPaid += (AdValue adValue) => { + // This log is executed off the Unity main thread. + // Write all time-sensitive code before ExecuteInUpdate(). Debug.Log(String.Format("Banner view paid {0} {1}.", adValue.Value, adValue.CurrencyCode)); + + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + // This callback may be delayed on Android until the user + // returns to the app. Place all code that interacts with + // Unity UI and GameObjects inside this callback. + Debug.Log("Banner view paid callback " + + "invoked inside ExecuteInUpdate."); + }); }; // Raised when an impression is recorded for an ad. _bannerView.OnAdImpressionRecorded += () => diff --git a/samples/HelloWorld/Assets/Scripts/InterstitialAdController.cs b/samples/HelloWorld/Assets/Scripts/InterstitialAdController.cs index b3611fb33..c57705a33 100644 --- a/samples/HelloWorld/Assets/Scripts/InterstitialAdController.cs +++ b/samples/HelloWorld/Assets/Scripts/InterstitialAdController.cs @@ -1,6 +1,7 @@ using System; using UnityEngine; using GoogleMobileAds.Api; +using GoogleMobileAds.Common; namespace GoogleMobileAds.Sample { @@ -67,7 +68,11 @@ public void LoadAd() RegisterEventHandlers(ad); // Inform the UI that the ad is ready. - AdLoadedStatus?.SetActive(true); + // Use MobileAdsEventExecutor to ensure the UI is updated on the main thread. + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + AdLoadedStatus?.SetActive(true); + }); }); } @@ -85,9 +90,6 @@ public void ShowAd() { Debug.LogError("Interstitial ad is not ready yet."); } - - // Inform the UI that the ad is not ready. - AdLoadedStatus?.SetActive(false); } /// @@ -123,9 +125,20 @@ private void RegisterEventHandlers(InterstitialAd ad) // Raised when the ad is estimated to have earned money. ad.OnAdPaid += (AdValue adValue) => { + // This log is executed off the Unity main thread. + // Write all time-sensitive code before ExecuteInUpdate(). Debug.Log(String.Format("Interstitial ad paid {0} {1}.", adValue.Value, adValue.CurrencyCode)); + + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + // This callback may be delayed on Android until the user + // returns to the app. Place all code that interacts with + // Unity UI and GameObjects inside this callback. + Debug.Log("Interstitial ad paid callback " + + "invoked inside ExecuteInUpdate."); + }); }; // Raised when an impression is recorded for an ad. ad.OnAdImpressionRecorded += () => @@ -141,6 +154,12 @@ private void RegisterEventHandlers(InterstitialAd ad) ad.OnAdFullScreenContentOpened += () => { Debug.Log("Interstitial ad full screen content opened."); + + // Use MobileAdsEventExecutor to ensure the UI is updated on the main thread. + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + AdLoadedStatus?.SetActive(false); + }); }; // Raised when the ad closed full screen content. ad.OnAdFullScreenContentClosed += () => @@ -152,6 +171,12 @@ private void RegisterEventHandlers(InterstitialAd ad) { Debug.LogError("Interstitial ad failed to open full screen content with error : " + error); + + // Use MobileAdsEventExecutor to ensure the UI is updated on the main thread. + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + AdLoadedStatus?.SetActive(false); + }); }; } } diff --git a/samples/HelloWorld/Assets/Scripts/RewardedAdController.cs b/samples/HelloWorld/Assets/Scripts/RewardedAdController.cs index a2508901e..fb389a857 100644 --- a/samples/HelloWorld/Assets/Scripts/RewardedAdController.cs +++ b/samples/HelloWorld/Assets/Scripts/RewardedAdController.cs @@ -1,6 +1,7 @@ using System; using UnityEngine; using GoogleMobileAds.Api; +using GoogleMobileAds.Common; namespace GoogleMobileAds.Sample { @@ -67,7 +68,11 @@ public void LoadAd() RegisterEventHandlers(ad); // Inform the UI that the ad is ready. - AdLoadedStatus?.SetActive(true); + // Use MobileAdsEventExecutor to ensure the UI is updated on the main thread. + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + AdLoadedStatus?.SetActive(true); + }); }); } @@ -90,9 +95,6 @@ public void ShowAd() { Debug.LogError("Rewarded ad is not ready yet."); } - - // Inform the UI that the ad is not ready. - AdLoadedStatus?.SetActive(false); } /// @@ -128,9 +130,20 @@ private void RegisterEventHandlers(RewardedAd ad) // Raised when the ad is estimated to have earned money. ad.OnAdPaid += (AdValue adValue) => { + // This log is executed off the Unity main thread. + // Write all time-sensitive code before ExecuteInUpdate(). Debug.Log(String.Format("Rewarded ad paid {0} {1}.", adValue.Value, adValue.CurrencyCode)); + + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + // This callback may be delayed on Android until the user + // returns to the app. Place all code that interacts with + // Unity UI and GameObjects inside this callback. + Debug.Log("Rewarded ad paid callback " + + "invoked inside ExecuteInUpdate."); + }); }; // Raised when an impression is recorded for an ad. ad.OnAdImpressionRecorded += () => @@ -146,6 +159,12 @@ private void RegisterEventHandlers(RewardedAd ad) ad.OnAdFullScreenContentOpened += () => { Debug.Log("Rewarded ad full screen content opened."); + + // Use MobileAdsEventExecutor to ensure the UI is updated on the main thread. + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + AdLoadedStatus?.SetActive(false); + }); }; // Raised when the ad closed full screen content. ad.OnAdFullScreenContentClosed += () => @@ -157,6 +176,12 @@ private void RegisterEventHandlers(RewardedAd ad) { Debug.LogError("Rewarded ad failed to open full screen content with error : " + error); + + // Use MobileAdsEventExecutor to ensure the UI is updated on the main thread. + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + AdLoadedStatus?.SetActive(false); + }); }; } } diff --git a/samples/HelloWorld/Assets/Scripts/RewardedInterstitialAdController.cs b/samples/HelloWorld/Assets/Scripts/RewardedInterstitialAdController.cs index 37d673b0d..c8082ddb9 100644 --- a/samples/HelloWorld/Assets/Scripts/RewardedInterstitialAdController.cs +++ b/samples/HelloWorld/Assets/Scripts/RewardedInterstitialAdController.cs @@ -1,6 +1,7 @@ using System; using UnityEngine; using GoogleMobileAds.Api; +using GoogleMobileAds.Common; namespace GoogleMobileAds.Sample { @@ -70,7 +71,11 @@ public void LoadAd() RegisterEventHandlers(ad); // Inform the UI that the ad is ready. - AdLoadedStatus?.SetActive(true); + // Use MobileAdsEventExecutor to ensure the UI is updated on the main thread. + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + AdLoadedStatus?.SetActive(true); + }); }); } @@ -90,9 +95,6 @@ public void ShowAd() { Debug.LogError("Rewarded interstitial ad is not ready yet."); } - - // Inform the UI that the ad is not ready. - AdLoadedStatus?.SetActive(false); } /// @@ -128,9 +130,20 @@ protected void RegisterEventHandlers(RewardedInterstitialAd ad) // Raised when the ad is estimated to have earned money. ad.OnAdPaid += (AdValue adValue) => { + // This log is executed off the Unity main thread. + // Write all time-sensitive code before ExecuteInUpdate(). Debug.Log(String.Format("Rewarded interstitial ad paid {0} {1}.", adValue.Value, adValue.CurrencyCode)); + + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + // This callback may be delayed on Android until the user + // returns to the app. Place all code that interacts with + // Unity UI and GameObjects inside this callback. + Debug.Log("Rewarded interstitial ad paid callback " + + "invoked inside ExecuteInUpdate."); + }); }; // Raised when an impression is recorded for an ad. ad.OnAdImpressionRecorded += () => @@ -146,6 +159,12 @@ protected void RegisterEventHandlers(RewardedInterstitialAd ad) ad.OnAdFullScreenContentOpened += () => { Debug.Log("Rewarded interstitial ad full screen content opened."); + + // Use MobileAdsEventExecutor to ensure the UI is updated on the main thread. + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + AdLoadedStatus?.SetActive(false); + }); }; // Raised when the ad closed full screen content. ad.OnAdFullScreenContentClosed += () => @@ -157,6 +176,12 @@ protected void RegisterEventHandlers(RewardedInterstitialAd ad) { Debug.LogError("Rewarded interstitial ad failed to open full screen content" + " with error : " + error); + + // Use MobileAdsEventExecutor to ensure the UI is updated on the main thread. + MobileAdsEventExecutor.ExecuteInUpdate(() => + { + AdLoadedStatus?.SetActive(false); + }); }; } } diff --git a/samples/HelloWorld/Assets/Snippets/GlobalSettingsSnippets.cs b/samples/HelloWorld/Assets/Snippets/GlobalSettingsSnippets.cs new file mode 100644 index 000000000..11f65695d --- /dev/null +++ b/samples/HelloWorld/Assets/Snippets/GlobalSettingsSnippets.cs @@ -0,0 +1,40 @@ +using UnityEngine; +using GoogleMobileAds.Api; +using GoogleMobileAds.Common; + +namespace GoogleMobileAds.Snippets +{ + /// + /// Code snippets used for the developer guides covering global settings. + /// + internal class GlobalSettingsSnippets + { + internal GameObject _myGameObject; + + private void HandleAdEventsOnMainThread() + { + // [START execute_in_update] + // Google Mobile Ads events are raised off the Unity main thread. + + // This log is executed off the Unity main thread. + // Write all time-sensitive code before ExecuteInUpdate(). + Debug.Log("Executing off the Unity main thread."); + + // Use ExecuteInUpdate to run code on the main thread, allowing you to + // interact with Unity UI and GameObjects. + // Changed to fully-qualified name to resolve CS0103 + GoogleMobileAds.Common.MobileAdsEventExecutor.ExecuteInUpdate(() => + { + // This callback may be delayed on Android until the user returns to the app. + Debug.Log("Executing on the Unity main thread."); + + // Place all code that interacts with Unity UI and GameObjects inside this callback. + if (_myGameObject != null) + { + _myGameObject.SetActive(true); + } + }); + // [END execute_in_update] + } + } +} diff --git a/samples/HelloWorld/Assets/Snippets/GlobalSettingsSnippets.cs.meta b/samples/HelloWorld/Assets/Snippets/GlobalSettingsSnippets.cs.meta new file mode 100644 index 000000000..89af77597 --- /dev/null +++ b/samples/HelloWorld/Assets/Snippets/GlobalSettingsSnippets.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4800e421163f54edcbd27aaa8eaae488 \ No newline at end of file