Unity android banner ad issue after level restart - android

in my game when character die i want to show banner and hide it when player press restart button. Its work fine but after first reset when i want to show banner i get error
NullReferenceException: Object reference not set to an instance of an object
GoogleMobileAdsDemoScript.showBanner ()
so should i request banner after every game restart? it wont be too laggy?
i tried also to attach DontDestroyOnLoad (this); to object which has my ad scripts but it didnt work.
My restart button: Application.LoadLevel (Application.loadedLevel);
AD Script `
private BannerView bannerView;
private InterstitialAd interstitial;
private static string outputMessage = "";
public static string OutputMessage
{
set { outputMessage = value; }
}
private void RequestBanner()
{
#if UNITY_EDITOR
string adUnitId = "unused";
#elif UNITY_ANDROID
string adUnitId = "myai";
#elif UNITY_IPHONE
string adUnitId = "INSERT_IOS_BANNER_AD_UNIT_ID_HERE";
#else
string adUnitId = "unexpected_platform";
#endif
// Create a 320x50 banner at the top of the screen.
bannerView = new BannerView(adUnitId, AdSize.SmartBanner, AdPosition.Top);
// Register for ad events.
bannerView.AdLoaded += HandleAdLoaded;
bannerView.AdFailedToLoad += HandleAdFailedToLoad;
bannerView.AdOpened += HandleAdOpened;
bannerView.AdClosing += HandleAdClosing;
bannerView.AdClosed += HandleAdClosed;
bannerView.AdLeftApplication += HandleAdLeftApplication;
// Load a banner ad.
bannerView.LoadAd(createAdRequest());
}
private void RequestInterstitial()
{
#if UNITY_EDITOR
string adUnitId = "unused";
#elif UNITY_ANDROID
string adUnitId = "INSERT_ANDROID_INTERSTITIAL_AD_UNIT_ID_HERE";
#elif UNITY_IPHONE
string adUnitId = "INSERT_IOS_INTERSTITIAL_AD_UNIT_ID_HERE";
#else
string adUnitId = "unexpected_platform";
#endif
// Create an interstitial.
interstitial = new InterstitialAd(adUnitId);
// Register for ad events.
interstitial.AdLoaded += HandleInterstitialLoaded;
interstitial.AdFailedToLoad += HandleInterstitialFailedToLoad;
interstitial.AdOpened += HandleInterstitialOpened;
interstitial.AdClosing += HandleInterstitialClosing;
interstitial.AdClosed += HandleInterstitialClosed;
interstitial.AdLeftApplication += HandleInterstitialLeftApplication;
GoogleMobileAdsDemoHandler handler = new GoogleMobileAdsDemoHandler();
interstitial.SetInAppPurchaseHandler(handler);
// Load an interstitial ad.
interstitial.LoadAd(createAdRequest());
}
// Returns an ad request with custom ad targeting.
private AdRequest createAdRequest()
{
return new AdRequest.Builder()
.AddTestDevice(AdRequest.TestDeviceSimulator)
.AddTestDevice("0123456789ABCDEF0123456789ABCDEF")
.AddKeyword("game")
.SetGender(Gender.Male)
.SetBirthday(new DateTime(1985, 1, 1))
.TagForChildDirectedTreatment(false)
.AddExtra("color_bg", "9B30FF")
.Build();
}
private void ShowInterstitial()
{
if (interstitial.IsLoaded())
{
interstitial.Show();
}
else
{
print("Interstitial is not ready yet.");
}
}
#region Banner callback handlers
public void HandleAdLoaded(object sender, EventArgs args)
{
print("HandleAdLoaded event received.");
}
public void HandleAdFailedToLoad(object sender, AdFailedToLoadEventArgs args)
{
print("HandleFailedToReceiveAd event received with message: " + args.Message);
}
public void HandleAdOpened(object sender, EventArgs args)
{
print("HandleAdOpened event received");
}
void HandleAdClosing(object sender, EventArgs args)
{
print("HandleAdClosing event received");
}
public void HandleAdClosed(object sender, EventArgs args)
{
print("HandleAdClosed event received");
}
public void HandleAdLeftApplication(object sender, EventArgs args)
{
print("HandleAdLeftApplication event received");
}
#endregion
#region Interstitial callback handlers
public void HandleInterstitialLoaded(object sender, EventArgs args)
{
print("HandleInterstitialLoaded event received.");
}
public void HandleInterstitialFailedToLoad(object sender, AdFailedToLoadEventArgs args)
{
print("HandleInterstitialFailedToLoad event received with message: " + args.Message);
}
public void HandleInterstitialOpened(object sender, EventArgs args)
{
print("HandleInterstitialOpened event received");
}
void HandleInterstitialClosing(object sender, EventArgs args)
{
print("HandleInterstitialClosing event received");
}
public void HandleInterstitialClosed(object sender, EventArgs args)
{
print("HandleInterstitialClosed event received");
}
public void HandleInterstitialLeftApplication(object sender, EventArgs args)
{
print("HandleInterstitialLeftApplication event received");
}
#endregion
`
What should i do?

I recommend you use a plugin of Appodeal.

Related

Game crashes after showing intersitial and rewarded ads

I am using admob for ads. Ads working very well on the Editor but on the phone it doesn't. I have a button in the game that show rewarded ads then load next level. And I am showing interstitial ads at end of the level then load next level. But after loading next level game crashes. I am trying to fix it for days but it keeps happening. I am adding my ad manager script. (unit ids not empty of course)
using System.Collections;
using UnityEngine;
using GoogleMobileAds.Api;
using System;
public class AdManager : MonoBehaviour
{
public static AdManager instance;
private BannerView bannerView;
private RewardedAd rewardedAd;
private InterstitialAd interstitialAd;
#if UNITY_ANDROID
string bannerAdUnitId = " ";
string rewardedAdUnitId = " ";
string interstitialAdUnitId = " ";
#else
string bannerAdUnitId = "unexpected_platform";
string rewardedAdUnitId = "unexpected_platform";
string interstitialAdUnitId = "unexpected_platform";
#endif
void Awake()
{
if(instance != null && instance != this){
Destroy(this.gameObject);
}
else{
instance = this;
DontDestroyOnLoad(this.gameObject);
}
}
private void Start() {
MobileAds.Initialize(initStatus => { });
RequestInterstitialAd();
RequestBannerAd();
RequestRewardedAd();
}
//BANNER
public void RequestBannerAd(){
if (bannerView != null)
bannerView.Destroy();
else{
bannerView = new BannerView(bannerAdUnitId, AdSize.Banner, AdPosition.Bottom);
AdRequest request = new AdRequest.Builder().Build();
bannerView.LoadAd(request);
}
}
//REWARDED
public void RequestRewardedAd(){
if(rewardedAd != null)
rewardedAd.Destroy();
rewardedAd = new RewardedAd(rewardedAdUnitId);
// Called when an ad request failed to show.
rewardedAd.OnAdFailedToShow += HandleRewardedAdFailedToShow;
// Called when the ad is closed.
rewardedAd.OnAdClosed += HandleRewardedAdClosed;
AdRequest request = new AdRequest.Builder().Build();
rewardedAd.LoadAd(request);
}
public void ShowRewardedAd(){
if (rewardedAd.IsLoaded()) {
rewardedAd.Show();
}
else{
StartCoroutine(RewardedNotLoadedFunctionCall());
}
}
IEnumerator RewardedNotLoadedFunctionCall(){
FindObjectOfType<GameManagement>().RewardedAdNotLoaded();
yield return null;
}
public void HandleRewardedAdClosed(object sender, EventArgs args)
{
RequestRewardedAd();
StartCoroutine(AdClosedFunctionCall());
}
IEnumerator AdClosedFunctionCall(){
FindObjectOfType<GameManagement>().AdClosed();
yield return null;
}
public void HandleRewardedAdFailedToShow(object sender, AdErrorEventArgs args)
{
StartCoroutine(RewardedNotLoadedFunctionCall());
}
//interstitial
private void RequestInterstitialAd(){
if(interstitialAd != null)
interstitialAd.Destroy();
interstitialAd = new InterstitialAd(interstitialAdUnitId);
interstitialAd.OnAdClosed += HandleOnAdClosed;
AdRequest request = new AdRequest.Builder().Build();
interstitialAd.LoadAd(request);
}
public void ShowInterstitialAd(){
if (interstitialAd.IsLoaded()) {
interstitialAd.Show();
}
else{
StartCoroutine(AdClosedFunctionCall());
}
}
public void HandleOnAdClosed(object sender, EventArgs args)
{
RequestInterstitialAd();
StartCoroutine(AdClosedFunctionCall());
}
}
logcat
Admob Ad does not run on the same thread as Unity's main thread.
rewardedAd.OnAdClosed += HandleRewardedAdClosed;
Calling Unity's function from Admob's thread will lead to unexpected error.
First, add UnityMainThreadDispatcher to your project. All functions called by Admob's callback need be queued by UnityMainThreadDispatcher to main thread:
public void HandleRewardedAdClosed(object sender, EventArgs args)
{
UnityMainThreadDispatcher.Instance().Enqueue(()=>{
RequestRewardedAd();
StartCoroutine(AdClosedFunctionCall());
});
}
Secondly, you should not use FindObjectOfType(). This is an expensive operation and you might run into NullReferenceException if it fails to find the GameManagement object. And since this exception did not happen on Unity's main thread, the logcat message was cryptic.
You should use Singleton or Observer pattern instead.
Thirdly, you're giving reward to user even if they skip the reward ad. Use rewardedAd.OnUserEarnedReward to make sure user have earned the reward ad.

Should object that creates ads (e.g. Banner, Interstitial) be a singleton?

Following on through the Google AdMob read on implementation for the varying ads:
https://developers.google.com/admob/unity/banner
https://developers.google.com/admob/unity/interstitial
Right now I have a C# Script which implements these ads and I go on to create a game object inside my inspector which has this script.
I believe that this is enough information for me to get a straight forward answer hopefully without any code required and a very general one.
I would like to know whether this object should be initialized only once, ideally in the Main Menu scene and be recycled through the other scenes to manage the reference to these ads.
OR
Delete the existing game object which manages those ads to then have the following scene instantiate a new one, potentially showing a different advert to the one previous.
EDIT:
AdManager Script:
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
using GoogleMobileAds.Api;
public class AdManager : MonoBehaviour
{
public static AdManager instance;
//Test id: ca-app-pub-3940256099942544~3347511713
private string APP_ID = "An id";
private BannerView bannerAD;
private InterstitialAd interstitialAD;
private void Awake()
{
if (instance != null)
{
Destroy(gameObject);
}
else
{
instance = this;
DontDestroyOnLoad(gameObject);
}
}
// Start is called before the first frame update
void Start()
{
//FOR PUBLISHING ONLY
//MobileAds.Initialize(APP_ID);
RequestBannerAD();
RequestInterstitialAD();
}
private void RequestBannerAD()
{
string banner_ID = "ca-app-pub-3940256099942544/6300978111";
bannerAD = new BannerView(banner_ID, AdSize.Banner, AdPosition.Bottom);
// Called when an ad request has successfully loaded.
bannerAD.OnAdLoaded += HandleOnAdLoaded;
// Called when an ad request failed to load.
bannerAD.OnAdFailedToLoad += HandleOnAdFailedToLoad;
// Called when an ad is clicked.
bannerAD.OnAdOpening += HandleOnAdOpened;
// Called when the user returned from the app after an ad click.
bannerAD.OnAdClosed += HandleOnAdClosed;
// Called when the ad click caused the user to leave the application.
bannerAD.OnAdLeavingApplication += HandleOnAdLeavingApplication;
//FOR PRODUCTION
//AdRequest adRequest = new AdRequest.Builder().Build();
//FOR TESTING
AdRequest adRequest = new AdRequest.Builder().AddTestDevice("2077ef9a63d2b398840261c8221a0c9b").Build();
bannerAD.LoadAd(adRequest);
void HandleOnAdLoaded(object sender, EventArgs args)
{
Display_Banner();
}
void HandleOnAdFailedToLoad(object sender, AdFailedToLoadEventArgs args)
{
RequestBannerAD();
}
void HandleOnAdOpened(object sender, EventArgs args)
{
MonoBehaviour.print("HandleAdOpened event received");
}
void HandleOnAdClosed(object sender, EventArgs args)
{
MonoBehaviour.print("HandleAdClosed event received");
}
void HandleOnAdLeavingApplication(object sender, EventArgs args)
{
MonoBehaviour.print("HandleAdLeavingApplication event received");
}
}
public void Display_Banner()
{
bannerAD.Show();
}
public void DestroyBanner()
{
bannerAD.Destroy();
}
private void RequestInterstitialAD()
{
string interstitial_ID = "ca-app-pub-3940256099942544/1033173712";
interstitialAD = new InterstitialAd(interstitial_ID);
// Called when an ad request has successfully loaded.
interstitialAD.OnAdLoaded += HandleOnAdLoaded;
// Called when an ad request failed to load.
interstitialAD.OnAdFailedToLoad += HandleOnAdFailedToLoad;
// Called when an ad is clicked.
interstitialAD.OnAdOpening += HandleOnAdOpened;
// Called when the user returned from the app after an ad click.
interstitialAD.OnAdClosed += HandleOnAdClosed;
// Called when the ad click caused the user to leave the application.
interstitialAD.OnAdLeavingApplication += HandleOnAdLeavingApplication;
//FOR PRODUCTION
//AdRequest adRequest = new AdRequest.Builder().Build();
//FOR TESTING
AdRequest adRequest = new AdRequest.Builder().AddTestDevice("2077ef9a63d2b398840261c8221a0c9b").Build();
interstitialAD.LoadAd(adRequest);
void HandleOnAdLoaded(object sender, EventArgs args)
{
}
void HandleOnAdFailedToLoad(object sender, AdFailedToLoadEventArgs args)
{
}
void HandleOnAdOpened(object sender, EventArgs args)
{
MonoBehaviour.print("HandleAdOpened event received");
}
void HandleOnAdClosed(object sender, EventArgs args)
{
MonoBehaviour.print("HandleAdClosed event received");
}
void HandleOnAdLeavingApplication(object sender, EventArgs args)
{
MonoBehaviour.print("HandleAdLeavingApplication event received");
}
}
public void Display_Interstitial()
{
if (interstitialAD.IsLoaded())
{
interstitialAD.Show();
}
}
public void DestroyInterstitial()
{
interstitialAD.Destroy();
}
}
MenuLoader Script (fragment to interstitial call attached to a UI Button):
public void LoadGameOver()
{
StartCoroutine(WaitAndLoad_GameOver());
}
private IEnumerator WaitAndLoad_GameOver()
{
yield return new WaitForSeconds(gameOver_loadDelay);
FindObjectOfType<AdManager>().Display_Interstitial();
SceneManager.LoadScene("Game Over");
}
EDIT 2 (In response to Eliasar):
06-20 22:07:13.988 6492 6518 E Unity : NullReferenceException: Object reference not set to an instance of an object
06-20 22:07:13.988 6492 6518 E Unity : at AdManager.Display_Banner () [0x00000] in <0b5b8f6032c04370a5fa0fecd73ecd6b>:0
06-20 22:07:13.988 6492 6518 E Unity : at MenuLoader+<WaitAndLoad_Game>d__6.MoveNext () [0x00084] in <0b5b8f6032c04370a5fa0fecd73ecd6b>:0
06-20 22:07:13.988 6492 6518 E Unity : at UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) [0x00027] in <1f017b19aaf9475abf1041405dbaf390>:0
06-20 22:07:13.988 6492 6518 E Unity :
AdManager:
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
using GoogleMobileAds.Api;
public static class AdManager
{
//public static AdManager instance;
//Test id: ca-app-pub-3940256099942544~3347511713
private static string APP_ID = "An id";
private static BannerView bannerAD;
private static InterstitialAd interstitialAD;
//private void Awake()
//{
// if (instance != null)
// {
// Destroy(gameObject);
// }
// else
// {
// instance = this;
// DontDestroyOnLoad(gameObject);
// }
//}
// Start is called before the first frame update
//void Start()
//{
// //FOR PUBLISHING ONLY
// //MobileAds.Initialize(APP_ID);
// RequestBannerAD();
// RequestInterstitialAD();
//}
private static void RequestBannerAD()
{
string banner_ID = "ca-app-pub-3940256099942544/6300978111";
bannerAD = new BannerView(banner_ID, AdSize.Banner, AdPosition.Bottom);
// Called when an ad request has successfully loaded.
bannerAD.OnAdLoaded += HandleOnAdLoaded;
// Called when an ad request failed to load.
bannerAD.OnAdFailedToLoad += HandleOnAdFailedToLoad;
// Called when an ad is clicked.
bannerAD.OnAdOpening += HandleOnAdOpened;
// Called when the user returned from the app after an ad click.
bannerAD.OnAdClosed += HandleOnAdClosed;
// Called when the ad click caused the user to leave the application.
bannerAD.OnAdLeavingApplication += HandleOnAdLeavingApplication;
//FOR PRODUCTION
//AdRequest adRequest = new AdRequest.Builder().Build();
//FOR TESTING
AdRequest adRequest = new AdRequest.Builder().AddTestDevice("2077ef9a63d2b398840261c8221a0c9b").Build();
bannerAD.LoadAd(adRequest);
void HandleOnAdLoaded(object sender, EventArgs args)
{
Display_Banner();
}
void HandleOnAdFailedToLoad(object sender, AdFailedToLoadEventArgs args)
{
RequestBannerAD();
}
void HandleOnAdOpened(object sender, EventArgs args)
{
MonoBehaviour.print("HandleAdOpened event received");
}
void HandleOnAdClosed(object sender, EventArgs args)
{
MonoBehaviour.print("HandleAdClosed event received");
}
void HandleOnAdLeavingApplication(object sender, EventArgs args)
{
MonoBehaviour.print("HandleAdLeavingApplication event received");
}
}
public static void Display_Banner()
{
bannerAD.Show();
}
public static void DestroyBanner()
{
bannerAD.Destroy();
}
private static void RequestInterstitialAD()
{
string interstitial_ID = "ca-app-pub-3940256099942544/1033173712";
interstitialAD = new InterstitialAd(interstitial_ID);
// Called when an ad request has successfully loaded.
interstitialAD.OnAdLoaded += HandleOnAdLoaded;
// Called when an ad request failed to load.
interstitialAD.OnAdFailedToLoad += HandleOnAdFailedToLoad;
// Called when an ad is clicked.
interstitialAD.OnAdOpening += HandleOnAdOpened;
// Called when the user returned from the app after an ad click.
interstitialAD.OnAdClosed += HandleOnAdClosed;
// Called when the ad click caused the user to leave the application.
interstitialAD.OnAdLeavingApplication += HandleOnAdLeavingApplication;
//FOR PRODUCTION
//AdRequest adRequest = new AdRequest.Builder().Build();
//FOR TESTING
AdRequest adRequest = new AdRequest.Builder().AddTestDevice("2077ef9a63d2b398840261c8221a0c9b").Build();
interstitialAD.LoadAd(adRequest);
void HandleOnAdLoaded(object sender, EventArgs args)
{
}
void HandleOnAdFailedToLoad(object sender, AdFailedToLoadEventArgs args)
{
}
void HandleOnAdOpened(object sender, EventArgs args)
{
MonoBehaviour.print("HandleAdOpened event received");
}
void HandleOnAdClosed(object sender, EventArgs args)
{
MonoBehaviour.print("HandleAdClosed event received");
}
void HandleOnAdLeavingApplication(object sender, EventArgs args)
{
MonoBehaviour.print("HandleAdLeavingApplication event received");
}
}
public static void Display_Interstitial()
{
if (interstitialAD.IsLoaded())
{
interstitialAD.Show();
}
}
public static void DestroyInterstitial()
{
interstitialAD.Destroy();
}
}
MenuLoader (fragment edit):
public void LoadGameOver()
{
StartCoroutine(WaitAndLoad_GameOver());
}
private IEnumerator WaitAndLoad_GameOver()
{
yield return new WaitForSeconds(gameOver_loadDelay);
AdManager.Display_Interstitial();
//FindObjectOfType<AdManager>().Display_Interstitial();
SceneManager.LoadScene("Game Over");
AdManager.Display_Banner();
}

Unity: Admob Reward Video Ad Doesn't Call Events

I'm trying to add an Admob reward video ad to my android game made in Unity. The displays fine but when I close the ad, the reward is never given. I've tested the code in the function and the works fine so I think the problem is that is isn't gettting called. Can anyone help me?
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System;
using GoogleMobileAds;
using GoogleMobileAds.Api;
public class textEdit : MonoBehaviour
{
public Image lifeAdUI;
static Image lifeAdUIStat;
public Text adFailUI;
static Text adFailUIStat;
public Button lifeButton;
private static RewardBasedVideoAd videoAd;
static bool adTime = false;
static bool adPlaying = false;
static int pass = 0;
bool watched;
// Use this for initialisation
void Start()
{
Button btn = lifeButton.GetComponent<Button>();
btn.onClick.AddListener(VideoAd);
videoAd = RewardBasedVideoAd.Instance;
videoAd.OnAdFailedToLoad += HandleOnAdFailedToLoad;
videoAd.OnAdOpening += HandleOnAdOpening;
videoAd.OnAdClosed += HandleOnAdClosed;
videoAd.OnAdRewarded += HandleOnAdReward;
videoAd.OnAdLeavingApplication += HandleOnAdLeavingApplication;
videoAd.OnAdLoaded += HandleOnAdLoaded;
videoAd.OnAdStarted += HandleOnAdStarted;
lifeAdUIStat = lifeAdUI;
adFailUIStat = adFailUI;
}
public static void LoadVideoAd()
{
#if UNITY_EDITOR
string adUnitID = "unused";
#elif UNITY_ANDROID
string adUnitID = "ca-app-pub-3025391748532285/9122766975";
#elif UNITY_IPHONE
string adUnitID = "";
#else
string adUnitID = "unexpected_platform";
#endif
videoAd.LoadAd(new AdRequest.Builder().Build(), adUnitID);
pass = pass + 1;
}
void VideoAd()
{
if (videoAd.IsLoaded())
{
videoAd.Show();
}
else
{
//ad not loaded
}
}
//Ad Events
public void HandleOnAdFailedToLoad(object sender, AdFailedToLoadEventArgs args)
{
if (pass < 2)
{
LoadVideoAd();
}
else
{
StartCoroutine(adFailCoro());
}
}
public void HandleOnAdOpening(object ssender, EventArgs args)
{
adPlaying = true;
}
public void HandleOnAdClosed(object sender, EventArgs args)
{
adPlaying = false;
watched = true;
if (watched == true)
{
control controlScript = GameObject.FindGameObjectWithTag("Control").GetComponent<control>();
lifeAdUI.enabled = false;
StartCoroutine(controlScript.ExtraLife());
}
}
public void HandleOnAdReward(object sender, EventArgs args)
{
watched = true;
}
public void HandleOnAdLeavingApplication(object sender, EventArgs args)
{
}
public void HandleOnAdLoaded(object sender, EventArgs args)
{
}
public void HandleOnAdStarted(object sender, EventArgs args)
{
}
}
If you called VideoAd to show your video Ad but due to some unforeseen reason your video is not loaded yet, or having loading failure, so request to load your Ad Again.
void VideoAd()
{
if (videoAd.IsLoaded())
{
videoAd.Show();
}
else
{
LoadVideoAd();
}
}
Request to load new Video Ad when your Ad is closed by user.
public void HandleOnAdClosed(object sender, EventArgs args)
{
adPlaying = false;
watched = true;
if (watched == true) //what is the need of this condition, it always true
{
control controlScript = GameObject.FindGameObjectWithTag("Control").GetComponent<control>();
lifeAdUI.enabled = false;
StartCoroutine(controlScript.ExtraLife());
LoadVideoAd();
}
}
Init Admob Unity Plugin
using admob;
Admob.Instance().initAdmob("admob banner id", "admob interstitial id");//admob id with format ca-app-pub-279xxxxxxxx/xxxxxxxx
//Admob.Instance().initAdmob("ca-app-pub-3940256099942544/2934735716", "ca-app-pub-3940256099942544/4411468910");
Here is the minimal code to create an admob video.
Admob.Instance().loadRewardedVideo("ca-app-pub-3940256099942544/1712485313");
Video need to be explicitly shown at an appropriate stopping point in your app, check that the video is ready before showing it:
if (Admob.Instance().isRewardedVideoReady()) {
Admob.Instance().showRewardedVideo();
}
handle reward
Admob.Instance().videoEventHandler += onVideoEvent;
void onVideoEvent(string eventName, string msg)
{
Debug.Log("handler onAdmobEvent---" + eventName + " " + msg);
if (eventName == AdmobEvent.onRewarded)
{
//msg is the reward count.you can handle it now
}
}
ref admob plugin

Social Network Plugin doesn't login

I use SocialNetwork Plugin for Android from Prime31 (here) in my project for facebook.
If I use demo scene - all work good. If I in single window create 3 buttons (init, login, share) it also work good. But if I use FacebookAndroid.init() in first update (or Awake or Start) and login in some window of my game - after login to FB window session isn't valid and I Can't share anything.
List of my Facebook Controller:
public class FacebookController : MonoBehaviour
{
public static FacebookController instance;
void Awake ()
{
instance = this;
}
private bool isFirst = true;
void Update ()
{
if (isFirst)
{
isFirst = false;
#if UNITY_ANDROID
FacebookAndroid.init();
#endif
}
}
public void Login()
{
#if UNITY_ANDROID
var permissions = new string[] { "publish_actions", "publish_stream" };
FacebookAndroid.setSessionLoginBehavior(FacebookSessionLoginBehavior.SUPPRESS_SSO);
FacebookAndroid.loginWithPublishPermissions(permissions);
#endif
}
public void Logoff()
{
#if UNITY_ANDROID
FacebookAndroid.logout();
#endif
}
public bool IsLogged()
{
#if UNITY_ANDROID
FacebookAndroid.isSessionValid();
#endif
return false;
}
public void Share(string name, string message)
{
#if UNITY_ANDROID
if (FacebookAndroid.isSessionValid())
{
var parameters = new Dictionary<string, object>
{
{ "link", "http://prime31.com" },
{ "name", name },
{ "picture", "http://prime31.com/assets/images/prime31logo.png" },
{ "caption", message }
};
FacebookAndroid.showFacebookShareDialog(parameters);
}
#endif
}
}

Are there undocumented invalid states for Android MediaPlayer.getCurrentPosition() and MediaPlayer.getDuration()?

I have an instance of the Androids MediaPlayer, where I try to keep track of the current state as good as possible.
As I use Xamarin (monodroid), I cannot use the wrapper, written by danielhawkes (https://gist.github.com/danielhawkes/1029568), but have to write my own. I ended up with that one:
namespace MyApp.UI.Droid
{
public delegate void InternalStatusChangedEventHandler(object sender, MediaPlayerInternalStatusEventArgs e);
public class MediaPlayerWrapper : Android.Media.MediaPlayer
{
public event InternalStatusChangedEventHandler InternalStatusChanged;
private MediaPlayerStatus internalStatus;
public MediaPlayerStatus InternalStatus {
get { return internalStatus; }
set {
internalStatus = value;
if (InternalStatusChanged != null)
InternalStatusChanged(this, new MediaPlayerInternalStatusEventArgs(internalStatus));
}
}
public MediaPlayerWrapper() : base() {
InternalStatus = MediaPlayerStatus.IDLE;
Prepared += (object sender, EventArgs e) => InternalStatus = MediaPlayerStatus.PREPARED;
Error += (object sender, ErrorEventArgs e) => InternalStatus = MediaPlayerStatus.ERROR;
Completion += (object sender, EventArgs e) => {
if (!Looping)
InternalStatus = MediaPlayerStatus.PLAYBACK_COMPLETED;
};
}
public override void Reset ()
{
InternalStatus = MediaPlayerStatus.IDLE;
base.Reset ();
}
public override void SetDataSource (Android.Content.Context context, Android.Net.Uri uri)
{
InternalStatus = MediaPlayerStatus.INITIALIZED;
base.SetDataSource (context, uri);
}
public override void SetDataSource (Android.Content.Context context, Android.Net.Uri uri, System.Collections.Generic.IDictionary<string, string> headers)
{
InternalStatus = MediaPlayerStatus.INITIALIZED;
base.SetDataSource (context, uri, headers);
}
public override void SetDataSource (Java.IO.FileDescriptor fd)
{
InternalStatus = MediaPlayerStatus.INITIALIZED;
base.SetDataSource (fd);
}
public override void SetDataSource (Java.IO.FileDescriptor fd, long offset, long length)
{
InternalStatus = MediaPlayerStatus.INITIALIZED;
base.SetDataSource (fd, offset, length);
}
public override void SetDataSource (string path)
{
InternalStatus = MediaPlayerStatus.INITIALIZED;
base.SetDataSource (path);
}
public override void PrepareAsync ()
{
InternalStatus = MediaPlayerStatus.PREPARING;
base.PrepareAsync ();
}
public override void Prepare ()
{
InternalStatus = MediaPlayerStatus.PREPARED;
base.Prepare ();
}
public override void Start ()
{
InternalStatus = MediaPlayerStatus.STARTED;
base.Start ();
}
public override void Pause ()
{
InternalStatus = MediaPlayerStatus.PAUSED;
base.Pause ();
}
public override void Stop ()
{
InternalStatus = MediaPlayerStatus.STOPPED;
base.Stop ();
}
public override void Release ()
{
InternalStatus = MediaPlayerStatus.END;
base.Release ();
}
}
public class MediaPlayerInternalStatusEventArgs : EventArgs
{
public MediaPlayerInternalStatusEventArgs(MediaPlayerStatus status)
{
this.Status = status;
}
public MediaPlayerStatus Status { get; private set; }
}
}
After a while of testing and re-reading the docs (http://developer.android.com/reference/android/media/MediaPlayer.html#Valid_and_Invalid_States) I stumbled on one thing:
The method MediaPlayer.getCurrentPosition() is reported to be invalid to call in the Error state of the instance. But in my example, it also triggers the OnError handler, if the player is in the Idle state.
Same to the method MediaPlayer.getDuration(). It is reported to be invalid to call in the Idle, Initialized, Error state of the instance. But in my example, it also triggers the OnError handler, if the player is in the PREPARING state.
Is the documentation wrong here? Or am I missing something in my wrapper? Is this something special for MonoDroid maybe?
Check instance.isPlaying() or isPaused() before a call to getCurrentPosition().
Only call getDuration() once in onPrepared() and store the value.
As mentioned in other threads, MediaPlayer state handling be a beehutch.
There is no getState() method.
Not only that, you can't add codecs to it. Also, the network streaming be dain bramaged (esp. for youtube).
It was prematurely released and like much of Android, now it be stuck with its bad self.
In my next project I will use any other extensible sensible opensource player like VLC.
The Preparing state is not mentioned as invalid state for any of the method calls, but it's a generally unstable and undefined state to call anything in.
As stated a bit earlier in the documentation:
It is important to note that the Preparing state is a transient state, and the behavior of calling any method with side effect while a MediaPlayer object is in the Preparing state is undefined.

Categories

Resources