Showing Google Admob Interstitial ad in Xamarin Forms without delay - c#

I'm working on Xamarin forms project and i have implemented Interstitial ad on all three platforms (Google admob doesn't support UWP). Ads are working fine but they are showing with a delay of 4 to 5 seconds. All i want is to finish that delay so they can show immediately.
PCL class.
public interface IAdmobInterstitial
{
void Show(string adUnit);
}
Droid Code.
public class InterstitialAdListener : AdListener
{
readonly InterstitialAd _ad;
public InterstitialAdListener(InterstitialAd ad)
{
_ad = ad;
}
public override void OnAdLoaded()
{
base.OnAdLoaded();
if (_ad.IsLoaded)
_ad.Show();
}
}
public class AdmobInterstitial : Controls.IAdmobInterstitial
{
InterstitialAd _ad;
public void Show(string adUnit)
{
var context = Android.App.Application.Context;
_ad = new InterstitialAd(context);
_ad.AdUnitId = adUnit;
var intlistener = new InterstitialAdListener(_ad);
intlistener.OnAdLoaded();
_ad.AdListener = intlistener;
var requestbuilder = new AdRequest.Builder().AddTestDevice("302E90D530B2193F59FDD7F22A11B45A");
_ad.LoadAd(requestbuilder.Build());
}
}
iOS Code.
public class AdmobInterstitial : IAdmobInterstitial
{
Interstitial _adInterstitial;
public void Show(string adUnit)
{
_adInterstitial = new Interstitial(adUnit);
var request = Request.GetDefaultRequest();
_adInterstitial.AdReceived += (sender, args) =>
{
if (_adInterstitial.IsReady)
{
var window = UIApplication.SharedApplication.KeyWindow;
var vc = window.RootViewController;
while (vc.PresentedViewController != null)
{
vc = vc.PresentedViewController;
}
_adInterstitial.PresentFromRootViewController(vc);
}
};
_adInterstitial.LoadRequest(request);
}
}
Calling interstitial ad on PCL page.
DependencyService.Get<IAdmobInterstitial>().Show("(id will come here)");
Navigation.PushAsync(new Page());
Ad is showing perfectly but with a delay. I want to show the ad first and then the page.

So i just solved this.
Here is the code.
PCL Class. Add another function to your interface.
public interface IAdmobInterstitial
{
void Show(string adUnit);
void Give();
}
Droid code. Put _ad.Show() in the new function.
public class InterstitialAdListener : AdListener
{
readonly InterstitialAd _ad;
public InterstitialAdListener(InterstitialAd ad)
{
_ad = ad;
}
public override void OnAdLoaded()
{
base.OnAdLoaded();
//if (_ad.IsLoaded)
// _ad.Show();
}
}
public class AdmobInterstitial : Controls.IAdmobInterstitial
{
InterstitialAd _ad;
public void Show(string adUnit)
{
var context = Android.App.Application.Context;
_ad = new InterstitialAd(context);
_ad.AdUnitId = adUnit;
var intlistener = new InterstitialAdListener(_ad);
intlistener.OnAdLoaded();
_ad.AdListener = intlistener;
var requestbuilder = new AdRequest.Builder().AddTestDevice("302E90D530B2193F59FDD7F22A11B45A");
_ad.LoadAd(requestbuilder.Build());
}
public void Give()
{
if (_ad.IsLoaded)
_ad.Show();
}
}
Now, call the function Show() in the constructor of your MainPage in PCL and call the function Give() when you press the button for the next page.
public MainPage()
{
InitializeComponent();
DependencyService.Get<IAdmobInterstitial>().Show("ca-app-pub-3940256099942544/1033173712");
}
private void button_Clicked(object sender, EventArgs e)
{
DependencyService.Get<IAdmobInterstitial>().Give();
Navigation.PushAsync(new Percentage());
}
This is only for Android. Same goes for iOS as well.
I hope it helps the other programmers. :)

Related

Xamarin Forms Global variable updates slower than code

I have a problem. I am using the following code in my App.xaml.cs:
public static int agentId;
public static List<Agent> agents;
public App()
{
InitializeComponent();
loadingAgents += onLoadingAgents;
LoadAgentList();
MainPage = new MainPage();
}
private event EventHandler loadingAgents = delegate { };
private async void onLoadingAgents(object sender, EventArgs args)
{
Agents = await RestService.GetAgents();
}
private void LoadAgentList()
{
loadingAgents(this, EventArgs.Empty);
}
public static int AgentId
{
get
{
return agentId;
}
set
{
agentId = value;
}
}
public static List<Agent> Agents
{
get
{
if (agents == null)
{
agents = new List<Agent>();
}
return agents;
}
set
{
agents = value;
AgentId = Agents.Min(x => x.Id);
}
}
Now what this simply should do is the following:
On startup, it collects all the Agents from a webcall and puts it in a List<Agent> Agents
Once the List<Agent> Agents is set, it sets the AgentId to the minimum Id of the Agents list
The problem is that in the ViewModel of the MainPage I use those variables that are supposed to be set, but the code of the ViewModel is faster than the code that needs to update the variables.
How can I wait for the variables to finish before hitting this line: MainPage = new MainPage();?
First i don't think it is necessary to use private event EventHandler loadingAgents.Then you get Agents is an asynchronous operation,so MainPage = new MainPage(); has been executed when the method is called(at this time, the Agents may be null).And in general we don't call asynchronous tasks in the constructor to get the data,you could do it in the OnStart() method.
You could try to change like below :
public App()
{
InitializeComponent();
}
protected async override void OnStart()
{
Agents = await RestService.GetAgents();
MainPage = new MainPage();
}

WPF application doesn't run (or appear) if api not available

I have a simple WPF application that doesn't appear if api is not available. How do I handle it so screen at least shows up saying no api is available?
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
GetWeather();
}
private void GetWeather()
{
using (var client = new WebClient())
{
var content = client.DownloadString($"http://localhost:50054/WeatherForecast");
var data = JsonConvert.DeserializeObject<IEnumerable<WeatherForecast>>(content);
message4Label.Text = data.ToList()[0].Summary;
}
}
}
You must move the call from the constructor of the form because if there's an exception it will close the form without any message. Also, protecting the function with a try/catch is always a good idea.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
if(!GetWeather())
//Present a message to the user
}
private bool GetWeather()
{
try
{
using (var client = new WebClient())
{
var content = client.DownloadString($"http://localhost:50054/WeatherForecast");
var data = JsonConvert.DeserializeObject<IEnumerable<WeatherForecast>>(content);
message4Label.Text = data.ToList()[0].Summary;
}
return true;
}
catch{ return false; }
}
}

java.lang.IllegalArgumentException: No such service ComponentInfo{/com.SampleApp.AttendanceApp.ServiceClass}

I am using Xamarin Android to build an app which should allow the app to keep sending a driver's location every 15 minutes so that I can keep track of his movement. I used JobScheduler to get this done. My project is very simple now and only contains the following 3 files:
MainActivity.cs
AttendancePage.cs (Content page, interact with UI button to start the service)
ServiceClass.cs
Methods in Main Activity.cs
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
scheduler = (JobScheduler)GetSystemService(JobSchedulerService);
LoadApplication(new App()); //This line will then jump to AttendancePage.cs
}
public void ScheduleJob()
{
ComponentName componentName = new ComponentName(this, Java.Lang.Class.FromType(typeof(ServiceClass)));
JobInfo info = new JobInfo.Builder(123, componentName)
.SetPersisted(true)
.SetPeriodic(60000)
.Build();
int resultCode = scheduler.Schedule(info); //The error show when hit this line.
if (resultCode == JobScheduler.ResultSuccess)
{
Log.Info("Message", "Job Schedule!");
}
else
{
Log.Info("Message", "Job shceduling failed");
}
}
public void CancelJob()
{
scheduler.Cancel(123);
}
AttendancePage.cs
public partial class AttendancePage : ContentPage
{
MainActivity main = new MainActivity();
public AttendancePage()
{
InitializeComponent();
Title = "Attendance App";
}
//Button OnClickEvent
async void ScheduleJob(object s, EventArgs e)
{
main.ScheduleJob();
}
//Button OnClickEvent
async void CancelJob(object s, EventArgs e)
{
main.CancelJob();
}
}
ServiceClass.cs
[Service(Name = "com.SampleApp.AttendanceApp.ServiceClass", Permission = "android.permission.BIND_JOB_SERVICE")]
public class ServiceClass : JobService
{
public ServiceClass()
{
}
public override bool OnStartJob(JobParameters jobParamsOnStart)
{
doBackgroundWork(jobParamsOnStart);
return true;
}
private void doBackgroundWork(JobParameters jobParam)
{
//My code to send driver's location
TestingPage.GetGPS();
JobFinished(jobParam, false);
}
public override bool OnStopJob(JobParameters jobParamsOnStop)
{
return false;
}
}
I have added the service tag inside AndroidManifest.xml as well.
<service android:name=".ServiceClass"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true" />
I have no idea why the error is still there. The error is from the line scheduler.Schedule(JobInfo). Anyone has another possible solution? I am frustrated on solving this. Will the reason be I can't debug on the service but only can straight away run in release mode? Please help.
Froms shared code it works in Xamarin.Android project , however here is a Xamarin.Forms project . It can not work.
In AttendancePage.cs , you create a new MainActivity to invoke the native method ScheduleJob and CancelJob . This will not find the JobScheduler in native ,then it will return null .
No such service ComponentInfo{/com.SampleApp.AttendanceApp.ServiceClass}
If you want to invoke native method , you can have a try with DependencyService in Xamarin Forms .
At least need to create a Interface in Forms to invoke :
public interface IJobSchedulerService
{
//Start JobSchedule
void StartJobSchedule();
//Cancel JobSchedule
void CancelJobSchedule();
}
Then can invoke in Xamarin Forms as follow :
async void ScheduleJob(object s, EventArgs e)
{
DependencyService.Get<IJobSchedulerService>().StartJobSchedule();
}
//Button OnClickEvent
async void CancelJob(object s, EventArgs e)
{
DependencyService.Get<IJobSchedulerService>().CancelJobSchedule();
}
Now you need to implement the IJobSchedulerService in native android .Create the JobSchedulerDependcenyService:
public class JobSchedulerDependcenyService : IJobSchedulerService
{
JobScheduler jobScheduler;
public JobSchedulerDependcenyService()
{
jobScheduler = (JobScheduler)MainActivity.Instance.GetSystemService(Android.Content.Context.JobSchedulerService);
}
public void StartJobSchedule()
{
ComponentName componentName = new ComponentName(MainActivity.Instance, Java.Lang.Class.FromType(typeof(DownloadJob)));
JobInfo jobInfo = new JobInfo.Builder(1, componentName)
.SetOverrideDeadline(0)
.Build();
//var jobScheduler = (JobScheduler)GetSystemService(JobSchedulerService);
var scheduleResult = jobScheduler.Schedule(jobInfo);
if (JobScheduler.ResultSuccess == scheduleResult)
{
var snackBar = Snackbar.Make(MainActivity.Instance.FindViewById(Android.Resource.Id.Content), "jobscheduled_success", Snackbar.LengthShort);
snackBar.Show();
}
else
{
var snackBar = Snackbar.Make(MainActivity.Instance.FindViewById(Android.Resource.Id.Content), "jobscheduled_failure", Snackbar.LengthShort);
snackBar.Show();
}
}
public void CancelJobSchedule()
{
jobScheduler.CancelAll();
}
}
Here you will find the MainActivity.Instance inside it , that's a static instance defined by self in MainActivity.
public static MainActivity Instance { set; get; }
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Instance = this;
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}

Windows Phone 8.1 Currency converter Json

I got a school project. I have to make a currency converter and I got stuck. I found something on the Code Project web site, but I am new at this and I do not really know how to implement it in my project.
I tried something like `
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
class WebClient
{
internal string DownloadString(string url)
{
throw new NotImplementedException();
url = "https://openexchangerates.org/api/latest.json?app_id=ae11142304694b10a1dbf2d25933a333";
var currencyRates = _download_serialized_json_data<App9.CurrencyRates>(url);
}
}
public static T _download_serialized_json_data<T>(string url) where T : new()
{
var w = new WebClient();
{
//using (var w = new WebClient()) {
var json_data = string.Empty;
// attempt to download JSON data as a string
try
{
json_data = w.DownloadString(url);
}
catch (Exception) { }
// if string with JSON data is not empty, deserialize it to class and return its instance
return !string.IsNullOrEmpty(json_data) ? JsonConvert.DeserializeObject<T>(json_data) : new T();
}
}
private void comboBoxTo_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void convertButton_Click(object sender, RoutedEventArgs e)
{
if (amountTb.Text == string.Empty)
{
afisareTb.Text = "Scrieti o valoare";
}
else
{
var currencyRates = _download_serialized_json_data<CurrencyRates>("https://openexchangerates.org/api/latest.json?app_id=YOUR_APP_ID ");
}
}
}
`
I do not have any errors, it is just that, when I press on converter button from my app, nothing happens.

SeekBar on Mono for Android

I would like to create a seekbar for a Mono for Android app that allows the user to select and i want to implement the SeekBar Widget, how can i use a SeekBarChangeListener() on Mono for Android?
To write a change listener you need a class that implements SeekBar.IOnSeekBarChangeListener:
public class SeekBarListener : Java.Lang.Object, SeekBar.IOnSeekBarChangeListener
{
public void OnProgressChanged(SeekBar seekBar, int progress, bool fromUser)
{
}
public void OnStartTrackingTouch(SeekBar seekBar)
{
}
public void OnStopTrackingTouch(SeekBar seekBar)
{
}
}
Then you can assign that to the seek bar:
seekBar.SetOnSeekBarChangeListener(new SeekBarListener());
Well i resolve this in the same class implementing SeekBar.IOnSeekBarChangeListener on another way here is my code:
private void CreateDialogSeek()
{
dialogSeek = new Dialog(this);
dialogSeek.SetContentView(Resource.Layout.seekbar_dialog);
dialogSeek.SetTitle("Change your configuration");
dialogSeek.SetCancelable(true);
//Ok
btnOk = (Button)(dialogSeek.FindViewById(Resource.Id.btnSettingsOKSeekBar));
btnCancel = (Button)(dialogSeek.FindViewById(Resource.Id.btnSettingsCancelSeekBar));
SeekBar mSeekBar = (SeekBar)(dialogSeek.FindViewById(Resource.Id.seekbar));
mSeekBar.Progress = cache;
mSeekBar.SetOnSeekBarChangeListener(this);
dialogSeek.Show();
btnOk.Click += delegate {OKSeek();};
btnCancel.Click += delegate {dialogSeek.Dismiss();;};
}
public void OnProgressChanged(SeekBar seekBar, int progress, bool fromUser)
{
cache = progress;
}
public void OnStartTrackingTouch(SeekBar seekBar)
{
}
public void OnStopTrackingTouch(SeekBar seekBar)
{
}

Categories