Introducing Xamarin - A REST API based HackerNews application that works on iOS, Android and Windows Phone

Posted by: Filip Ekberg , on 7/24/2014, in Category Xamarin
Views: 64498
Abstract: This article introduces Xamarin and demonstrated how to create a C# REST API based application that can run on all the major platforms - iOS, Android, Windows, Mac, Windows Phone

The past 5-7 years has been extremely interesting in the mobile world, especially considering the release of iPhones, Androids and Windows Phones. There has been a lot going on in the mobile spectrum even outside these three different brands. These three in particular share something though; they’re all easy to create applications for. This is of course subjective, it’s easier for some than for others, but if we compare the way we create native mobile applications for these three different platforms to what we saw 10 years ago; this is easier.

This article is published from the DotNetCurry .NET Magazine – A Free High Quality Digital Magazine for .NET professionals published once every two months. Subscribe to this eMagazine for Free and get access to hundreds of free tutorials from experts

Over the years we’ve seen a lot of interesting abstractions that have made the development even easier. Consider that you have an application that needs to target all the major platforms; iOS, Android and Windows Phone. In general that meant to either develop one application natively for each platform or develop the application using a shared code principle or a wrapper such as PhoneGap. Both of these strategies for cross-platform development have their ups and downs. The problem with the first approach of creating one application natively per platform is that we need a team that specializes in each platform. That means three different teams understanding the same acceptance criteria, hence three times as expensive, in general that is.

The benefit of going all-in on Native, is that we get a specialized user interface and it performs fast. Compared to the approach where we use PhoneGap or similar, to write an application in HTML, CSS and JavaScript that runs everywhere; the native approach wins performance and feeling wise. You can make an application good enough using PhoneGap, Sencha or similar, but it will never beat the native experience. However, write once – run everywhere has its benefits; you have one code base. This means one team developing the application, one team understanding the acceptance criteria and this means not as expensive.

Filip is giving away 20 of his C# Smorgasbord eBook to celebrate DNC Magazine's 2nd Anniversary.Participate Now. Giveaway ends on 10th August.

 

Xamarin to the rescue

Up until recently, going native has meant to develop three different applications, using three different languages and that has made it really difficult for companies to select more than 1-2 platforms to target. With Xamarin this is no longer necessary! What Xamarin does is that it introduces a third strategy for cross-platform development; write in one language, run everywhere and customize the user interface.

The way it works is that Xamarin will let you write the code in C#, a language we all love, then target all the major platforms; iOS, Android, Windows, Mac, Windows Phone. Most of these platforms don’t run the executables C# normally compiles to, so what Xamarin does is that it compiles it to the native code that each platform understands and produces the necessary binary. This means for iOS we have the IPA files and for Android we have APK.

This means that the code written with this approach, will run natively on each platform and perform just as well as if it was written in the language that the platform normally prefers; i.e. Objective-C for iOS and Java for Android.

In order to get a native user interface though, and with native user interface I refer to the fact that an iOS user doesn’t want an Android experience, we have a different user interface layer per platform. This means that the iOS, Android and Windows Phone project will be different. This is also what defines what type of executable to produce when the project itself is compiled.

Up until recently there’s been a goal of being able to share about 90% of the code between the different platforms. This is done by taking advantage of something called Portable Class Library (PCL). However, Xamarin has upped their game and released something called Xamarin.Forms, which enables you to share up to 100% of the code.

One language, one team, native performance, all major platforms – what else could we ask for when creating mobile applications?

Code sharing principles

Being able to share up to 100%, or even 90% among three different platforms is a great achievement. It will also mean there is less code to maintain, given that you didn’t write more code to be able to share of course. Consider all the business logic that you have in your applications you’ve written before. You may have ways to process users such as adding or removing. You might have ways to process invoices, reports, privileges and what not. Are any of those specific to iOS, Android or Windows Phone? Hopefully not, thus having this shared in a common class library (PCL) means we don’t have to write it once per platform.

Other things are platform specific and should be, such as reading and writing to the storage. This works differently on iOS, Android and Windows Phone so how do we write sharable code for this? If we have a lot of logic around storing and processing stored data, we don’t want to keep all that sharable logic, redundantly in each platform specific project. The answer is Interfaces!

You’re developing an application that handles lots of data, you want to cache the data and only download new data after 1 – 2 days, or whatever expiry period the data might have. You want to hide the caching mechanism in your repository, but the loading and saving to the device storage is platform specific, so what we need is an interface that we can implement in each of the platform specific projects.

Let’s say that we have the interface IStorageHandler, each of our projects can now have an implementation of this interface: iOS.StorageHandler, Droid.StorageHandler and WindowsPhone.StorageHandler. When the application starts, we simply inject the correct storage handler into the repository and it will simply use the platform specific code. Because after all, the interface is just a contract telling us what something can do, it’s up to us to define the implementation where it matters.

Sometimes though, there’s no common interface to use, which might be problematic. You might want to trigger Azure Mobile Service authentication from a shared PCL, but there is no PCL version of Azure Mobile Service, however it does exist for all the platforms. What you can do in this case is to inject an Action or a Func to trigger the authentication. I prefer the interfaces, but that’s just me.

Creating a User Interface for each platform

While sharing the logic for the business layer might seem obvious, the question about what we do about the user interface arises. It’s not immediately evident that we have to separate each implementation of the user interfaces for each platform. However this is true with some modification, as stated previously, the goal is to share up to 100% of the code. Previously this is something we didn’t do. As each platform have their own specific user interface design principles, it’s been more convenient not to try and abstract this layer. Not just because it’s more convenient to make the native user interface using the approach that you’d do natively - Android XML for Android, Interface Builder/Storyboards for iOS and XAML for Windows Phone. Also because following this pattern separated the development where it mattered. Without the separation it’s easy to get stuck in the write once, run everywhere paradigm where we have to conform to a lowest common denominator.

With the release of Xamarin 3 you’re not obligated to go with this approach, you can create a shared user interface layer by defining the user interface in code; C# or XAML. It’s not necessary to have the entire application written with Xamarin.Forms, if it happens that there’s something you can’t share, user interface wise, you can create that specifically for each platform using the approach that one has been able to do before. Consider for a second how powerful it is to be able to create a mobile application using one language, getting a native experience both performance and user interface wise, without letting the users down. It’s perfect!

Sharing a User Interface with Xamarin.Forms

Fortunately for us with the latest version, Xamarin 3, we get Xamarin.Forms installed with some good project templates. Developing the applications for iOS, Android and Windows Phone, in my opinion, is easiest on a Mac. You might wonder why is that so? Simple: we can’t compile iOS applications on Windows due to license restrictions. However, Xamarin solves this for us by letting us connect to a Mac, be it the same machine using parallels or a machine on the network. We can use the Xamarin Build Host. This will let you connect Visual Studio to the build host, in order to enable build and debug from Windows. Personally I prefer doing this in parallels but it could just as well be a mac machine on your network, or why not MacInCloud!

xamarin-build-host

Figure 1: Xamarin Build Host

In Visual Studio, after of course having installed Xamarin 3, you will find the new project templates in the Mobile Apps selection. You can either select to use portable class libraries, or a shared project. The shared project is a new paradigm that was introduced first with Visual Studio 2013 Update 2 for Universal Apps.

xamarin-project-template

Figure 2: Xamarin Project Template in VS 2013 Update 2

Selecting the shared option will create 4 projects:

· A Shared project containing the shared UI

· Android project setting up the activity to use the shared UI

· iOS project setting up the view controller to use the shared UI

· Windows Phone project setting up the main page to use the shared UI

shared-code

Figure 3: Shared Code

The shared code in this template application simply sets up a new page; you might recognize the user interface principles from Windows Phone! Here we’re simply setting up a new content page with a label in it.

If we instead mark the iOS project as the start-up project, and select the platform to be the iOS Simulator, you may now run the application and see that it successfully deploys to iOS!

old-ios-simulator

Figure 4: Application running in an older iOS simulator

We of course want to change this user interface, but this gives you a basic idea that we have the code for the interface shared! All the different platforms create this page differently. The shared code is accessible via App.GetMainPage() and the different platforms uses it differently to set it up.

iOS

In the App Delegate for iOS, where we setup the main view controller, we simply create and use the shared user interface like this:

Forms.Init();
App.GetMainPage().CreateViewController()

Android

In the main activity for android, we set it up differently compared to iOS, as both the platforms are fundamentally different:

Xamarin.Forms.Forms.Init(this, bundle);
SetPage(App.GetMainPage());

Windows Phone

For Windows Phone what happens in the main page is that it converts the page returned from the shared user interface code, to a real UIElement. It then sets the current page content to whatever that element represents:

Forms.Init();
Content = DNC.NewsReader.App.GetMainPage().ConvertPageToUIElement(this);

Note the call to Forms.Init(). Forms.Init() must be called before making any calls to Forms API. This step enables the device (iOS, Android, Windows Phone) specific implementation of Xamarin.Forms to be available globally in the application.

Capabilities and possibilities

Frankly I think you can solve about anything using Xamarin.Forms without too much diversity. There are so many different layouts and controls available out of the box such as: Stack-, Grid-, Absolute-, RelativeLayout, Button, Image, Map, Editor, WebView, ActivityIndicator and much more. All these components and layouts make up for most of the things that you could possibly want to use; unless you are creating a game of course, but then you might be looking at other alternatives such as Unity.

Of course what we have seen so far is just a very simple example, but with some imagination, you could see the endless possibilities and the hours, money and headaches saved by going this route.

Consuming REST APIs

Working with data is central to almost any application and a lot of our data today is accessible over HTTP. A REST API is just a fancy way of saying that we expose an API over HTTP, meaning that we can perform GET, POST, PUT and DELETE. Let’s not worry too much about the HTTP verbs but only focus on using GET for this example. Here’s what I’d like to achieve, see it as the acceptance criteria and allow it to be a bit vague:

The application should work on iOS, Android and Windows Phone with a minimalistic UI. The application uses an API to fetch news articles from HackerNews; which is publicly accessible by a third party. When listing news, show the title. When clicking the article, show the article content.

As you may have noticed, the shared project does not contain any references; this is because it relies on File Linking. This means that if we want to use certain libraries in our shared project, we need to install the reference in each UI layer.

However in our case, let’s create a portable class library where we can interact with our API, that way we don’t have to install the NuGet package in all the projects! We just need to reference our PCL to them.

I’ve created a new portable class library that I call Shared:

portable-class-library

Figure 5: Portable Class Library

We’re going to start off by installing Microsoft.Net.Http to get access to the HttpClient, which we will use in order to fetch the news from the HackerNews API. This is of course installed into our newly created PCL.

http-package

To make this work, you will also need to install JSON.NET.

newtonsoft-json

Within the shared library, the portable class library that I want to have is a class that I call HackerNewsRepository. This is my entry point from where I get the news. As a consumer of the repository, I don’t really care where it comes from, if it’s cached or what is going on – I just want the data!

public class HackerNewsRepository
    {
        public async Task> TopEntriesAsync()
        {
            var client = new HttpClient();

            var result = await client.GetStringAsync("http://api.ihackernews.com/page/");

            return JsonConvert.DeserializeObject(result).Items;
        }
    }

The repository is fairly straightforward, it relies on two models as seen below, performs a web request to a certain URL and returns the deserialized result from that. We are never exposing what we know as a Page inside the repository, but just an enumerable of Entries.

public class Entry
    {
        public int Id { get; set; }
        public int Points { get; set; }
        public string PostedAgo { get; set; }
        public string PostedBy { get; set; }
        public string Title { get; set; }
        public string Url { get; set; }
    }

    public class Page
    {
        public int? Next { get; set; }
        public IEnumerable Items { get; set; }
    }

From the example you saw above in Figure 4, where the application runs on iOS, I’m using an older simulator. This is just to show that this is backwards compatible and works good with older devices too! Going forward we will look at it using the latest iOS simulator.

Now that we have the possibility to fetch news from the HackerNews API, we want to make the necessary changes to the shared user interface code. Before we can do that, we need to have a reference to the shared portable class library in all the user interface layers.

Once that is done, we want to modify the App class to look like the following:

 

public class App
{
    public static INavigation Navigation { get; private set; }
	public static Xamarin.Forms.Page GetMainPage()
	{
		var navigationPage = new NavigationPage(new HackerNewsPage());
        Navigation = navigationPage.Navigation;

        return navigationPage;
	}
}

There are a couple of distinct things to notice here. First, I had to change the method signature to use the full namespace for Page as this type now also exists in our shared portable class library. Secondly we are no longer returning just a content page, we are returning a navigation page and the navigation property from it is exposed as a property on the App. The HackerNewsPage is simply a class that inherits from ContentPage. This allows us to override certain methods, such as when the page appears.

public class HackerNewsPage : ContentPage
{
    private ListView listView;
    public HackerNewsPage()
    {
        Title = "Hacker News Stories";

        listView = new ListView
        {
            RowHeight = 80
        };

        Content = new StackLayout
        {
            VerticalOptions = LayoutOptions.FillAndExpand,
            Children = { listView }
        };
    }
    protected override async void OnAppearing()
    {
        base.OnAppearing();

        var entries = await new HackerNewsRepository().TopEntriesAsync();
        listView.ItemTemplate = new DataTemplate(typeof(HackerNewsEntryCell));
        listView.ItemsSource = entries;
    }
}


Having an asynchronous void method is generally bad, but let’s say that it’s OK in this case and move on from that part. The code above creates the list view that we see; it starts loading the data when the view appears and populates the list view once the data has arrived. It uses a cell template that we need to define; in this cell template we can make use of data binding. This is also where we define what happens when we tap on one of the list view rows:

public class HackerNewsEntryCell : ViewCell
{
    public HackerNewsEntryCell()
    { 
        var title = new Label();
        title.SetBinding(Label.TextProperty, "Title");
            
        var postedBy = new Label();
        postedBy.SetBinding(Label.TextProperty, "PostedBy");

        View = new StackLayout
        {
            Children = { title, postedBy }
        };
    }

    protected override void OnTapped()
    {
        base.OnTapped();

        var entry = BindingContext as Shared.Entry;

        var article = new WebView
        {
            Source = new UrlWebViewSource
            {
                Url = entry.Url,
            },
            VerticalOptions = LayoutOptions.FillAndExpand
        };

        App.Navigation.PushAsync(new ContentPage { Title = entry.Title, Content = article });
    }
}


Interestingly enough we are using the navigation that we previously made accessible in the application definition. We use this to push a new web view in a new content view, onto the stack of views. We can access the bound element that we clicked via BindingContext hence this is how we can get the entry title and url. Running this gives us the native look and feel on the different devices:

xamarin-native-feel

Figure 6: Native Look and Feel across Devices

Create the UI using XAML

If you rather prefer creating the user interface using XAML, that’s equally easy! All you need to do is create a new Xamarin.Forms XAML file and add the corresponding code to that. Having seen the XAML from WPF, Silverlight, Windows 8 or Windows Phone helps to get you accustom to the syntax and the elements. All the controls that we have used translates directly into XAML and with just a slight modification on how we handle the tapping of an element, we can get this transformed into XAML.

The following is all the code that goes into the HackerNewsPage.xaml in order to make it corresponding to what we had earlier. This replaces the HackerNewsPage and HackerNewsEntryCell that we saw previously:


               

As you can observe, we are taking advantage of bindings by binding to elements that we know are inside our collection of data. Now you’re probably wondering what does the code behind looks like and honestly it’s basically a copy and paste from what we had in the previous OnTapped method. The only difference is where we get our tapped element:

public void OnTapped(object sender, ItemTappedEventArgs args)
{
    var entry = args.Item as Shared.Entry;

    var article = new WebView
    {
        Source = new UrlWebViewSource
        {
            Url = entry.Url,
        },
        VerticalOptions = LayoutOptions.FillAndExpand
    };

    App.Navigation.PushAsync(new ContentPage { Title = entry.Title, Content = article });
}

There is one more thing that we do have to change before we can get this to play well with our application. We have to tell the app startup to hook up the context that we want to bind. We’re going to do this by using an asynchronous event, in reality you want to unsubscribe to your events as well, but to keep the example easy, I’ll make use of an anonymous, asynchronous method. We are also going to keep track of if the data is already loaded, this makes it much easier on the application. We no longer have to load the data each time the view appears:

public static Xamarin.Forms.Page GetMainPage()
{
    var page = new HackerNewsPage();

    var contentLoaded = false;

    page.Appearing += async (sender, args) => {
        if (!contentLoaded)
        {
            page.BindingContext = await new HackerNewsRepository().TopEntriesAsync();
            contentLoaded = true;
        }
    };
            
    var navigationPage = new NavigationPage(page);
    Navigation = navigationPage.Navigation;

    return navigationPage;
}

That is all there is to it, in order to convert the code we had previously used and instead use XAML! As you will see in Figure 7, running this on Android will look similar to what we’ve seen on the other platforms, but it has the Android feel. There’s a bunch of things you can do to make the user interface look better of course, but that’s outside the scope of this article.

android-view

Figure 7: Android look and feel

Conclusion

Developing mobile applications seem to get easier by the day, especially with tools like Xamarin. There’s no longer a valid reason to neglect one of the major platforms when developing a new application for yourself or for your business. Sharing all the user interface code in one library, sharing all business logic, one language, one team, and one set of experts; how else could it have possibly become better? If you have a lot of time invested in a native platform, it might make sense to continue down that path, but keep in mind that Xamarin can help your transition by letting you create wrappers for native code. This means that you can develop using Xamarin for new applications while still maintaining your native code-base as long as you need to.

What are you waiting for? Get started with your application for iOS, Android and Windows Phone today!

Download the entire source code from our GitHub Repository at bit.ly/dncm13-xamarin

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Filip is a Microsoft Visual C# MVP, Book author, Pluralsight author and Senior Consultant at Readify. He is the author of the book C# Smorgasbord, which covers a vast variety of different technologies, patterns and practices. Follow Filip on twitter @fekberg and read his articles on fekberg.com


Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by Rob de Voer on Thursday, July 24, 2014 4:03 PM
Please note that the dotnetcurry branding is on the second image for NuGet and hides the command! :)

I know the command but others may not.

Thought you would like to know so you can fix it...
Comment posted by Rob de Voer on Thursday, July 24, 2014 4:09 PM
Hi, please note that class HackerNewsRepository has html markup in return... <page> has closing statement... :)

Also class Page has html markup near <entry>.

Cheers.

Like the article! Would be good to see a slightly more advanced follow up to promote Xamarin and also show how it works. Nice work.
Comment posted by Suprotim Agarwal on Friday, July 25, 2014 12:50 PM
Not sure how these things creep in the code. Anyways thanks @Rob de Voer for pointing them out. Fixed! Btw, what exactly do you have in mind for a followup article?
Comment posted by vivek on Friday, January 9, 2015 3:47 AM
how to pass json data in listview??

Categories

JOIN OUR COMMUNITY

POPULAR ARTICLES

FREE .NET MAGAZINES

Free DNC .NET Magazine

Tags

JQUERY COOKBOOK

jQuery CookBook