Google AdMob ads not showing in Unity - android

I am making a Flappy Bird game and trying to display ads when the Bird dies.
I have setup Google AdMob and UnityAds from Google AdMob Console and Unity Dashboard respectively.
This is my code below.
using GoogleMobileAds.Api;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class GameController : MonoBehaviour {
public static GameController instance;
public GameObject gameOverText;
public bool isGameOver = false;
public float scrollSpeed = -1.5f;
public Text scoreText;
private int score = 0;
private InterstitialAd interstitialAd;
// Awake is called before Start
void Awake() {
if(instance == null) {
instance = this;
} else if (instance != null) {
Destroy(gameObject);
}
}
// Start is called before the first frame update
void Start() {
MobileAds.Initialize(initStatus => { });
RequestInterstitial();
}
private void RequestInterstitial() {
string adUnitId = "unexpected_platform";
#if UNITY_ANDROID
adUnitId = Values.TEST_ANDROID_AD_UNIT_ID;
#endif
// Initialize InterstitialAd
this.interstitialAd = new InterstitialAd(adUnitId);
// Create empty ad request
AdRequest request = new AdRequest.Builder().Build();
// Load interstitial with the request
this.interstitialAd.LoadAd(request);
}
public void ShowAd() {
if (this.interstitialAd.IsLoaded()) {
this.interstitialAd.Show();
}
}
// Update is called once per frame
void Update() {
if(isGameOver && Input.GetKey(KeyCode.Space)) {
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
} else if (isGameOver && Input.touchCount > 0) {
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
public void BirdScored() {
if(isGameOver) {
return;
}
score++;
scoreText.text = "Score: " + score;
}
public void BirdDied() {
gameOverText.SetActive(true);
isGameOver = true;
ShowAd();
}
}
The code reaches the ShowAd() function when I debug but the ad is not displayed.
What am I doing wrong?

Related

How to implement SkuDetailsResponseListener for in-app billing?

I want to include in-app billing in my Android app.
When reading the documentation it says to:
"specify a listener which implements the SkuDetailsResponseListener interface. You can then override onSkuDetailsResponse() which notifies the listener when the query finishes"
public class MainActivity extends AppCompatActivity implements SkuDetailsResponseListener {
Which gives:
#Override
public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetailsList) {
}
However, this is a problem because it doesn't include the listener specified in the documentation, ie.
billingClient.querySkuDetailsAsync(params.build(),
new SkuDetailsResponseListener() {
#Override
public void onSkuDetailsResponse(BillingResult billingResult,
List<SkuDetails> skuDetailsList) {
// Process the result.
}
});
When including the BillingClient line and the listener there is obviously a resolve symbol error as it is outside any method, so how do you work around this?
Additionally, would you then place this block inside onCreate()?
List<String> skuList = new ArrayList<> ();
skuList.add("coins5");
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(SkuType.INAPP);
As documented in Billing API documentation, you also need to implement the BillingClientStateListener as well as PurchaseUpdateListener. https://developer.android.com/google/play/billing/integrate
The following code is a working example in Billing API 3.0 with Android Version Targeted SDK 28. The code is defined in a Singleton class so it can be used from multiple activities with one instance of BillingClient.
public class ApplicationBillingClient
{
static ApplicationBillingClient applicationBillingClient= null;
private static BillingClient billingClient;
private ApplicationBillingClient() {}
private static boolean isInitialized()
{
return applicationBillingClient != null && billingClient != null;
}
private static void initialize(Context applicationContext)
{
try
{
if(applicationContext != null)
{
applicationBillingClient = new ApplicationBillingClient();
BillingClient.Builder builder= BillingClient.newBuilder(applicationContext);
builder.setListener(new PurchaseActivityListener());
builder.enablePendingPurchases();
billingClient = builder.build();
}
LogUtil.info("Initializing the Billing Client");
}
catch (Exception ex)
{
LogUtil.error("Error while initializing billing client", ex);
}
}
public static ApplicationBillingClient getInstance(Context applicationContext)
{
if(isInitialized() == false)
{
initialize(applicationContext);
}
return applicationBillingClient;
}
public void startConnection()
{
billingClient.startConnection(new StateListener());
}
public boolean isReady()
{
return billingClient.isReady();
}
public void getMonthlySubscription()
{
try
{
if(billingClient.isReady())
{
SkuDetailsParams.Builder skuBuilder = SkuDetailsParams.newBuilder();
skuBuilder.setType(BillingClient.SkuType.SUBS);
skuBuilder.setSkusList(Arrays.asList(new String[]{MONTHLY_BILLING_SUBSCRIPTION_SKU}));
SkuDetailsParams params = skuBuilder.build();
billingClient.querySkuDetailsAsync(params, new SkuDetailsListener());
}
}
catch (Exception ex)
{
LogUtil.error("Error while querying async SKU for Monthly Subscription", ex);
}
}
}
//In your activity
ApplicationBillingClient appBillingClient =
ApplicationBillingClient.getInstance(applicationContext);
if (appBillingClient.isReady() == false)
{
appBillingClient.startConnection();
}
else
{
appBillingClient.getMonthlySubscription();
}
Welcome to stackoverflow !
Two solutions :
Use the the listener specified in the documentation and don't implements it on the class declaration.
Or keep the implements and instead billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() { ....
just use : billingClient.querySkuDetailsAsync(params.build(), this);

WebViewPool, Last html page show before new url when reuse WebView from WebViewPool

There is a WebViewPool,when Activity/Fragment is destoryed,webview will be reset and add to the WebViewPool.
The following is the code of WebViewPool:
public class WebViewPool {
private static volatile WebViewPool sINSTANCE;
private int mMaxSize;
private List<WebView> mAvailableList;
private List<WebView> mInUsedList;
private IWebViewPoolFactory mFactory;
private WebViewPool() {
}
public static WebViewPool getInstance() {
if (sINSTANCE == null) {
synchronized (WebViewPool.class) {
if (sINSTANCE == null) {
sINSTANCE = new WebViewPool();
}
}
}
return sINSTANCE;
}
public void init(IWebViewPoolFactory factory,boolean lazy) {
init(2, factory,lazy);
}
public void init(int maxSize, IWebViewPoolFactory factory,boolean lazy) {
mMaxSize = maxSize;
mFactory = factory;
mAvailableList = new ArrayList<>(maxSize);
mInUsedList = new ArrayList<>(maxSize);
if (!lazy) {
create();
}
}
private synchronized void create() {
if (mFactory == null) {
return;
}
for (int i = 0; i < mMaxSize; i++) {
WebView webView = mFactory.create(new MutableContextWrapper(APP.getApplicationContext()));
mAvailableList.add(webView);
}
}
/**
* get webview form pool
* #param context
* #return
*/
public synchronized WebView getWebView(Context context) {
if(!(context instanceof Activity)){
throw new IllegalStateException("Context must be Activity");
}
WebView webView = null;
if (mAvailableList.size() > 0) {
webView = mAvailableList.remove(0);
} else {
if (mFactory != null) {
webView = mFactory.create(new MutableContextWrapper(APP.getApplicationContext()));
}
}
if (webView != null) {
((MutableContextWrapper) webView.getContext()).setBaseContext(context);
mInUsedList.add(webView);
}
return webView;
}
/**
* reset/destroy webview when activity/fragemnt is destroyed
* #param webView
*/
public synchronized void restWebView(WebView webView) {
if (webView == null || mFactory == null) {
return;
}
mFactory.reset(webView);
((MutableContextWrapper) webView.getContext()).setBaseContext(APP.getApplicationContext());
if (mInUsedList.contains(webView)) {
mInUsedList.remove(webView);
if (mAvailableList.size() < mMaxSize) {
mAvailableList.add(webView);
} else {
mFactory.destroy(webView);
}
} else {
mFactory.destroy(webView);
}
}
}
the following is some code of reset function:
public void reset(WebView webView) {
if(webView==null){
return;
}
ViewParent viewParent = webView.getParent();
if (viewParent!=null) {
((ViewGroup)viewParent).removeView(webView);
}
webView.stopLoading();
webView.clearCache(false);
webView.loadUrl("about:blank");
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
webView.clearHistory();
}
}, 1000);
}
But when reuse the webview,last html page show first before new url sometimes.It doesn't happened everytime. I searched in Google, but not work.Does anyone know the reason? Thank you!
This problem is solved finally! The reason is that add the reseted WebView to available list while about:blank is not loaded so that clearHistory() doesn't work.
So, reset the webview but do not add to available list when activity/fragment is destroyed, call clearHistory() at onPageFinished() when url is about:blank:
#Override
public void onPageFinish(String url, boolean success) {
if("about:blank".equals(url)){
webView.clearHistory();
//then add the webview to available list;
}
}

Android MediaPlayer dispose of video correctly

I am trying to create a Xamarin Forms application that displays a full screen video for the launch page. Once loading is complete the launch page takes you to the home screen. The home screen displays a series of videos in a carousel.
On Android the carousel videos work fine by themselves but when I add in the launch screen video it displays over the carousel ones. Currently I have a View called VideoView in my App that has a BindableProperty for the video source.
The rendering is done platform specifically in a custom renderer that is below. It uses a native VideoView and MediaPlayer control for Android. I have tried the various dispose and and release functions in the OnDisappearing function in the launch screen, but none of them seem to release the video.
[assembly: ExportRenderer(typeof(App.Renderers.VideoView),
typeof(VideoViewRenderer))]
namespace App.Droid.Renderers
{
public class VideoViewRenderer :
ViewRenderer<App.Renderers.VideoView, VideoView>, ISurfaceHolderCallback
{
private VideoView videoview;
private MediaPlayer player;
public void SurfaceChanged(ISurfaceHolder holder, global::Android.Graphics.Format format, int width, int height)
{
}
public void SurfaceDestroyed(ISurfaceHolder holder)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<App.Renderers.VideoView> e)
{
base.OnElementChanged(e);
e.NewElement.StopAction = () =>
{
player.Pause();
};
e.NewElement.StartAction = () =>
{
player.Start();
};
e.NewElement.DisposeAction = () =>
{
Control.StopPlayback();
Control.Dispose();
player.Stop();
player.Reset();
player.Release();
};
if (Control == null)
{
videoview = new VideoView(Context);
base.SetNativeControl(videoview);
Control.Holder.AddCallback(this);
player = new MediaPlayer();
play(e.NewElement.FileSource);
}
}
void play(string fullPath)
{
AssetFileDescriptor afd = Forms.Context.Assets.OpenFd(fullPath);
if (afd != null)
{
try
{
player.SetDataSource(afd.FileDescriptor, afd.StartOffset, afd.Length);
player.Prepare();
player.Looping = true;
Control.Layout(0, 200, player.VideoHeight, player.VideoWidth);
player.SetVideoScalingMode(VideoScalingMode.ScaleToFit);
}
catch
{
}
}
}
public void SurfaceCreated(ISurfaceHolder holder)
{
player.SetDisplay(holder);
}
}
}
The VideoView class extends View and is as follows:
public class VideoView : View
{
public Action StopAction;
public Action StartAction;
public Action DisposeAction;
public VideoView()
{
FileSource = string.Empty;
}
public static readonly BindableProperty FileSourceProperty =
BindableProperty.Create<VideoView, string>(
p => p.FileSource, string.Empty);
public string FileSource
{
get { return (string)GetValue(FileSourceProperty); }
set { SetValue(FileSourceProperty, value); }
}
public void Stop()
{
if (StopAction != null)
StopAction();
}
public void Dispose()
{
if (DisposeAction != null)
DisposeAction();
}
public void Start()
{
if (StartAction != null)
StartAction();
}
}
And finally usage of the view is as follows:
<controls:VideoView Grid.Row="0" Grid.Column="0" x:Name="Video1" FileSource="big_buck_bunny.mp4" Margin="0,10,0,40" />

Unity3d AdMob rewarded ad not showing

I am doing some simple app with two buttons... first button is sending request for Awarded (test) ad and then second shows the ad.
Here is my code:
using GoogleMobileAds.Api;
using UnityEngine;
using System;
public class adManager : MonoBehaviour
{
RewardBasedVideoAd rewardedAd;
public void Start()
{
rewardedAd = RewardBasedVideoAd.Instance;
requestVideo();
}
public void requestVideo()
{
Debug.Log("Video Requested!");
string adID = "My ad ID";
AdRequest request = new AdRequest.Builder()
.AddTestDevice(AdRequest.TestDeviceSimulator) // Simulator.
.AddTestDevice("BD6E7C35B6F8FA70") // My test device.
.Build();
rewardedAd.LoadAd(request, adID);
}
public void showBannerAd()
{
if (rewardedAd.IsLoaded())
{
Debug.Log("AdAvailible!");
rewardedAd.OnAdRewarded += HandleOnAdRewarded;
rewardedAd.Show();
}
else
{
Debug.Log("AdNotAvailible!");
}
}
public void HandleOnAdRewarded(object sender, EventArgs args)
{
Debug.Log("You are rewarded!");
}
public event EventHandler<Reward> OnAdRewarded;
}
Is something wrong with my code or something else?
I tried interstitial and banner ad and they WORKED.
Thanks for help.

Xamarin.Forms ViewRenderer audio doesnt stop on homepage/backbutton

I am new so excuse me if I dont ask a question right or post enough information.
I am new to creating mobile applications and i am using Xamarin.Forms to create a custom view. with this view I am using an Android ViewRenderer to play audio/video with built in android MediaPlayer/VideoView.
pretty much the exact same thing as the android renderer posted and accepted as the answer for Renderer I copied and is working
My issue is when the video starts and you click the homepage/back button the audio continues playing for a few seconds and then stops. I want to audio to stop immediately.
Methods I have tried:
In my ViewRenderer I have attempted to override SurfaceDestroyed to call player.stop(). This has not worked, no errors or anything just audio continues like this code doesnt exist. Audio stops after about 3-5 seconds.
In the ViewRenderer I have attempted to use the Control.SystemUiVisibilityChange event to call player.stop(). No errors or anything. Audio continues for 3-5 seconds.
I am unable to pass the player instance to the main activity onPause() method as I am to new to Xamarin.Forms and android ViewRenderers to understand how to. Possibly calling this player.stop() on the onPause() method will work but I cant find how to do this. Can anyone assist? I have searched many forums for weeks and have finally given up to post a question.
For back button, you simply need to override OnBackButtonPressed of your current Xamarin.Forms' page:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
protected override bool OnBackButtonPressed()
{
//stop the videoview
videoview.Stop();
return base.OnBackButtonPressed();
}
...
}
For home button, I referred to this thread and made a Xamarin version of HomeWatcher out of Jack's answer:
public interface IOnHomePressedListener
{
void OnHomePressed();
void OnHomeLongPressed();
}
public class HomeWatcher
{
static readonly String TAG = "hg";
private Context mContext;
private IntentFilter mFilter;
private IOnHomePressedListener mListener;
private InnerRecevier mRecevier;
public HomeWatcher(Context context)
{
mContext = context;
mFilter = new IntentFilter(Intent.ActionCloseSystemDialogs);
}
public void SetOnHomePressedListener(IOnHomePressedListener listener)
{
mListener = listener;
mRecevier = new InnerRecevier(mListener);
}
public void StartWatch()
{
if (mRecevier != null)
{
mContext.RegisterReceiver(mRecevier, mFilter);
}
}
public void StopWatch()
{
if (mRecevier != null)
{
mContext.UnregisterReceiver(mRecevier);
}
}
private class InnerRecevier : BroadcastReceiver
{
readonly String SYSTEM_DIALOG_REASON_KEY = "reason";
readonly String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
readonly String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
readonly String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
IOnHomePressedListener _listener;
public InnerRecevier(IOnHomePressedListener listener)
{
_listener = listener;
}
public override void OnReceive(Context context, Intent intent)
{
String action = intent.Action;
if (action.Equals(Intent.ActionCloseSystemDialogs))
{
String reason = intent.GetStringExtra(SYSTEM_DIALOG_REASON_KEY);
if (reason != null)
{
//Log.e(TAG, "action:" + action + ",reason:" + reason);
if (_listener != null)
{
if (reason.Equals(SYSTEM_DIALOG_REASON_HOME_KEY))
{
_listener.OnHomePressed();
}
else if (reason.Equals(SYSTEM_DIALOG_REASON_RECENT_APPS))
{
_listener.OnHomeLongPressed();
}
}
}
}
}
}
}
And use it in the VideoViewRenderer ( StartWatch() when video start play, StopWatch() when the videoview is cleaned):
public class VideoViewRenderer : ViewRenderer<VideoView, Android.Widget.VideoView>, ISurfaceHolderCallback,IOnHomePressedListener
{
...
private MediaPlayer _player;
private HomeWatcher _homeWatcher;
public VideoViewRenderer(Context context) : base(context)
{
_context = context;
_homeWatcher = new HomeWatcher(context);
_homeWatcher.SetOnHomePressedListener(this);
}
protected override void OnElementChanged(ElementChangedEventArgs<CustomVideoViewDemo.VideoView> e)
{
base.OnElementChanged(e);
e.NewElement.CleanAction = new Action(() =>
{
#region Clean video player action (player no more used)
if (_player == null)
return;
//stop watch home button
_homeWatcher.StopWatch();
_player.Release();
#endregion
});
e.NewElement.PlayAction = new Action(() =>
{
#region Play video if it was stopped
if (_player == null)
return;
//start watch home button
_homeWatcher.StartWatch();
if (!_player.IsPlaying)
{
_player.Start();
}
#endregion
});
...
}
}

Categories

Resources