Iām trying to implement interstitial ads in my game using AdMob and Iām having some trouble. It turns out that if an ad is currently showing and you task switch (either via task switch buttons or by simply clicking the ad), the MonoGame application dies.
Iāve created some code for a simple test application that demonstrates the issue.
Create a new MonoGame Android Application (I did this in Visual Studio 2017 with MonoGame 3.6 installed)
Add a NuGet package for Xamarin.GooglePlayServices.Ads
Replace the code in Activity1.cs with the code found here: https://pastebin.com/Raad2rYM
NOTE: You will need an Ad Unit ID that you get from AdMob, or some other public test ID. I have one but Iām not sure if Iām supposed to shareā¦ new to this
Run the code on a simulator. Iām using Nexus_5X_API_24 (Android 7.0 - API 24) that I created via Android Studio.
Once the program starts, wait until the rectangle turns green.
Task switch to the home screen.
Task switch back to the test game. Observe that it comes back as expected.
Click the green rectangle. A test ad will appear.
Click the X to close the test ad. Observe that the application re-appears.
Perform a task switch away and back. Observe that the application re-appears.
Click the green rectangle to show another test ad.
Without closing the ad, task switch to the home screen.
Task switch back to the app. The ad is currently visible.
Click the X button to close the ad. The application switches to the home screen and the app is seemingly unrecoverable.
Here is a paste of the entire log I get when I run this code using the steps above. Iāll admit I donāt really understand whatās going on, but from the googling Iāve been doing and the breakpoints Iāve been setting, it looks like the activity itself is crashing, leaving only the ad behind.
Log dump: << See reply >>*
The reason I suspect that this has to do with MonoGame is that Iāve recreated this application using a Xamarin Android App using a simple activity containing a button, as well as an OpenGL activity, and have not been able to reproduce it. I only get this behaviour when using MonoGame.
Iām hoping thereās a setting Iām missing here because thus far Iāve been unable to work around this. The crash happens when I task switch when the ad is showing, so Iāve already gotten the OnPause event from the acitivity and Iām not sure how to get an OnPause event from the ad itself, in order to detect when that is task switched.
Iām thinking this might actually be a bug within MonoGame, but this is new territory for me so it could just as easily be user error. Has anybody else encountered this or have any ideas? If this is entering possible bug territory, if thereās any way I can help the devs track down the issue, Iām happy to help.
Thanks!
Gary
Apparently new users can only put two links in a post, so Iāll add a link to the log dump in a reply, if it lets me.
Ok, Iāve done a lot more researchā¦ by which, of course, I mean furiously hacking away. Iām not entirely sure if the application is crashingā¦ something is going wrong; however, both the activity and the game objects are still alive and can provide data. For some reason, the view just doesnāt show anymoreā¦ and I have no idea why.
I discovered that with this bit of code, you can actually detect this state.
private bool CheckIfApplicationAlive()
{
bool appAlive = false;
try
{
View gameView = _game.Services.GetService<View>();
if (gameView == null || gameView.IsShown == false)
throw new Exception("Game view did not show after ad close.");
appAlive = true;
}
catch { }
return appAlive;
}
I put a call to this method in my AdListenerās AdClosed event (routed from AdListener.OnAdClosed). Through testing, Iāve discovered that under normal circumstances, the gameās view comes back after an ad is closed and IsShown will be true. Under this weird state, IsShown will be false after the ad closes.
So when this happens, I can do somethingā¦ what that something is has proven to be quite a challenge! I tried calling the Activityās Finish and FinishAndRemoveTask methods; however, something is keeping the task open somehow. It shows up in the task list and keeps my Visual Studio debugging session open. About the absolute best Iāve managed to do is to create a new activity that shows an error message, then show that activity. This error message summed up is pretty much āI donāt evenā¦ sorryā¦ please kill application manually and donāt hate me forever.ā
Anyway, something is definitely up hereā¦ hopefully others have some ideas.
Is this cool? Iām trying to provide as much information on this as possible in the hopes that, if there is an issue within MonoGame here, the devs have as much information as possible for their investigations. Of course, I also get a notification when Iām posting that I shouldnāt post several posts in a rowā¦ Iām new here so if this isnāt cool, please let me know what the accepted approach is
For now though, the results of my latest experiment. Since Iāve confirmed in a previous test that the issue doesnāt present itself when performed from a normal Android application (Xamarin), I figured I would try having my game activity launch a different activity that would be responsible for showing ads. I put all the ad stuff inside that activity so that nothing was in my main game, then when the button was clicked, I launched the separate activity. I still got the issueā¦ as soon as I closed the ad after task switching back, the application quit out to the main screen again.
Iām not sure if this is helpfulā¦ but maybe it will help somehow? I dunnoā¦ but thatās all Iāve got for now.
I still have no idea whatās causing this, but I have discovered a half workaround. By half, I mean it will allow recovery if you task switch while an ad is open, but only if you didnāt click the ad itself (which launches a web browser linked to your main activity).
The general idea is as followsā¦
Create a new activity, MainActivity, to serve as a host for the application. This has MainLauncher = true set in the attributes and does not launch the mono game class. Ensure LaunchMode is set to SingleInstance as well.
Remove MainLauncher = true from your MonoGame Activityā¦ say, MonoGameActivity.
In MainActivity.OnResume, have it switch to the game activity the first time, but all other times have it just show an Ad.
In the OnAdClosed method, have it switch to the game activity.
In the game activity, when itās time to show an ad, have it change to MainActivity. This will trigger an ad to show and, when that ad closes, it will switch back to the game activity.
Here is the code that makes up my MainActivity class: https://pastebin.com/5GEh73GR
In the Activity1.cs code above, I got rid of all the references to the InterstitialAd object and, in ShowAd, I simply put the following code:
{
Intent i = new Intent(this, typeof(MainActivity));
this.StartActivity(i);
}```
This sort of works, but isn't ideal because you can still get the issue if you click the ad, then task switch back to the game without closing the web browser that was launched. If you close the web browser first, everything comes back fine, but if you leave the browser open, it breaks.
So it's something... at least?
Looks like the above workaround doesnāt help under the following scenarioā¦
Show ad
Click ad (triggers a web browser to open).
Without closing the web browser, task switch back to the game.
If you close the web browser first, everything is restored, but if you donāt, you get the same issue as above.
/sads
Itās something, but itās definitely not ideal to have this issue occur when a user opens an ad. It seems a very reasonable use case that someone would click the ad, then task switch back to the game. Users shouldnāt be punished in this way.
This issue is quite frustrating. Not sure what to try nextā¦ maybe something will come to me later. Iāll report back with findings if anything comes of it.
Extra bad newsā¦ the work around isnāt really sound. It leads to other problems with resuming the game via tapping the icon instead of picking it from the task list. I can see ways to solve this; however, itās really just another band-aid to a workaround that doesnāt entirely fix the issue anyway.
I really need some help here, and am disappointed in the lack of response and engagement by the dev team (or anyone) on this issue. Iām quite at a loss on how to proceed.
*Edit: I canāt seem to edit the original title anymore. Can someone please remove the ā[WORKAROUND-ISH]ā component, as the proposed workaround is not correct.
I just read your posted issue in github. First of all I just want to say that the emulator never should be trusted. Always test with a real device. (I donāt know if youāve already done that already).
Once said that, Iāve tested your code in a tablet and the problem differs slightly to what you mentioned, but still is a problem.
However moving to LaunchMode.SingleTop instead of LaunchMode.SingleInstance seems to fix the problem, at least in my device. (actually itās the mode I use in the games Iāve released, and never had a similar report)
I hope it helps.
p.s. I had to use AdMob 42.1021.1 because I couldnāt install the latest (I donāt have the latest SDK)
I unfortunately donāt have a physical Android device and have thus far been doing all of my development on the emulator. Iām working on getting a device, but havenāt been able to yet. I appreciate the advice though and hopefully can get one soon
Having said that, I gave your advice a try and switched my LaunchMode to SingleTop instead of SingleInstance and this seems to have resolved the issue, even on my emulator. This is kinda huge, thank you so much!
Iāll be doing some research to better understand this property, but I donāt suppose you can tell me what this means, and why this makes a difference?
Honestly, I canāt remember. A year ago or so I had a similar problem with android achievements notifications. I had a look at it and choose SingleTop (basically it was the only one which allowed me to use achievements and adverts without problems). The knowledge has been out of the cache for some time now.
I keep the link that cast some light over this issue for me, though =)