Monotouch - iPhone load Admob interstitials statically - ios

I am trying to load Admob interstitial ads using a static class, so I can show it in a convient time.
I have created a method for loading the Interstitial:
public static void GetInterstitial()
{
interstitial = new GADInterstitial ();
interstitial.AdUnitID = "my_ad_unit_id";
interstitial.LoadRequest (GADRequest.Request);
interstitial.DidReceiveAd += (sender, args) => {
didInterstitialLoad = true;
} ;
interstitial.DidFailToReceiveAd += (object sender, GADInterstitialDidFailToReceiveAdWithErrorEventArgs e) => {
didLoadInterFailed = true;
};
interstitial.DidDismissScreen += (sender, e) => {
//TODO - Handle interstitial dismiss ();
};
}
and then in my ViewController:
if (isInterstitialLoaded) {
interstitial.PresentFromRootViewController(this.NavigationController);
}
This works for the first time, but after that I am getting the following error in interstitial.DidFailToReceiveAd:
Will not send request because interstitial object has been used
What can be done to fix it?

I got this error when I tried to interstitial.PresentFromRootViewController(this.NavigationController);
The solution was to recreate the entire interstitial ad after dismissing the last one. So inside your DidDismissScreen handler, just create it again:
didInterstitialLoad = false;
interstitial = new GADInterstitial ();
interstitial.AdUnitID = "my_ad_unit_id";
interstitial.LoadRequest (GADRequest.Request);
interstitial.DidReceiveAd += (sender, args) => {
didInterstitialLoad = true;
};
HIH :)

Related

xamarin push notification ios Page navigation not working when push notification click

I have azure push notification in Xamarin forms. when push notification received I need to open a page in my application. Its working fine in android. In iOS its not working when app is open. When app is in the background its working find in iOS.
This is my App Delegate code
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo,
Action<UIBackgroundFetchResult> completionHandler)
{
try
{
UIApplication.SharedApplication.ApplicationIconBadgeNumber = 0;
NSError error;
NSData notification = NSJsonSerialization.Serialize(userInfo["action"], NSJsonWritingOptions.PrettyPrinted, out error);
string notificationString = NSString.FromData(notification, NSStringEncoding.UTF8).ToString();
var NotificationObj = JsonConvert.DeserializeObject<NotificationData>(notificationString);
NotificationService.pushPageName = NotificationObj.Notification[0].PageName.ToString();
NotificationService.pushAppName = NotificationObj.AppName.ToString();
NotificationService.OpenPages = NotificationObj.Notification[0].OpenPage;
NotificationService.Notification = notificationString;
if (UIApplication.SharedApplication.ApplicationState.Equals(UIApplicationState.Active))
{
//App is in foreground. Act on it.
var application1 = new App(NotificationService.pushPageName, NotificationService.pushAppName, NotificationService.Notification);
LoadApplication(application1);
}
else
{
// var application1 = new App(NotificationService.pushPageName, NotificationService.pushAppName, NotificationService.Notification);
// LoadApplication(application1);
}
}
catch (Exception ex)
{
//LogInfo.ReportErrorInfo(ex.Message, ex.StackTrace, "AppDelegate-DidReceiveRemoteNotification");
}
}
after click push notification I need to open splash screen again.
This is App.cs Code
public App(string openPageName, string openAppName,string notification)
{
ServiceContainer.Resolve<IPushNotificationActionService>()
.ActionTriggered += NotificationActionTriggered;
InitMainPage(openPageName, openAppName, notification);
}
private void InitMainPage(string pageName,string appName,string notification)
{
ServiceContainer.Resolve<IPushNotificationActionService>()
.ActionTriggered += NotificationActionTriggered;
PushNotificationActionService.PushNotificationPageName = pageName ;
PushNotificationActionService.PushNotificationAppName = appName;
PushNotificationActionService.PushNotificationMessage = notification;
MainPage = new NavigationPage(new Splash(pageName));
}
All methods are calling and push notification data also loading correctly in iOS. But not navigating to Spalsh Screen. Anyone have an idea to resolve this please help.
If the app is running, we don't need to reload app with LoadApplication , we can directly send message to set MainPage in App.cs .
iOS
if (UIApplication.SharedApplication.ApplicationState.Equals(UIApplicationState.Active))
{
MessagingCenter.Send<object>(this,"Hi");
}
Forms
public App()
{
InitializeComponent();
MainPage = new MainPage();
MessagingCenter.Subscribe<object>(this, "Hi", (obj) => {
MainPage = new NavigationPage(new Splash(pageName));
});
}

Updating a Button control with an NSTimer in Xamarin

I have created a very basic ios project that has a single button on it with it's title text property set to "Start". I am trying to have this button count down from 15.
I have added the event handler for the button as below.
void StartButton_TouchUpInside (object sender, EventArgs ea) {
_currentCount = 15;
_timer = NSTimer.CreateRepeatingScheduledTimer(TimeSpan.FromSeconds(1), () =>
{
if (_currentCount <= 0) {
StartButton.TitleLabel.Text = "Start";
_timer.Dispose();
} else {
string titleText = (_currentCount--).ToString ();
//Console.WriteLine(titleText);
StartButton.TitleLabel.Text = titleText;
//Console.WriteLine(StartButton.TitleLabel.Text);
//StartButton.SetNeedsDisplay();
}
});
}
So here is the strange thing. The Button changes to 15 just fine then it flashes back to "Start" then 14. Then 13 then "Start" then 12 etc... etc... etc...
Why is it doing this? And how do I prevent it from flashing back to start. Thanks in advance.
Try to use this.InvokeOnMainThread
private int counter = 0;
public override void WillActivate()
{
Console.WriteLine ("{0} will activate", this);
_timer = NSTimer.CreateRepeatingScheduledTimer(1, (timer) =>
{
this.InvokeOnMainThread(()=>{
Console.WriteLine("++++++++ NSTimer Call");
this.AlertTimeLabel.SetText(counter.ToString());
counter++;
});
});
}

Why is Xamarin.Auth throwing authentication error with OAuth1Authenticator and Twitter

I am currently using Xamarin.Auth on a iOS project to handle some user authentication via Facebook and Twitter in my application. The Facebook authentication using OAuth2Authenticator works great and my implementation was based mainly off the docs (http://components.xamarin.com/gettingstarted/xamarin.auth). Twitter however still uses OAuth1 it seems and thus I based my implementation mainly off the answer in this StackOverflow questions (https://stackoverflow.com/a/21982205). Everything works properly and I am able to retrieve user, tweets, etc. but after all the code executes I receive a "Authentication Error" popup on the screen saying "Object reference not set to an instance of an object." there is nothing printed to the console however as is the case with most normal errors I have seen thus far. I can dismiss the popup and everything continues to preform correctly. I believe I have narrowed the problem down to something within the OAuth1Authenticator request as I still receive the error when all of the other handling code has been commented out. Please reference the code below to see what might be the cause of this.
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
signupBtn.TouchUpInside += delegate {
LoginToTwitter(true, this);
};
}
void LoginToTwitter(bool allowCancel, UIViewController _vc)
{
var auth = new OAuth1Authenticator (
consumerKey: "My Consumer Key",
consumerSecret: "My Consumer Secret",
requestTokenUrl: new Uri("https://api.twitter.com/oauth/request_token"),
authorizeUrl: new Uri("https://api.twitter.com/oauth/authorize"),
accessTokenUrl: new Uri("https://api.twitter.com/oauth/access_token"),
callbackUrl: new Uri("My callback url"),
getUsernameAsync: (IDictionary<string, string> accountProperties) => {
string screen_name = "";
if (accountProperties.TryGetValue("screen_name", out screen_name)) {
Console.WriteLine("SN: {0}", screen_name);
Account a = new Account(screen_name, accountProperties);
AuthenticatorCompletedEventArgs e = new AuthenticatorCompletedEventArgs(a);
TwitterCompleted(e, _vc);
}
return null;}
);
auth.AllowCancel = allowCancel;
UIViewController authView = auth.GetUI ();
_vc.PresentViewController (authView, true, null);
}
void TwitterCompleted (AuthenticatorCompletedEventArgs e, UIViewController _vc)
{
var theAccount = e.Account;
var theProperties = theAccount.Properties;
foreach (var item in theProperties) {
Console.WriteLine (item); //debugging
}
InvokeOnMainThread (delegate {
_vc.DismissViewController (true, null);
});
AccountStore.Create ().Save (e.Account, "Twitter");
if (!e.IsAuthenticated) {
Console.WriteLine("Not authorized");
return;
}
theScreenName = e.Account.Properties["screen_name"];
theCount = "2";
IDictionary<string, string> theDict = new Dictionary<string, string>();;
theDict.Add("screen_name", theScreenName);
theDict.Add("count", theCount);
var request = new OAuth1Request("GET", new Uri("https://api.twitter.com/1.1/statuses/user_timeline.json"), theDict, e.Account, false);
request.GetResponseAsync().ContinueWith (t => {
if (t.IsFaulted)
Console.WriteLine("Error: {0}", t.Exception.InnerException.Message);
else if (t.IsCanceled)
Console.WriteLine("Canceled");
else
{
var obj = JsonValue.Parse (t.Result.GetResponseText());
Console.WriteLine("object: {0}", obj); // debugging
}
}, uiScheduler);
return;
}
private readonly TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
instead of returning null in "getUsernameAsync" return Task

MonoTouch, ZXing: Redirect to another ViewController after scan

I'm using the ZXing MobileScanner lib with my xamarin project for iOS (MonoTouch).
I set up the scanning, it is working fine, reading my QRCode and having the correct result.
After reading the QRCode I want to show another ViewController. I set a property in the second Controller with the result from scanning and then want to show the controller.
The second view is not shown on screen. No errors, no feedback, simply not shown.
I guess, the MobileScanner builds up its own View (which can be seen in the source of the lib) and adds this to the NavigationController - and that this causes my Controller to stay "behind". Testing with simply redirecting to my controller on button clicks is working fine.
I also tried to "dispose" the view by calling scanner.Cancel(), but this results in
Warning: Attempt to dismiss from view controller <UINavigationController: 0x19a0c60> while a presentation or dismiss is in progress!
Here is my code, any help on how to display my view is appreciated.
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
scanner = new MobileBarcodeScanner(this.NavigationController);
this.btnScan.TouchUpInside += (sender, e) => {
//Tell our scanner to use the default overlay
scanner.UseCustomOverlay = false;
//We can customize the top and bottom text of the default overlay
scanner.TopText = "Ticket vor den Scanner halten";
scanner.BottomText = "Code wird automatisch eingelesen";
//Start scanning
scanner.Scan ().ContinueWith((t) =>
{
//Our scanning finished callback
if (t.Status == System.Threading.Tasks.TaskStatus.RanToCompletion){
string msg = "";
ZXing.Result result = t.Result;
if (result != null && !string.IsNullOrEmpty (result.Text)) {
scanner.Cancel();
if(this.ticketScreen == null) {
this.ticketScreen = new TicketScreen();
}
this.ticketScreen.ticketUrl = result.Text;
this.NavigationController.PushViewController(this.ticketScreen, true);
} else {
msg = "Code nicht erkannt!";
this.InvokeOnMainThread(() => {
var av = new UIAlertView("Fehler!", msg, null, "OK", null);
av.Show();
});
}
}
});
};
}
I use this.InvokeOnMainThread(() and it works fine in my code.
The solution for you is:
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
scanner = new MobileBarcodeScanner(this.NavigationController);
this.btnScan.TouchUpInside += (sender, e) => {
//Tell our scanner to use the default overlay
scanner.UseCustomOverlay = false;
//We can customize the top and bottom text of the default overlay
scanner.TopText = "Ticket vor den Scanner halten";
scanner.BottomText = "Code wird automatisch eingelesen";
//Start scanning
scanner.Scan ().ContinueWith((t) =>
{
//Our scanning finished callback
if (t.Status == System.Threading.Tasks.TaskStatus.RanToCompletion){
string msg = "";
ZXing.Result result = t.Result;
if (result != null && !string.IsNullOrEmpty (result.Text)) {
scanner.Cancel();
this.InvokeOnMainThread(() =>
{
if(this.ticketScreen == null) {
this.ticketScreen = new TicketScreen();
}
this.ticketScreen.ticketUrl = result.Text;
this.NavigationController.PushViewController(this.ticketScreen, true);
});
} else {
msg = "Code nicht erkannt!";
this.InvokeOnMainThread(() => {
var av = new UIAlertView("Fehler!", msg, null, "OK", null);
av.Show();
});
}
}
});
};
}

Integrate Admob in iOS App which uses monogame

I am trying to do this for a few days, and still cannot make it. And I tried to find some samples but they are all on Android. Did anyone succeed to integrate admob on iOS?
I had some problems with AdMob bindings from monotouch-bindings repository. But then I switched to AlexTouch.GoogleAdMobAds bindings and them works just great. You can find sample of using AlexTouch.GoogleAdMobAds in README on Github. Is is quite simple, but if you'll need some help - feel free to ask more detailed question.
// code for admob "using AlexTouch.GoogleAdMobAds"
UIViewController vc = new UIViewController ();
UIViewController controller = UIApplication.SharedApplication.Windows [0].RootViewController;
var ad = new GADBannerView (GADAdSizeCons.SmartBannerLandscape, new PointF (0, 0))
{
AdUnitID = "ADMOB_ID",
RootViewController = vc
};
ad.Hidden = false;
ad.DidReceiveAd += delegate {
ad.Hidden = false;
ad.Frame = new System.Drawing.RectangleF (0, (int) 0, (int) (ad.Bounds.Width), (int) (ad.Bounds.Height));
Console.WriteLine ("AD Received");
};
ad.DidFailToReceiveAdWithError += delegate(object sender, GADBannerViewDidFailWithErrorEventArgs e) {
ad.Hidden = true;
Console.WriteLine (e.Error);
};
ad.WillPresentScreen += delegate {
Console.WriteLine ("showing new screen");
};
ad.WillLeaveApplication += delegate {
Console.WriteLine ("I will leave application");
};
ad.WillDismissScreen += delegate {
Console.WriteLine ("Dismissing opened screen");
};
ad.UserInteractionEnabled = true;
vc.View.AddSubview(ad);
vc.View.Frame = new System.Drawing.RectangleF(0f, 0f, (int)(ad.Bounds.Width), (int)(ad.Bounds.Height));
controller.View.AddSubview(vc.View);
Task.Factory.StartNew(() => {
while (true)
{
Console.WriteLine("Requesting Ad");
InvokeOnMainThread (delegate {
GADRequest r = new GADRequest();
ad.LoadRequest(r);
});
System.Threading.Thread.Sleep(30000);
}
});

Resources