Admob banner is invisible but still clickable in Unity - c#

I'm working on an app that displays a banner depending on the scene. I use Show and Hide to control this behavior.
It works perfectly the first time that the banner is shown, but the second (after being hidden) the banner does not appear. However, the banner zone still clickable and it performs as expected.
I'm using the last release of the AdMob plugin for unity (v3.15.1) and I have not been able of finding any solution to the problem.
This is my code:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GoogleMobileAds;
using GoogleMobileAds.Api;
public class AdsManager //Ads information: https://developers.google.com/admob/unity (see left menu fo detailed info of each ad type)
{
public static AdsManager instance;
public BannerView bannerAd;
public InterstitialAd interstitialAd;
public RewardBasedVideoAd rewardedVideoAd;
#if UNITY_EDITOR
private static String appId = "unused";
private static String bannerAdId = "unused";
private static String interistitialAdId = "unused";
private static String rewardedVideAdId = "TBD";
#elif UNITY_ANDROID
private static String appId = "ca-app-pub-6685658831663319~7807395346";
private static String bannerAdId = "ca-app-pub-3940256099942544/6300978111"; //"ca-app-pub-6685658831663319/9607562172";
private static String interistitialAdId = "ca-app-pub-3940256099942544/1033173712"; //"ca-app-pub-6685658831663319/4875778545";
private static String rewardedVideAdId = "ca-app-pub-3940256099942544/5224354917"; //"ca-app-pub-6685658831663319/2971919290";
#elif UNITY_IOS
private static String appId = "ca-app-pub-6685658831663319~7807395346";
private static String bannerAdId = "ca-app-pub-6685658831663319/9607562172";
private static String interistitialAdId = "ca-app-pub-6685658831663319/4875778545";
private static String rewardedVideAdId = "ca-app-pub-6685658831663319/2971919290";
#else
private static String appId = "unexpected_platform";
private static String bannerAdId = "unexpected_platform";
private static String interistitialAdId = "unexpected_platform";
private static String rewardedVideAdId = "unexpected_platform";
#endif
public enum TypeOfAd
{
Banner,
Interestitial,
RewardedVideo
}
public AdsManager()
{
Debug.Log("Initializing a new AdsManager.");
if (instance == null)
{
instance = this;
Setup();
Debug.Log("AdsManager initialization successful.");
}
else
{
Debug.Log("AdsManager already exists. New initialization unsuccessful.");
}
}
private void Setup()
{
// Initialize the Google Mobile Ads SDK.
MobileAds.Initialize(appId);
this.bannerAd = new BannerView(bannerAdId, AdSize.SmartBanner, AdPosition.Bottom); //Info to chang banner size: https://developers.google.com/admob/unity/banner#banner_sizes
SetupBannerEventHandlers();
this.interstitialAd = new InterstitialAd(interistitialAdId);
SetupInterstitialEventHandlers();
this.rewardedVideoAd = RewardBasedVideoAd.Instance;
SetupRewardedVideoAdsEventHandlers();
//Load firsts ads
instance.LoadAd(TypeOfAd.Interestitial);
instance.LoadAd(TypeOfAd.Banner);
}
private void SetupBannerEventHandlers()
{
this.bannerAd.OnAdLoaded += HandlerOnBannerAdLoaded;
this.bannerAd.OnAdFailedToLoad += HandlrOnBannerAdFailedToLoad;
this.bannerAd.OnAdOpening += HandlerOnBannerAdOpening;
this.bannerAd.OnAdClosed += HandlerOnBannerAdClosed;
this.bannerAd.OnAdLeavingApplication += HandlerOnBannerAdLeavingApplication;
}
private void SetupInterstitialEventHandlers()
{
this.interstitialAd.OnAdLoaded += HandlerOnInterstitialAdLoaded;
this.interstitialAd.OnAdFailedToLoad += HandlerOnInterstitialAdFailedToLoad;
this.interstitialAd.OnAdOpening += HandlerOnInterstitialAdOpening;
this.interstitialAd.OnAdClosed += HandlerOnInterstitialAdClosed;
this.interstitialAd.OnAdLeavingApplication += HandlerOnInterstitialAdLeavingApplication;
}
private void SetupRewardedVideoAdsEventHandlers()
{
this.rewardedVideoAd.OnAdLoaded += HandlerRewardVideoAdLoaded;
this.rewardedVideoAd.OnAdFailedToLoad += HandlerRewardVideoAdFailedToLoad;
this.rewardedVideoAd.OnAdOpening += HandlerRewardVideoAdOpening;
this.rewardedVideoAd.OnAdStarted += HandlerRewardVideoAdStarted;
this.rewardedVideoAd.OnAdRewarded += HandlerRewardVideoAdRewarded;
this.rewardedVideoAd.OnAdClosed += HandlerRewardVideoAdClosed;
this.rewardedVideoAd.OnAdLeavingApplication += HandlerRewardVideoAdLeftApplication;
}
public void LoadAd(TypeOfAd typeOfAd)
{
if (DataManager.instance.showAds)
switch (typeOfAd)
{
case TypeOfAd.Banner:
Debug.Log("Loading Banner ad");
this.bannerAd.LoadAd(new AdRequest.Builder().Build()); //After loading it, it will be automatically displayed
break;
case TypeOfAd.Interestitial:
Debug.Log("Loading Interestitial ad");
if (!this.interstitialAd.IsLoaded())
this.interstitialAd.LoadAd(new AdRequest.Builder().Build());
break;
case TypeOfAd.RewardedVideo:
Debug.Log("Loading RewardedVideo ad");
if (!this.rewardedVideoAd.IsLoaded())
this.rewardedVideoAd.LoadAd(new AdRequest.Builder().Build(), rewardedVideAdId);
break;
}
}
public bool ShowAd(TypeOfAd typeOfAd)
{
if (DataManager.instance.showAds)
switch (typeOfAd)
{
case TypeOfAd.Banner:
Debug.Log("Showing Banner ad");
this.bannerAd.Show(); //No avaliable check to know if the ad has been loaded...
return true; //...so maybe the return is true but the ad is not being displayed because it was not loaded before.
case TypeOfAd.Interestitial:
Debug.Log("Showing Interestitial ad");
if (this.interstitialAd.IsLoaded())
{
this.interstitialAd.Show();
return true;
}
else
{
Debug.LogWarning("Trying to show InterstitialAd but it is not loaded");
//TBD: Automaitcally load?
}
break;
case TypeOfAd.RewardedVideo:
Debug.Log("Showing RewardedVideo ad");
if (this.rewardedVideoAd.IsLoaded())
{
this.rewardedVideoAd.Show();
return true;
} else {
Debug.LogWarning("Trying to show RewardedBasedVideoAd but it is not loaded");
//TBD: Automaitcally load?
}
break;
}
return false;
}
public void QuitAd(TypeOfAd typeOfAd)
{
switch (typeOfAd)
{
case TypeOfAd.Banner:
Debug.Log("Quiting Banner ad");
bannerAd.Hide();
break;
case TypeOfAd.Interestitial:
Debug.Log("Quiting Interestitial ad");
Debug.LogError("QuitAd Interestitial Not Implemented");
break;
case TypeOfAd.RewardedVideo:
Debug.Log("Quiting RewardedVideo ad");
Debug.LogError("QuitAd RewardedVideo Not Implemented");
break;
}
}
//BANNER EVENT HANDLERS
public void HandlerOnBannerAdLoaded(object sender, EventArgs args) { } // Called when an ad request has successfully loaded.
public void HandlrOnBannerAdFailedToLoad(object sender, AdFailedToLoadEventArgs args) { Debug.LogWarning("Banner failed to load: " + args.Message); LoadAd(TypeOfAd.Banner); } // Called when an ad request failed to load.
public void HandlerOnBannerAdOpening(object sender, EventArgs args) { } // Called when an ad is clicked.
public void HandlerOnBannerAdClosed(object sender, EventArgs args) { } // Called when the user returned from the app after an ad click.
public void HandlerOnBannerAdLeavingApplication(object sender, EventArgs args) { } // Called when the ad click caused the user to leave the application.
//INTERSTITIAL EVENT HANDLERS
public void HandlerOnInterstitialAdLoaded(object sender, EventArgs args) { } // Called when an ad request has successfully loaded.
public void HandlerOnInterstitialAdFailedToLoad(object sender, AdFailedToLoadEventArgs args) { Debug.LogWarning("Interstitial failed to load: " + args.Message); LoadAd(TypeOfAd.Interestitial); } // Called when an ad request failed to load.
public void HandlerOnInterstitialAdOpening(object sender, EventArgs args) { } // Called when an ad is shown.
public void HandlerOnInterstitialAdClosed(object sender, EventArgs args) { } // Called when the ad is closed.
public void HandlerOnInterstitialAdLeavingApplication(object sender, EventArgs args) { } // Called when the ad click caused the user to leave the application.
//REWARDED VIDEO AD EVENT HANDLERS
public void HandlerRewardVideoAdLoaded(object sender, EventArgs args) { } // Called when an ad request has successfully loaded.
public void HandlerRewardVideoAdFailedToLoad(object sender, AdFailedToLoadEventArgs args) { Debug.LogWarning("RewardedVideo failed to load: " + args.Message); LoadAd(TypeOfAd.RewardedVideo); } // Called when an ad request failed to load.
public void HandlerRewardVideoAdOpening(object sender, EventArgs args) { } // Called when an ad is shown.
public void HandlerRewardVideoAdStarted(object sender, EventArgs args) { } // Called when the ad starts to play.
public void HandlerRewardVideoAdRewarded(object sender, Reward args) { Debug.Log("Rewarded video ad completed. Reward info: " + args.Amount + " of " + args.Type); } // Called when the user should be rewarded for watching a video.
public void HandlerRewardVideoAdClosed(object sender, EventArgs args) { } // Called when the ad is closed.
public void HandlerRewardVideoAdLeftApplication(object sender, EventArgs args) { } // Called when the ad click caused the user to leave the application.
}
To show the ads I'm simply calling the method ShowAd and to hide them I'm calling the method QuitAd. I think that both perform as expected because they work the first time they are called and because in the scenes where the HideAd is called the "banner area" is not clickable but when te ShowAd method is called you can click on the invisible banner.
Thank you for any help!

In my case canvas for some reason overlapped banner, i just unchecked "Render Over native UI" in PlayerSettings -> Resolution and Presentation and now it works fine.

I solved the problem by destroying the banner in the QuitAd method:
public void QuitAd(TypeOfAd typeOfAd)
{
switch (typeOfAd)
{
case TypeOfAd.Banner:
Debug.Log("Quiting Banner ad");
bannerAd.Destroy();
break;
case TypeOfAd.Interestitial:
Debug.Log("Quiting Interestitial ad");
Debug.LogError("QuitAd Interestitial Not Implemented");
break;
case TypeOfAd.RewardedVideo:
Debug.Log("Quiting RewardedVideo ad");
Debug.LogError("QuitAd RewardedVideo Not Implemented");
break;
}
}
And then I've modified the ShowAd method loading the banner before showing it:
public bool ShowAd(TypeOfAd typeOfAd)
{
if (DataManager.instance.showAds)
switch (typeOfAd)
{
case TypeOfAd.Banner:
Debug.Log("Showing Banner ad");
LoadAd(TypeOfAd.Banner); //Every time the banner is asked to be shown it will try to load before being shown.
this.bannerAd.Show(); //Will be show after loading
return true;
case TypeOfAd.Interestitial:
Debug.Log("Showing Interestitial ad");
if (this.interstitialAd.IsLoaded())
{
this.interstitialAd.Show();
return true;
}
else
{
Debug.LogWarning("Trying to show InterstitialAd but it is not loaded");
//TBD: Automaitcally load?
}
break;
case TypeOfAd.RewardedVideo:
Debug.Log("Showing RewardedVideo ad");
if (this.rewardedVideoAd.IsLoaded())
{
this.rewardedVideoAd.Show();
return true;
} else {
Debug.LogWarning("Trying to show RewardedBasedVideoAd but it is not loaded");
//TBD: Automaitcally load?
}
break;
}
return false;
}
However, I do not know if this is a proper solution because a new load request will be done every time a banner has to be shown (after a scene where it is not shown).
Additionally, this "solution" is only a different approach for the same objective, not a fix for the original approach.
So if anyone knows why the original code is not working I would appreciate a lot the sharing of this knowledge.

Related

Rewarded video ads events not firing in Unity and Admob

I am using Unity 2019.2.8f1 and I am preparing to publish my first game on Google Play Store. Unfortunately the reward is not being given to the user after watching a rewarded ad. The user should get an extra life whenever he/she watches a rewarded ad.
Here is my Ad Manager script. I am using dummy ids for testing.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GoogleMobileAds.Api;
using System;
public class AdManager : MonoBehaviour
{
public static AdManager instance;
private string AppId = "ca-app-pub-3940256099942544~3347511713";
private BannerView banner;
private string bannerID = "ca-app-pub-3940256099942544/6300978111";
private InterstitialAd videoAD;
private string videoID = "ca-app-pub-3940256099942544/1033173712";
private int showing, video;
private RewardBasedVideoAd rewardedAds;
private string rewardedID = "ca-app-pub-3940256099942544/5224354917";
public bool RewardTaken;
public void HandleRewardBasedVideoClosed(object sender, EventArgs args)
{
Debug.Log("HandleRewardBasedVideoClosed event received");
RequestRewardedAD();
}
public void HandleRewardBasedVideoRewarded(object sender, Reward args)
{
UIManager.variable.RewardPanel.SetActive(true);
UIManager.variable.gameOver.SetActive(false);
}
private void Awake()
{
rewardedAds = RewardBasedVideoAd.Instance;
showing = PlayerPrefs.GetInt("show");
video = PlayerPrefs.GetInt("video");
MobileAds.Initialize(AppId);
RequestvideoAD();
if (instance == null)
{
instance = this;
}
else
{
Destroy(this);
}
}
private void Start()
{
RewardTaken = false;
if (video == 1)
{
ShowvideoAD();
}
if (showing == 1)
{
requestBanner();
}
RequestRewardedAD();
// Called when the user should be rewarded for watching a video.
rewardedAds.OnAdRewarded += HandleRewardBasedVideoRewarded;
// Called when the ad is closed.
rewardedAds.OnAdClosed += HandleRewardBasedVideoClosed;
}
public void requestBanner()
{
banner = new BannerView(bannerID, AdSize.Banner, AdPosition.Bottom);
AdRequest request = new AdRequest.Builder().Build();
banner.LoadAd(request);
banner.Show();
}
public void RequestvideoAD()
{
videoAD = new InterstitialAd(videoID);
AdRequest request = new AdRequest.Builder().Build();
videoAD.LoadAd(request);
}
public void ShowvideoAD()
{
if (videoAD.IsLoaded())
{
videoAD.Show();
}
else
{
Debug.Log("FullscreenADNotLoaded");
}
}
public void RequestRewardedAD()
{
AdRequest request = new AdRequest.Builder().Build();
rewardedAds.LoadAd(request,rewardedID);
}
public void ShowRewardedAD()
{
if(rewardedAds.IsLoaded())
{
rewardedAds.Show();
Debug.Log("Ads Are Working");
}
else
{
Debug.Log("Rewarded Ads not laded properly");
}
}
public void HideAD()
{
banner.Hide();
}
}
Even though the console was not showing any message that I wanted to show as a part of the test. After trying several times, I decided to remove the debug text.
It looks like you are attaching Callbacks to a different ad object and you are loading ads from a different object.
Try using rewardedAds
to Load Ad
public void RequestvideoAD()
{
AdRequest request = new AdRequest.Builder().Build();
rewardedAds.LoadAd(request);
}

Admob video reward plays once only

I've been trying to implement the Admob services on a game I developed. But the reward video system is giving me headaches.
When I launch the app, the video ad shows and gives the player the rewards I programed for.
But the second time I press the button to watch the video, nothing happens. The video does not load not show.
My code:
private RewardBasedVideoAd rewardBasedVideo;
public GameObject GameOverUI;
public GameObject RewardPanel;
public int count=0;
public static string OutputMessage
{
set { outputMessage = value; }
}
public static GoogleMobileAdsDemoScript instance = null;
public static GoogleMobileAdsDemoScript Instance
{
get{return instance;}
}
void Awake()
{
if (instance != null && instance != this)
{
Destroy(this.gameObject);
return;
}
else
{
instance = this;
}
DontDestroyOnLoad(this.gameObject);
}
public void Start()
{
// Get singleton reward based video ad reference.
this.rewardBasedVideo = RewardBasedVideoAd.Instance;
// RewardBasedVideoAd is a singleton, so handlers should only be registered once.
this.rewardBasedVideo.OnAdLoaded += this.HandleRewardBasedVideoLoaded;
this.rewardBasedVideo.OnAdFailedToLoad += this.HandleRewardBasedVideoFailedToLoad;
this.rewardBasedVideo.OnAdOpening += this.HandleRewardBasedVideoOpened;
this.rewardBasedVideo.OnAdStarted += this.HandleRewardBasedVideoStarted;
this.rewardBasedVideo.OnAdRewarded += this.HandleRewardBasedVideoRewarded;
this.rewardBasedVideo.OnAdClosed += this.HandleRewardBasedVideoClosed;
this.rewardBasedVideo.OnAdLeavingApplication += this.HandleRewardBasedVideoLeftApplication;
this.RequestRewardBasedVideo ();
}
//
// Returns an ad request with custom ad targeting.
private AdRequest CreateAdRequest()
{
return new AdRequest.Builder().Build();
}
private void RequestRewardBasedVideo()
{
#if UNITY_ANDROID
string adUnitId = "ca-app-pub-3940256099942544/5224354917";
#elif UNITY_IPHONE
string adUnitId = "ca-app-pub-3940256099942544/5224354917";
#else
string adUnitId = "unexpected_platform";
#endif
this.rewardBasedVideo.LoadAd(this.CreateAdRequest(), adUnitId);
}
public void LoadAd()
{
RequestRewardBasedVideo();
}
public void ShowRewardBasedVideo()
{
if (this.rewardBasedVideo.IsLoaded())
{
count++;
PlayerPrefs.SetInt ("adstype", 1);
this.rewardBasedVideo.Show();
}
else
{
MonoBehaviour.print("Reward based video ad is not ready yet");
}
}
#region RewardBasedVideo callback handlers
public void HandleRewardBasedVideoLoaded(object sender, EventArgs args)
{
MonoBehaviour.print("HandleRewardBasedVideoLoaded event received");
}
public void HandleRewardBasedVideoFailedToLoad(object sender, AdFailedToLoadEventArgs args)
{
RequestRewardBasedVideo ();
MonoBehaviour.print(
"HandleRewardBasedVideoFailedToLoad event received with message: " + args.Message);
}
public void HandleRewardBasedVideoOpened(object sender, EventArgs args)
{
MonoBehaviour.print("HandleRewardBasedVideoOpened event received");
}
public void HandleRewardBasedVideoStarted(object sender, EventArgs args)
{
MonoBehaviour.print("HandleRewardBasedVideoStarted event received");
}
public void HandleRewardBasedVideoClosed(object sender, EventArgs args)
{
RequestRewardBasedVideo();
MonoBehaviour.print("HandleRewardBasedVideoClosed event received");
}
public void HandleRewardBasedVideoRewarded(object sender, Reward args)
{
string type = args.Type;
double amount = args.Amount;
MonoBehaviour.print(
"HandleRewardBasedVideoRewarded event received for " + amount.ToString() + " " + type);
GameOverUI.SetActive(false);
RewardPanel.SetActive(true);
}
public void HandleRewardBasedVideoLeftApplication(object sender, EventArgs args)
{
MonoBehaviour.print("HandleRewardBasedVideoLeftApplication event received");
}
public void ReceiveReward()
{
StartCoroutine(Restarttime());
}
IEnumerator Restarttime()
{
Time.timeScale = 1f;
PlayerPrefs.SetInt("ScoreReward", 1);
yield return new WaitForSeconds(0.2f);
RewardPanel.SetActive(false);
SceneManager.LoadScene("Game");
}
#endregion
}
Any help is welcome.
Thank you very much!

How to properly reward player with Admob rewarded video in Unity?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GoogleMobileAds.Api;
using UnityEngine.UI;
public class AdManager : MonoBehaviour {
RewardBasedVideoAd rewardBasedVideo;
static InterstitialAd interstitial;
string VideoID = "ca-app-pub-3888784411212422/2850896103";
string adUnitId = "ca-app-pub-3888784411212422/4158795262";
public static AdManager Instance;
void Start ()
{
Instance = this;
DontDestroyOnLoad(gameObject);
RequestRewardBasedVideo();
RequestInterstitial();
}
public void RequestRewardBasedVideo()
{
rewardBasedVideo = RewardBasedVideoAd.Instance;
rewardBasedVideo.LoadAd(new AdRequest.Builder().Build(), adUnitId);
}
public void RequestInterstitial()
{
interstitial = new InterstitialAd(VideoID);
interstitial.LoadAd(new AdRequest.Builder().Build());
}
public void ShowAd()
{
if(rewardBasedVideo.IsLoaded())
{
rewardBasedVideo.Show();
rewardBasedVideo.OnAdRewarded += HandleRewardBasedVideoRewarded;
}
}
public static void ShowInter()
{
showInterstitial(interstitial);
}
private void showAdd(RewardBasedVideoAd r)
{
if (r.IsLoaded())
{
//Subscribe to Ad event
r.Show();
r.OnAdRewarded += HandleRewardBasedVideoRewarded;
}
}
public void HandleRewardBasedVideoRewarded(object sender, Reward args)
{
PlayerPrefs.SetInt("coin", PlayerPrefs.GetInt("coin") + 200);
GameObject.FindGameObjectWithTag("Coin").GetComponent<Text>().text = PlayerPrefs.GetInt("coin").ToString();
GameObject.FindGameObjectWithTag("Double").GetComponent<Button>().interactable = false;
Debug.Log("Pref: " + PlayerPrefs.GetInt("coin"));
}
static void showInterstitial(InterstitialAd i)
{
if (i.IsLoaded())
{
i.Show();
}
}
}
I am rewarding players with 200 coins, but somehow every time i get reward increased by 200. First time when player get rewarded he gets 200, next time he gets 400, next time 600 etc. I have tried to change code in many ways but no positive result.
Method that is called upon button click is ShowAd(). Every time when panel with button thats calls the method is shown i call RequestRewardBasedVideo().
adding and creating new objects is the answer,
for example the Void would have something like that
public void HandleRewardBasedVideoRewarded(object sender, Reward args)
{
int CoinOld = PlayerPrefs.GetInt("coin");
CoinOld += 200;
PlayerPrefs.SetInt("coin", CoinOld);
GameObject.FindGameObjectWithTag("Coin").GetComponent<Text>().text = PlayerPrefs.GetInt("coin").ToString();
GameObject.FindGameObjectWithTag("Double").GetComponent<Button>().interactable = false;
Debug.Log("Pref: " + PlayerPrefs.GetInt("coin"));
}

Chartboost ads not showing in Unity 3D Game

I have a simple platformer game in which I'm using chartboost and unity ads t show ads and I it was working fine during the test mode but ever since I deployed to production and disabled the test mode in both chartboost and unity ads I noticed that my interstitial ads and videos don't load or show except once in a blue moon that too of a same game and then it start failing again.
I also noticed that my ads impression are quite low on the chartboost and Unity. Can you please tell me if I code for it correctly? I used the chartboost example an built my ad controller through it, oh and I'm using caching for ads and unless ad isn't cached already I won't show it.
Here's the code:
using UnityEngine;
using System.Collections;
using UnityEngine.Advertisements;
using ChartboostSDK;
using System;
public class AdsController : MonoBehaviour
{
public static AdsController instance;
// app id for unity apps
private const string _appId = "someID";
public bool canShowChartBoostInterstitial;
public bool canShowChartBoostVideo;
private void Awake()
{
MakeSingleton();
if (!canShowChartBoostInterstitial)
{
LoadChartBoostInterstitialAds();
}
if (!canShowChartBoostVideo)
{
LoadChartBoostVideoAds();
}
LoadUnityAds();
}
private void MakeSingleton()
{
if (instance != null)
{
Destroy(gameObject);
}
else
{
instance = this;
DontDestroyOnLoad(gameObject);
}
}
private void OnLevelWasLoaded()
{
if (Application.loadedLevelName == "LevelMenu")
{
if (GameController.instance.canShowAds)
{
if (canShowChartBoostInterstitial)
{
ShowChartBoostInterstitial();
}
else
{
LoadChartBoostInterstitialAds();
}
}
}
}
private void OnEnable()
{
Chartboost.didCompleteRewardedVideo += VideoCompleted;
Chartboost.didCacheInterstitial += DidCacheInterstitial;
Chartboost.didDismissInterstitial += DidDismissInterstitial;
Chartboost.didCloseInterstitial += DidCloseInterstitial;
Chartboost.didCacheRewardedVideo += DidCacheVideo;
Chartboost.didFailToLoadInterstitial += FailedToLoadInterstitial;
Chartboost.didFailToLoadRewardedVideo += FailedToLoadVideo;
}
private void OnDisable()
{
Chartboost.didCompleteRewardedVideo -= VideoCompleted;
Chartboost.didCacheInterstitial -= DidCacheInterstitial;
Chartboost.didDismissInterstitial -= DidDismissInterstitial;
Chartboost.didCloseInterstitial -= DidCloseInterstitial;
Chartboost.didCacheRewardedVideo -= DidCacheVideo;
Chartboost.didFailToLoadInterstitial -= FailedToLoadInterstitial;
Chartboost.didFailToLoadRewardedVideo -= FailedToLoadVideo;
}
public void VideoCompleted(CBLocation location, int reward)
{
canShowChartBoostVideo = false;
if (RewardController.instance != null)
{
RewardController.instance.VideoWatchedGiveUserAReward();
}
LoadChartBoostVideoAds();
}
public void DidCacheInterstitial(CBLocation location)
{
canShowChartBoostInterstitial = true;
}
public void DidDismissInterstitial(CBLocation location)
{
canShowChartBoostInterstitial = false;
LoadChartBoostVideoAds();
LoadChartBoostInterstitialAds();
}
public void DidCloseInterstitial(CBLocation location)
{
canShowChartBoostInterstitial = false;
LoadChartBoostVideoAds();
LoadChartBoostInterstitialAds();
}
public void DidCacheVideo(CBLocation location)
{
canShowChartBoostVideo = true;
}
private void FailedToLoadInterstitial(CBLocation location, CBImpressionError error)
{
canShowChartBoostInterstitial = false;
LoadChartBoostInterstitialAds();
}
private void FailedToLoadVideo(CBLocation location, CBImpressionError error)
{
canShowChartBoostVideo = false;
if (ShopMenuController.instance != null)
{
ShopMenuController.instance.FailedToLoadTheVideo();
}
LoadChartBoostVideoAds();
}
public void LoadChartBoostVideoAds()
{
Chartboost.cacheRewardedVideo(CBLocation.Default);
}
public void LoadChartBoostInterstitialAds()
{
Chartboost.cacheInterstitial(CBLocation.Default);
}
public void ShowChartBoostInterstitial()
{
if (canShowChartBoostInterstitial)
{
Chartboost.showInterstitial(CBLocation.Default);
}
else
{
LoadChartBoostInterstitialAds();
}
}
public void ShowChartBoostVideo()
{
if (canShowChartBoostVideo)
{
Chartboost.showRewardedVideo(CBLocation.Default);
}
else
{
LoadChartBoostVideoAds();
}
}
public void LoadUnityAds()
{
if (Advertisement.isSupported)
{
Advertisement.Initialize(_appId, false);
}
}
public void ShowUnityAds()
{
if (Advertisement.IsReady())
{
Advertisement.Show(null, new ShowOptions()
{
resultCallback = result =>
{
switch (result)
{
case ShowResult.Finished:
GameController.instance.RewardPlayerWithSomething();
LoadUnityAds();
break;
case ShowResult.Failed:
GameController.instance.VideoNotLoadedOrUserSkippedTheVideo("Failed to load the video. Please try again.");
LoadUnityAds();
break;
case ShowResult.Skipped:
GameController.instance.VideoNotLoadedOrUserSkippedTheVideo("Video skipped.");
LoadUnityAds();
break;
}
}
});
}
else
{
GameController.instance.VideoNotLoadedOrUserSkippedTheVideo("Failed to load the video. Please try again.");
LoadUnityAds();
}
}
}
Run cache after every time you show an interstitial.
like this :
Chartboost.showInterstitial(CBLocation.Default);
Chartboost.cacheInterstitial(CBLocation.Default);
That way you will replenish the cache every time you show an ad.
Remember to cache as soon as its initialized as well.

Using a windows forms timer to trigger a method from in a different class

Apologies if there are already answers out there for this, but I've dug a lot and found little.
I'm trying to implement a watchdog system on a C# .NET 4.5 Windows Forms Application. Basically, I have a form with various buttons, text displays, etc, that connects to an external device. I have a timer on the main form that should check the device for changes every 250ms or so.
I've lumped all MainPage form code, including the timer, into one class, and the code for the external device into its own class that inherits from MainPage. Trouble is, I want to be able to have the timer's Tick() function call a method from the Device class. Here's simplified code:
namespace MyApplication
{
public partial class MainPage : Form
{
public MainPage()
{
InitializeComponent();
}
public static void SetTextBox(string Message)
{
Textbox_Status.Text = Message;
}
private void timer1_Tick(object sender, EventArgs e)
{
Device.DeviceCheck();
}
}
public class Device : MainPage
{
public void DeviceCheck()
{
//Do other stuff here
SetTextBox("Some text");
}
}
}
Naturally, I can't call Device.DeviceCheck from within the timer because it's not static. However, if I declare DeviceCheck static, I now get an error that Textbox_Status is not static. If I try to declare it static, Visual Studio gets VERY mad at me!
Originally, I had dumped everything into the same class and it all worked fine, but that is very ugly code. Is there a better way?
EDIT: The extra snag = more than one thing in the form that needs to be changed by DeviceCheck()
So what I left out of the simplified code: in addition to the SetTextBox() method, I also have a method in the form that sets some indicators, based on information from DeviceCheck:
public void SetImages(string Image)
{
switch(Image)
{
case "Green":
Image_BlackDim.Visible = true;
Image_RedDim.Visible = true;
Image_GreenDim.Visible = false;
break;
case "Red":
Image_BlackDataKeyDim.Visible = true;
Image_RedDataKeyDim.Visible = false;
Image_GreenDataKeyDim.Visible = true;
break;
case "Black":
Image_BlackDim.Visible = false;
Image_RedDim.Visible = true;
Image_GreenDim.Visible = true;
break;
case "None":
default:
Image_BlackDim.Visible = true;
Image_RedDim.Visible = true;
Image_GreenDim.Visible = true;
break;
}
}
Naturally all my indicators are also put in place when I construct the form, so they can't be static either. So having DeviceCheck return the string message to be displayed works, but I can't really have it ALSO return the string that SetImages() uses.
Well... I could, by returning a struct with multiple strings, but is there a better way?
EDIT: Here's my working solution, based on Eric's advice:
I start out with a struct for the status elements:
public struct Dev_status
{
public string Indicator1;
public string Indicator2;
public DK_status(string indicator1, string indicator1)
{
this.Indicator1 = indicator1;
this.Indicator2 = indicator2;
}
}
public static Dev_status status = new Dev_status(Device.Messages.thing1_offline,Device.Messages.thing2_offline);
The indicators now grab the messages from status:
public void SetStatusBoxes()
{
Textbox_thing1_Status.Text = status.Indicator1;
Textbox_thing2_Status.Text = status.Indicator2;
}
public void SetImages()
{
string IndicatorColor = "None";
if (status.Indicator2 == Device.Messages.GreenThing) IndicatorColor = "Green";
else if (status.Indicator2 == Device.Messages.RedThing) IndicatorColor = "Red";
else if (status.Indicator2 == Device.Messages.BlackThing) IndicatorColor = "Black";
switch(IndicatorColor)
{
case "Green":
Image_BlackDim.Visible = true;
Image_RedDim.Visible = true;
Image_GreenDim.Visible = false;
break;
case "Red":
Image_BlackDim.Visible = true;
Image_RedDim.Visible = false;
Image_GreenDim.Visible = true;
break;
case "Black":
Image_BlackDim.Visible = false;
Image_RedDim.Visible = true;
Image_GreenDim.Visible = true;
break;
case "None":
default:
Image_BlackDim.Visible = true;
Image_RedDim.Visible = true;
Image_GreenDim.Visible = true;
break;
}
}
And the timer just calls the DeviceCheck method and sets the indicators:
private void timer1_Tick(object sender, EventArgs e)
{
status = Device.DeviceCheck();
SetStatusBoxes();
SetImages();
}
Finally, DeviceCheck sets values for the status struct which is public, static, and inherited by the Device class:
public static void DeviceCheck()
{
//Code that checks the device status
status.Indicator1 = CheckDeviceConnected();
status.Indicator2 = CheckDeviceType();
}
This works pretty seamlessly. In the end I didn't need to return values from DeviceCheck after all. I'll still mark that idea as accepted though, since it led me in the right direction.
What if you
1) had DeviceCheck() return the string that you want in the text box (instead of setting the text box)
2) within timer1_Tick(), set the text box with the return value from DeviceCheck.
Like this:
namespace MyApplication
{
public partial class MainPage : Form
{
public MainPage()
{
InitializeComponent();
}
public static void SetTextBox(string Message)
{
Textbox_Status.Text = Message;
}
private void timer1_Tick(object sender, EventArgs e)
{
string result = Device.DeviceCheck();
SetTextBox(result);
}
}
public class Device : MainPage
{
public string DeviceCheck()
{
//Do other stuff here
return("Some text");
}
}
}
I see two obvious options here: declare DeviceCheck() as an abstract method for subclasses to implement, or expose the timer tick event somehow.
Abstract method:
public partial abstract class MainPage : Form
{
public MainPage()
{
InitializeComponent();
}
public void SetTextBox(string message)
{
Textbox_Status.Text = message;
}
protected abstract void DeviceCheck();
private void timer1_Tick(object sender, EventArgs e)
{
DeviceCheck();
}
}
public class Device : MainPage
{
public void DeviceCheck()
{
//Do other stuff here
SetTextBox("Some text");
}
}
Event:
public partial abstract class MainPage : Form
{
public MainPage()
{
InitializeComponent();
}
public void SetTextBox(string message)
{
Textbox_Status.Text = message;
}
protected event EventHandler TimerTick;
private void timer1_Tick(object sender, EventArgs e)
{
EventHandler handler = TimerTick;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
public class Device : MainPage
{
public Device()
{
TimerTick += (sender, e) => DeviceCheck();
}
public void DeviceCheck()
{
//Do other stuff here
SetTextBox("Some text");
}
}
The other suggested answer should work too, assuming the static is removed from the SetTextBox() method. But based on your comment it sounds like the message handling (i.e. the string value) is just part of what you want to do. You could still follow that suggestion though, but you'd pass some kind of aggregate object instead of the string, i.e. a simple container class with multiple properties, including the message string and any other values you need.

Categories

Resources