Blog


Day 1 – Building an app – “Best Before” – with Ionic 3.x – Learning Angular 5.X / TypeScript

This video marks the beginning of a series in which I take on Ionic 3.X and Angular 5.X in developing an app called “Best Before”. In these first 2 hours we go through the project setup as I will be working with Visual Studio 2017 & there isn’t any official support for Ionic 3 projects in VS yet.

We’re also playing with some sample Angular fiddles and we look at some of the differences between Angular 1 and 2+.

You can follow this series live by subscribing to my Twitch channel: Twitch.tv/startdebugging. This way you will get notified when I go live. Or you can view the video recording on our YouTube channel page: YouTube.com




UWP – Using an Acrylic Brush in your Xamarin Forms MasterDetail menu

Right, so you are one of those guys targeting UWP with their Xamarin Forms app… aand you want to use the new Acrylic brush to make you application stand out. Say no more.

Gazeta Acrylic menu on UWP

We won’t be using any 3rd party library/package to do this and we’ll be working in the platform specific project; so open up your MainPage.xaml.cs found inside your UWP project. First thing we need to do is grab a reference to your MasterDetail Master page. In my case, the MasterDetail represents my MainPage so things are pretty straight forward.

var masterPage = (app.MainPage as Xamarin.Forms.MasterDetailPage).Master;



AdMob Smart Banner sizing in Xamarin Forms

In one of my previous posts on How To: Add AdMob to your Xamarin Forms app I was giving a piece of code that looked like this:

<controls:AdMobView WidthRequest="320" HeightRequest="50" />

That will work perfectly with Banner ads but it’s going to fail if you choose to use a Smart Banner. For a Smart Banner, the sizing is a bit more complicated – it depends on the height of your device. You can find out more on AdMob ad unit sizing here.

Ad height Screen height
32 dp ≤ 400 dp
50 dp > 400 dp and ≤ 720 dp
90 dp > 720 dp

Now, dps are density-independent pixels. Do not mistake them for your device’s screen resolution. This unit of measure is what both Android and Xamarin Forms use when it comes to sizes. In order to calculate you screen height in dps we’ll get the screen resolution and divide it by the density; Again this density value isn’t your screen dpi, it’s the scale at which pixels are grouped into dps. For example, for a screen width of 1080 pixels and a density of 3, you will have an actual width of 360dp.

var dpHeight = Resources.DisplayMetrics.HeightPixels / Resources.DisplayMetrics.Density;

So that’s how you get your screen height in dps. Now we need to implement the logic behind that size table and wrap it all into a function.

private int GetSmartBannerDpHeight()
{
    var dpHeight = Resources.DisplayMetrics.HeightPixels / Resources.DisplayMetrics.Density;

    if (dpHeight <= 400) return 32; 
    if (dpHeight > 400 && dpHeight <= 720) return 50;
    return 90;
}

 

The AdMob renderer

And that’s it, now in your AdMobRenderer you go ahead and specify the new AdBanner size and use the newly implemented method to request the proper height based on the device’s screen. The complete renderer for Android would look like this:

[assembly: ExportRenderer(typeof(AdMobView), typeof(AdMobRenderer))]

namespace GazetaSporturilor.Droid.Renderers
{
    public class AdMobRenderer : ViewRenderer
    {
        public AdMobRenderer(Context context) : base(context)
        {

        }

        private int GetSmartBannerDpHeight()
        {
            var dpHeight = Resources.DisplayMetrics.HeightPixels / Resources.DisplayMetrics.Density;

            if (dpHeight <= 400) return 32;
            if (dpHeight > 400 && dpHeight <= 720) return 50;
            return 90;
        }

        protected override void OnElementChanged(ElementChangedEventArgs<View> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
            {
                var ad = new AdView(Context)
                {
                    AdSize = AdSize.SmartBanner,
                    AdUnitId = "_your_admob_ad_unit_id_goes_here_"
                };

                var requestbuilder = new AdRequest.Builder();

#if !DEBUG
                ad.LoadAd(requestbuilder.Build());
                e.NewElement.HeightRequest = GetSmartBannerDpHeight();
#endif

                SetNativeControl(ad);
            }
        }
    }
}

That’s about it.




Xamarin ListView performance & replacing it with Syncfusion SfListView

While Xamarin keeps adding features and improves the performance of Xamarin Forms with each and every update, what they offer in terms of cross-platform user controls is not always enough. In my case, I’ve got an RSS reader app which aggregates news articles from different sources and displays them in a ListView like this:

Gazeta Xamarin ListView

While I like how the app looks, it has a big issue – performance. Even on high-end devices the scrolling is sluggish and on low-end devices it keeps on throwing OutOfMemory exceptions due to the images that are being loaded. So, a change was needed. In this article I’ll only cover the first one – the scrolling performance; we’ll have a look at the OutOfMemory exceptions another time.

The Item template

First thing you need to look at when troubleshooting performance is the ListView ItemTemplate. Any kind of optimization that you can do at this level will have a big impact on the overall performance of your ListView. Look at things like:

  • reducing the number of XAML elements. The fewer elements to render, the better
  • same goes for nesting. Avoid nesting elements and creating deep hierarchies. It will take way too long to render them
  • make sure your ItemSource is an IList and not an IEnumerable collection. IEnumerable doesn’t support random access
  • don’t change the layout based on your BindingContext. Use a DataTemplateSelector instead

You should already see some improvements in scrolling after making these changes. Next on the list is your caching strategy.

Caching strategy

By default Xamarin uses the RetainElement caching strategy for Android and iOS which means that it will create one instance of your ItemTemplate for each item in your list. Change your ListView’s caching strategy to RecycleElement to reuse containers that are no longer in view instead of creating new elements every time. This will increase performance by removing initialization costs.

<ListView CachingStrategy="RecycleElement">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
              ...
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

If by any chance you’re using a DataTemplateSelector, then you should use the RecycleElementAndDataTemplate caching strategy. For more details on caching strategies you can check Xamarin’s documentation on ListView performance.

Syncfusion ListView

If you got this far and your performance issues aren’t solved, then it’s time looking at other options. In my case, I gave Syncfusion SfListView a try because they’re known for their control suites and they offer their Xamarin controls for free under the same conditions as Visual Studio Community (more or less). To get started head over to Syncfusion’s website an claim your free comunity license if you haven’t already.

Next, you need to add the SfListView package to your project. Syncfusion packages are available through their own NuGet repository. To be able to access it you’ll need to add it to you NuGet sources. A complete guide on how to do that can be found here. One you’ve done that, a simple search for SfListView in NuGet will result in the desired package. Install the package in your core/cross-platform project and in all your platform projects as well; it will automatically pick up the correct DLLs based on your project’s target.

Now that you’ve got everything installed, it’s time to replace the standart ListView. To do so, add the following namespace in your page/view:

xmlns:sflv="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms"

And then replace the ListView tag with sflv:ListView, the ListView.ItemTemplate with sflv:SfListView.ItemTemplate and remove the ViewCell from your hierarchy – it’s not needed. Additionaly, if you’ve been using the CachingStrategy property, remove that as well – SfListView recycles elements by default. You should end up with something like this:

<sflv:ListView>
    <sflv:SfListView.ItemTemplate>
        <DataTemplate>
           ...
        </DataTemplate>
    </sflv:SfListView.ItemTemplate>
</sflv:SfListView>

That’s it. If you have any questions let me know in the comments section below. Also, if you’ve got any other tips to share that would improve ListView performance, please do.




How To: Add AdMob to your Xamarin Forms app

One of the first things people think about when developing for a new platform / using a new technology is monetization; and in my case the question is: how easy is it to integrate AdMob? For Xamarin Forms the answer would be: “It depends” – it depends on luck & on the complexity of what you want to achieve; but I will detail this as we move along.

The first thing you need to do is add the required components to your projects. For this walktrough I will be using Visual Studio but it should be relatively the same when using Xamarin Studio. Here, things go separate ways for each of the platforms:

  • for Android – add Nuget package Xamarin.GooglePlayServices.Ads.Lite
  • for iOS – add Nuget package Xamarin.Google.iOS.MobileAds
  • for Windows Phone – download the SDK from here and add it as a reference platform no longer supported

By now, you Android project should no longer be building & you should be receiving a COMPILETODALVIK : UNEXPECTED TOP-LEVEL error. To fix that, go into your Droid project properties, select the Android Options tab and then under Advanced modify the value for the Java Max Heap Size to 1G. Your project should now build without any errors.

Next, inside your shared / PCL project add a new Content View and call it AdMobView. Remove the code generated inside it’s constructor & it should look like this:

public class AdMobView : ContentView
{
    public AdMobView() { }
}

Add this new view to your page. In XAML you can do it like this:

<controls:AdMobView />

Make sure NOTHING interferes with the control. By nothing I mean – overlapping controls, page padding, control margins / spacing, etc. If you have something overlapping the ad control, ads will not display & you won’t receive an error, so be careful.

Next, it’s time to add the custom view renderers; and again, we’ll handle each platform:

Android

Add a new class called AdMobRenderer with the code below. Make sure to keep the ExportRenderer attribute above the namespace, otherwise the magic won’t happen.

[assembly: ExportRenderer(typeof(AdMobView), typeof(AdMobRenderer))]

namespace AdExample.Droid.Renderers
{
    public class AdMobRenderer : ViewRenderer
    {
        public AdMobRenderer(Context context) : base(context)
        {

        }

        private int GetSmartBannerDpHeight()
        {
            var dpHeight = Resources.DisplayMetrics.HeightPixels / Resources.DisplayMetrics.Density;

            if (dpHeight <= 400) return 32;
            if (dpHeight > 400 && dpHeight <= 720) return 50;
            return 90;
        }

        protected override void OnElementChanged(ElementChangedEventArgs<View> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
            {
                var ad = new AdView(Context)
                {
                    AdSize = AdSize.SmartBanner,
                    AdUnitId = "ca-app-pub-xxxxxxxxxxxxxxxx/xxxxxxxxxx"
                };

                var requestbuilder = new AdRequest.Builder();

                ad.LoadAd(requestbuilder.Build());
                e.NewElement.HeightRequest = GetSmartBannerDpHeight();

                SetNativeControl(ad);
            }
        }
    }
}

Next, you need to modify your AndroidManifest.xml file to add the AdActivity & required permissions for displaying ads: ACCESS_NETWORK_STATE, INTERNET; just like in the example below.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
	<uses-sdk android:minSdkVersion="15" />
	<application>
    <activity android:name="com.google.android.gms.ads.AdActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" android:theme="@android:style/Theme.Translucent" />
  </application>
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.INTERNET" />
</manifest>

That’s it. Your Android build should now display ads inside the AdMobView content view.

iOS

Start off by adding one line in your AppDelegate.cs to initialize the SDK with your application ID. Careful, do not mistake this with your ad unit ID! Add this just before the LoadApplication call.

MobileAds.Configure("ca-app-pub-xxxxxxxxxxxxxxxx~xxxxxxxxxx");

Then, same as before, just add a new class called AdMobRenderer and copy-paste the code below replacing the AdmobID with the ID of your banner unit.

[assembly: ExportRenderer(typeof(AdMobView), typeof(AdMobRenderer))]

namespace GazetaSporturilor.iOS.Renderers
{
    public class AdMobRenderer : ViewRenderer
    {
        BannerView adView;
        bool viewOnScreen;

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
        {
            base.OnElementChanged(e);

            if (e.NewElement == null)
                return;

            if (e.OldElement == null)
            {
                adView = new BannerView(AdSizeCons.SmartBannerPortrait)
                {                    
                    AdUnitID = "ca-app-pub-xxxxxxxxxxxxxxxx/xxxxxxxxxx",
                    RootViewController = GetRootViewController()
                };

                adView.AdReceived += (sender, args) =>
                {
                    if (!viewOnScreen) this.AddSubview(adView);
                    viewOnScreen = true;
                };

                var request = Request.GetDefaultRequest();

                e.NewElement.HeightRequest = GetSmartBannerDpHeight();
                adView.LoadRequest(request);

                base.SetNativeControl(adView);
            }
        }

        private UIViewController GetRootViewController()
        {
            foreach (UIWindow window in UIApplication.SharedApplication.Windows)
            {
                if (window.RootViewController != null)
                {
                    return window.RootViewController;
                }
            }

            return null;
        }

        private int GetSmartBannerDpHeight()
        {
            var dpHeight = (double)UIScreen.MainScreen.Bounds.Height;

            if (dpHeight <= 400) return 32;
            if (dpHeight > 400 && dpHeight <= 720) return 50;
            return 90;
        }
    }
}

That’s it. Now you have ads being served on both platforms. Any comments or suggestions you have leave them in the comments section below.

Update 30 Dec 2017

In this article we looked at displaying Banner ads and hard-coded the view size to 320 x 50 dp. If you’re looking to implement smart banners have a look at this follow-up post: AdMob Smart Banner sizing in Xamarin Forms

Update 21 Jan 2018

I finally made the courage to try and build one of my apps for iOS so I’ve updated this article to work with the latest version of AdMob for Xamarin. I’ve also included the smart sizing code mentioned in the 30 Dec update. Thanks to everyone helping out in the comments section with the iOS implementation.




Fix Xamarin error – Csc.exe exited with code -1073741790. (MSB6006)

Just run Xamarin Studio as an Administrator.

The error usually means that the process cannot access a certain resource. In my case that meant insufficient rights; but it could also mean that some file is already in use; in that case – Clean the solution & Rebuild and if that doesn’t work either do a manual cleanup of the solution bu deleting the “bin” and “obj” folders for every project in your solution.




Changing the Cordova version used by Hybrid Apps in Visual Studio 2013

Updating the Cordova version requires you to edit the platforms.js file found in:

%APPDATA%\Roaming\npm\node_modules\vs-mda\node_modules\cordova\node_modules\cord‌​ova-lib\src\cordova

You can change the version individually for each platform, tho I suggest you use the same version for all.
Also, it might be the case you’re looking to update only because of the Google Play warning regarding the high severity cross-application scripting (XAS) vulnerability found in Cordova 3.5.0. If so here you have the file updated to point to version 3.5.1 which fixes the mentioned vulnerability: platforms.js.

Note: In case you are using CTP 1 of the Hybrid Apps the path will be different:
%APPDATA%\npm\node_modules\vs-mda\node_modules\cordova\




Counting up to one trillion

How long does it take a computer to count up to one trillion?

This is a question that came after a discussion with a colleague of mine at the university. He was telling me about some company worth over 20 trillion dollars – and he just couldn’t imagine how that much money would look like in cash. Just to get an idea of it we calculated how many hundred dollar bills it would take to circle the Earth once – the answer was I believe around 240.000.000 meaning around 24 billion US dollars. That’s a lot of money. How much would it take a person to count that much money? Well, I can’t say for sure.

What we can do to get an idea is see how much it would take a computer to count up to that value. To simply iterate, no other action in between. For that I’ve wrote a simple piece of code which measures how much it takes to count up to one million and then does some simple math to estimate how much it would take to count up to different values and then displays the results in a friendly way using a method courtesy of StackOverflow.

The results are interesting. And the answer is: it depends on your machine. Even on the same machine you will get different results depending on the load. But let’s look at mine for a bit:

  • one billion (9 zeros) is being reached fast – 15 seconds
  • but to get to one trillion (12 zeros) – the difference is amazing – 4 hours and 10 minutes. Basically 1000 times more.
  • the differences get even more impressive as we go up to quadrillions (15 zeros)  which would take 173 days and then quintillions (18 zeros) which would take 475 years
  • the last one for which I did the math is one sextillion (21 zeros) and get ready – it would take my laptop exactly 7708 years, 292 days, 6 hours, 43 minutes and 52 seconds to iterate up to that value.



Adding speech recognition to your WP8 app

To add speech recognition to our app we will be using the newly released version of the Windows Phone toolkit (release June 2013) – which adds a nice new control called SpeechTextBox (that does exactly what you think). You can get the latest build using NuGet or you can download the source from CodePlex.

Once you’ve referenced the toolkit in you project all you are left to do is add the control:

<toolkit:SpeechTextBox SpeechRecognized="SpeechTextBox_SpeechRecognized" />

Handling the SpeechRecognized event is not necessary. I’ve left it there just to point out that you can choose what you want to do with the speech recognition result. The event comes with a SpeechRecognizedEventArgs parameter which allows you to check the level of confidence for the recognized phrase and also get details about the phrase semantics.




Periodically update your live tiles using ScheduledTaskAgent

I’ve covered in a previous post how to create wide tiles for your Windows Phone 7 application. Now it’s time to bring them to life. The easiest way to do so is by using a ScheduledTaskAgent. To create one go ahead and add a new project to your solution and from the project templates list choose ‘Windows Phone Scheduled Task Agent’.

Before we go any further – go ahead and add this new (task agent) project as a reference in the main application project.

This will create for you a class called ‘ScheduledAgent’ which inherits ‘ScheduledTaskAgent’. You can leave the constructor of the class and the exception handler as they are. The method that interests us is ‘OnInvoke’. This is the method that will be called for us periodically for as long as the agent is running.

This is the method in which we will update our live tile. Let’s say we update our tile from a RSS feed. So the first thing we need to do is download our feed.

protected override void OnInvoke(ScheduledTask task)
{
    WebClient client = new WebClient();
    client.DownloadStringCompleted += (s, e) =&gt;
        {
            DownloadStringCompleted(s, e);
            NotifyComplete();
        };
    client.DownloadStringAsync(new Uri(&quot;http://blogs.windows.com/windows_phone/b/windowsphone/rss.aspx&quot;));
}

Once downloaded, deserialize it, take the first (latest) item and use the title and image to update your live tile.

private void DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    if (e.Error == null)
    {
        StringReader stringReader = new StringReader(e.Result);
        XmlReader xmlReader = XmlReader.Create(stringReader);
        SyndicationFeed feed = SyndicationFeed.Load(xmlReader);

        var latestArticle = feed.Items.FirstOrDefault();
        var tile = ShellTile.ActiveTiles.FirstOrDefault();
        if (tile != null)
        {
            var tileData = new FlipTileData();
            tileData.Title = &quot;Windows Phone Blog&quot;;

            var content = latestArticle.Title.Text + &quot; - &quot; + latestArticle.Summary.Text;
            var image = latestArticle.Links.FirstOrDefault(l =&gt; l.MediaType != null &amp;&amp; l.MediaType.Contains(&quot;image&quot;)).Uri;

            tileData.BackContent = content;
            tileData.BackgroundImage = image;

            tileData.WideBackContent = content;
            tileData.WideBackgroundImage = image;
            tile.Update(tileData);
        }
    }
}

Pay attention to where I call NotifyComplete()! This method releases all the resources used by the agent. It is important to call this method because otherwise the task will never end and thus will never start again. It is also very important to call it when everything is done – in this particular case in the DownloadStringCompleted event, after updating the live tiles.

This leaves us with only one thing left to do: registering the scheduled task. We will do this in the Application_Launching event (found in App.xaml.cs).

private void Application_Launching(object sender, LaunchingEventArgs e)
{
    var taskName = &quot;WindowsPhoneBlogSTA&quot;;
    PeriodicTask periodicTask = ScheduledActionService.Find(taskName) as PeriodicTask;
    if (periodicTask != null)
        ScheduledActionService.Remove(taskName);

    periodicTask = new PeriodicTask(taskName) { Description = &quot;Periodic task to update the tile of &lt;your app&gt;.&quot; };
    try
    {
        ScheduledActionService.Add(periodicTask);
        #if DEBUG
            ScheduledActionService.LaunchForTest(taskName, TimeSpan.FromSeconds(30));
        #endif
    }
    catch (InvalidOperationException) { }
}