Building Android Apps with C# (Intro to Xamarin.Forms)

What is Xamarin?

We can’t just create an android project and start writing C# in it. That would be crazy! Right? We need some kind of wrapper or framework for that. You may have heard of a javascript framework called Cordova which allows you to write cross platform mobile apps using the web stacks (HTML, CSS, Javascript). Likewise, now we can also make cross platform apps with C# using Xamarin framework. Xamarin provides three solution templates to build mobile apps,

  • Xamarin.iOS ( Only for making iOS apps. Use storyboard to design UI and connect that to your C# code behind instead of Objective C or Swift )
  • Xamarin.Android ( Only for making Android apps. Use AXML for UI designing whereas you will use C# as code behind instead of Java as backend code )
  • Xamarin.Forms ( For making apps for iOS, Android and Windows. Framework provides a set of UI components for creating layout that can be shared across multiple platforms. Use XAML for UI designing and C# as code behind. )

Why Xamarin.Forms?

I’m using Xamarin.Forms for the demo which I’ll demonstrate soon. Reason behind choosing Xamarin.Forms is I’m a windows phone developer (guilty of charge) which means I already know XAML. Other than that I’m a huge fan of code sharing which means I like to write code once and get it working in all the possible platforms. If you want to know more about Xamarin, you can go to their official site from this link - https://xamarin.com/

What are we building?

Xamarin.Forms is a great choice for building data driven apps. So let’s make one. Let’s make an app which will show all the characters from STAR WARS movies in a ListView. I found a free API online (https://swapi.co/) from where I can get all the movie characters in a JSON format from this link - https://swapi.co/people.

Building the app

Open up the Xamarin Studio. Create a new Xamarin.Forms app. Give your app a name. You can keep the Identifier as it is. If you are on a MAC, you will have the iOS checkbox enabled for you. Since I’m on Windows I can only target the Android platform. Select portable or shared class library in the Shared Code section. Finish the next steps.

After you create the solution, you will have three projects in your solution. One for the shared code (starwars), one for the android app and last one as the name goes is a UI testing project for you app. Just set the starwars.Droid as a startup project and run your app.

Before plugin every bits and pieces of the app. Let’s discuss some of the basics of this skeleton app. So where this “Welcome to Xamarin Forms!” is coming from? If you go to the startwars.cs file, you will see the exact reason of this magic! In the App() constructor, we have set the MainPage (the starting page) property to a newly instantiated ContentPage. This is one of many built in classes that Xamarin gives us to build the UI of our app. Everything else inside ContentPage is self-explanatory. We added a StackLayout to the Content property. StackLayout is used to place your controls in a stack on the ContentPage. The StackLayout itself is vertically centered ( VerticalOptions = LayoutOptions.Center ) on the page. We have a Label which is used for showing raw text as child to the StackLayout. And the text is aligned in the center ( XAlign = TextAlignment.Center ) of the Label. I’ve mapped the whole code to the output layout so that you have a good understanding on what is happening.

We can add a standalone ContentPage in the project and mimic all these things with XAML. So, right click and add a new file to the shared project. Select the “Forms ContentPage Xaml” from the list. Since this is where I’ll show all the STAR WARS characters, so I named it SWCharacters.

After adding we’ll have a XAML document with a connected C# code behind.

If you notice carefully, you will see that we have a ContentPage and the Content node set up for us. Time to add the other pieces we are missing.

As you can see, I’ve added the equivalent XAML markup for the view. Now, we can remove all the codes attached to the MainPage property and attach a new instance of our newly created ContentPage. Save everything and give your app a spin. You will have the same result as before.

Enough with the basics. Let’s get back to our app. We need to make a HTTP call to the API (https://swapi.co/people) to get all the characters. To do that we need to add the Microsoft HTTP Client Libraries package. We also need the Json.NET which will help us parsing raw JSON data to class objects. Search and add both of those in your project from Nuget (Select the shared project > Go to “Project” menu from top menu bar > Add Nuget Packages).

Go to the SWCharacters code behind (SWCharacters.cs) and add these lines of code given below,


public ObservableCollection Peoples { get; set; }
private HttpClient _client;

private const string PeopleDataUrl = "http://swapi.co/api/people";

public SWCharacters ()
{
    InitializeComponent ();
    Peoples = new ObservableCollection();
}

public async Task GetAllCharacters()
{
    try
    {
        _client = new HttpClient();
        var response = await _client.GetStringAsync(PeopleDataUrl);

        if (!string.IsNullOrEmpty(response))
        {
            var data = JsonConvert.DeserializeObject(response);
            foreach (var people in data.Peoples)
            {
                Peoples.Add(people);
            }
        }
    }
    catch (Exception)
    {
        await DisplayAlert("Error", "Something went wrong", "Ok");
    }
}
private async void PeopleButton_OnClicked(object sender, EventArgs e)
{
    GetAllCharacters();
}

I’ve grabbed all the characters through a HTTP ‘GET’ call to https://swapi.co/people and serialized into a ObservableCollection (an extended version of the List class in C#) of People objects using Json.Net’s JsonConvert.DeserializeObject. To know more about serialization, you can read this blog post of mine here - http://fiyazhasan.me/serialization-for-fun/. Here is the serialized object class that I was talking about. The attributes ([JsonObject("Result")], [JsonProperty("results")] are used only for giving those class and property a generic name.

People.cs


[JsonObject("Result")]
public class People
{
    public string name { get; set; }
    public string height { get; set; }
    public string mass { get; set; }
    public string hair_color { get; set; }
    public string skin_color { get; set; }
    public string eye_color { get; set; }
    public string birth_year { get; set; }
    public string gender { get; set; }
    public string homeworld { get; set; }
    public string created { get; set; }
    public string edited { get; set; }
    public string url { get; set; }
}

public class RootObject
{
    public int count { get; set; }
    public string next { get; set; }
    public object previous { get; set; }

    [JsonProperty("results")]
    public List Peoples { get; set; }
}

Now, you can ask me where I got this class from. It’s really easy to generate class objects for serialization. I went to the https://swapi.co/ and initiate a request to their https://swapi.co/people API. I copied the JSON result. Then I went to this site - http://json2csharp.com/ and pasted my JSON to get the appropriate class objects. See the images below,


I’ve created a class file in my project and paste those two classes inside that. I’m done here. You can see a PeopleButton_OnClicked event in the SWCharacters.cs. That’s because I wanted to initiate the HTTP call only when I click on that button from the UI. Here is new XAML markup for the app that creates the button.


<ContentPage.Content>
       <StackLayout VerticalOptions="Center">
              <Button x:Name="PeopleButton" Text="Get People" Clicked="PeopleButton_OnClicked"></Button>
       </StackLayout>
</ContentPage.Content>

Now if you run the project and click on the button, you will get the people data from the API. The button is only for checking whether we have a successful call to the API or not. I’ve placed some debug points and check if everything’s okay or not.


Next we will replace the button with a ListView control and attached its ItemSource property to our ObservableCollection of people. Replace your previous XAML markup with the following


<ContentPage.Content HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
    <StackLayout>
        <ListView x:Name="PeopleListView" HasUnevenRows="True">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <ViewCell.View>
                            <Grid Padding="5">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"></RowDefinition>
                                    <RowDefinition Height="Auto"></RowDefinition>
                                </Grid.RowDefinitions>

                                <Label Text="{Binding name}" FontSize="16" Grid.Row="0"></Label>
                                <Label Text="{Binding height}" Grid.Row="1"></Label>
                            </Grid>
                        </ViewCell.View>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage.Content>

So, we have a ListView instead of the button we previously had. To set the look and feel of the items added to the ListView, we have ListView.ItemTemplate. To be able to bind controls inside a ListView.ItemTemplate to appropriate list item’s properties, we have DataTemplate. ViewCell is one of the many Cell controls of Xamarain. ViewCell is used just for showing raw data, you can use EntryCell if you want textbox control as a part of your list item. I’ve placed another Grid layout inside ViewCell.View and last of all added two Labels. One of the Label is bound to the name propety of the character while the second one is bound to the height property. The new code behind looks like below,


public partial class SWCharacters : ContentPage
{

    public ObservableCollection Peoples { get; set; }
    private HttpClient _client;

    private const string PeopleDataUrl = "http://swapi.co/api/people";

    public SWCharacters ()
    {
        InitializeComponent ();
        Peoples = new ObservableCollection();
        GetAllCharacters();
    }

    public async Task GetAllCharacters()
    {
        try
        {
            _client = new HttpClient();
            var response = await _client.GetStringAsync(PeopleDataUrl);

            if (!string.IsNullOrEmpty(response))
            {
                var data = JsonConvert.DeserializeObject(response);
                foreach (var people in data.Peoples)
                {
                    Peoples.Add(people);
                }

                PeopleListView.ItemsSource = Peoples;
            }
        }
        catch (Exception)
        {
            DisplayAlert("Error", "Something went wrong", "Ok");
        }
    }
}

Since I’ve remove the button from the view, so I also deleted the event handler associated with that and initiate the HTTP request from the main constructor. Again I’ve bound the ItemSource property of our ListView to the observable collection I talked about (PeopleListView.ItemsSource = Peoples;). Now if you run this project, after a while you will get the character list with the name and height property shown on the respective labels.

What you should be concerned about?

To make this demo project simple and easy to understand I’ve done somethings against the rules. Like I called an asynchronous process from the constructor. Which is definitely bad! You can search the web and follow best practices in writing asynchronous code. Again, wrote a whole lot of code in the XAML code behind. Basically in real life you would follow pattern like MVVM which will omit this codes from the UI backend and make you app unit testable.

Downloading and running the app

Download the solution as a zip format. Unzip it and open it in your Xamarin Studio. I’ve removed all the packages .dll files from the project. So you will need to restore the packages. Just like you added a nuget package in the project, restore the packages from the option right below it.

Download the source code from here - http://1drv.ms/1LYQyri

What's next?

These are some of the basic of building apps with Xamarin Forms. Consider this as a “Hello World” program. Download the project and add some more functionalities like a detail page for a specific character, add a loading indicator to allow user to know that you are downloading stuffs from the internet. Again play with the APIs available on https://swapi.co/ and make full-fledged STAR WARS fan app. You can find a whole lot of control available for you to use here - https://developer.xamarin.com/guides/cross-platform/xamarin-forms/controls/. Follow Xamarin’s API documentation if you stuck anywhere. Have fun and I’ll see you in the next post. Bye bye geeks!