Wednesday, April 30, 2014

Setting up Sqlite on iOS, Android and Windows Phone using Xamarin

This post is about setting up SQLite.NET-PCL to achieve cross-platform usage of the database code. SQLite is a very competent little database that we access using SQLite.NET that provides you with a small OR-mapper. No more sql for you... Unless you want to of course.

This is NOT an article about how to use SQLite.

We'll take a few architectural short cuts to make the core points clearer. We'll not use any IoC or MVVM patterns. This is not a tutorial, it simply highlights the important points, gives some examples and shows of the bare bone set up.

Short version - Use the SQLite.NET PCL and it's helper packages (one for each platform) to setup and use SQLite.

You can download the solution here

Prequisits

I'm using Visual Studio 2013 with Xamarins great stuff on Windows 8 and Xamarin Studio on Mac. You need to know about Nuget.

Step 1 - Set up your projects

I started with four projects:
  • A Portable Library core called Demo.Core (profile 78)
  • A windows phone project called Demo.WP
  • A iOS project called Demo.iOS
  • An Android project called Demo.Droid (don't name it Android since it will cause namespace issues for you).

Step 2 - "Install" Sqlite

Sqlite is already installed on Android and iOS. All you need there is a wrapper called Sqlite.net. On Windows Phone you need to install the underlying Sqlite database as well.

Each platform has a different nuget package that needs to be added to each solution. The core will only reference the sqlite.net-pcl package whilst each platform will need some platform specific bits. This collection of nuget packages makes this very easy.

Core

Add the SQLite.Net PCL library from nuget (sqlite.net-pcl).

iOS

Add the SQLite.NET PCL library for iOS (SQLite.Net.Platform.XamarinIOS)

Android

Add the SQLite.NET PCL library for Android (SQLite.Net.Platform.XamarinAndroid)

Windows Phone

Add the SQLite.NET PCL library for Windows Phone 8 (SQLite.Net.Platform.WindowsPhone8)

Step 3 - Define the entities

Keeping it simple, we only create one entity called Car in the core-project. Depending on requirements you could put the entity in another assembly, but this is good for now.

using System;
using SQLite.Net.Attributes;

namespace Demo.Core
{
    public class Car
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
        public string Brand { get; set; }
        public int Milage { get; set; }
        public int NumberOfWheels { get; set; }
    }
}


Step 4 - Create the repository

The repository is going to wrap our data access to keep it isolated from the rest of the application. In a real world you would add an ICarRepository interface to enable testing and Inversion of Control.

using System;
using System.Collections.Generic;
using System.Linq;
using SQLite.Net;

namespace Demo.Core
{
    public class CarRepository
    {
        private SQLiteConnection _connection;

        public CarRepository(SQLiteConnection connection)
        {
            _connection = connection;
            _connection.CreateTable<Car>();
        }

        public void Create(Car car)
        {
            _connection.Insert(car);
            _connection.Commit();
        }

        public void Delete(Car car)
        {
            _connection.Delete(car);
            _connection.Commit();
        }

        public Car Get(int carId)
        {
            var query = from c in _connection.Table<Car>()
                        where c.Id == carId
                        select c;

            return query.FirstOrDefault ();
        }

        public List<Car> GetAll()
        {
            var query = from c in _connection.Table<Car>()
                        select c;
            return query.ToList();
        }

        public void Update(Car car)
        {
            _connection.Update(car);
            _connection.Commit();
        }
    }
}

The repository takes a SQLiteConnection in its constructor. This is the key part of getting your code platform independent. The core does not know about your clients. It only cares about a database connection to use when communicating with SQLite.

We use standard linq to interact with the database. You can also drop down to SQL-level if you're more comfortable with that.

One more point is that we need to create the table at first run. Otherwise there will be nothing to interact with. The _connection.CreateTable(); does that for you. It will check each time you create a repository to make sure that we have that table. If it already exists, nothing will happen. So don't worry that it will destroy your table.

Step 5 - Consume the stuff in the clients

Each of the platforms provide a specific connection to the repository in the core. The demo application is bare bone. We supply a button that adds another car to the repository. We then display the total car count for the user. It's pretty much just the new project template, added a label and the platform specific SQLite code to initialize.

Each project must reference the Core-project as well.

iOS

This is a view controller that holds on to a connection. The connection is created in ViewDidLoad() by passing the platform specific SQLitePlatformIOS() object to the constructor of SQLiteConnection. We also need to pass the path to the database.

using System;
using System.Collections.Generic;
using System.Drawing;
using Demo.Core;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using SQLite.Net;
using SQLite.Net.Platform.XamarinIOS;

namespace Demo.iOS
{
    public partial class Demo_iOSViewController : UIViewController
    {
        private SQLiteConnection _connection;

        public Demo_iOSViewController () : base ("Demo_iOSViewController", null)
        {
        }
            
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();
            
            // Setup the database connection
            _connection = new SQLiteConnection (new SQLitePlatformIOS(), "test.sqlite");

            // Wire events
            AddCarButton.TouchUpInside += HandleTouchUpInside;

            // Update UI
            UpdateCarCount ();
        }

        void HandleTouchUpInside (object sender, EventArgs e)
        {
            var repository = new CarRepository (_connection);

            var c = new Car ();
            repository.Create (c);

            UpdateCarCount ();
        }

        void UpdateCarCount ()
        {
            var repository = new CarRepository (_connection);

            var count = repository.GetAll ().Count;
            CarCountLabel.Text = count.ToString();
        }
    }
}

That's it... It's not pretty but it's only supposed to get you started.

Android

We follow the same pattern on android by creating a connection in OnCreate. We then hook up events and

using System;
using System.IO;
using System.Linq;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Demo.Core;
using SQLite.Net;
using SQLite.Net.Platform.XamarinAndroid;

namespace Demo.Droid
{
    [Activity (Label = "Demo.Droid", MainLauncher = true)]
    public class MainActivity : Activity
    {
        private SQLiteConnection _connection;

        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);

            // Set our view from the "main" layout resource
            SetContentView (Resource.Layout.Main);

            // Setup the database connection
            var path = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "test.sqlite");
            _connection = new SQLiteConnection (new SQLitePlatformAndroid(), path);

            // Wire up events
            Button button = FindViewById<Button> (Resource.Id.myButton);
            button.Click += AddCarButton_Click;

            // Update display
            UpdateCarCount ();
        }

        private void AddCarButton_Click(object sender, System.EventArgs e)
        {
            var repository = new CarRepository (_connection);

            var c = new Car ();
            repository.Create (c);

            UpdateCarCount ();
        }

        private void UpdateCarCount()
        {
            var repository = new CarRepository (_connection);

            var count = repository.GetAll ().Count;
            var textview = FindViewById<TextView> (Resource.Id.countTv);
            textview.Text = count.ToString ();
        }
    }
}


Android is a little more fancy pants when it comes to the location of the database file. But other than that the code is pretty much the same, except that we pass in a SQLitePlatformAndroid() object instead of the iOS version. Starting to see a pattern here?

Windows Phone

WP doesn't come with SQLite installed. This is not rocket science anymore however.

1. In Visual Studio, go to Tools -> Extensions and update and search and install SQLite for Windows Phone. When found, install.

2. Add a reference to the SQLite for Windows Phone extension under your Windows Phone projects references.


When the underlying SQLite database is installed, it's almost the same code again. We added a label and a button to the page created by the default project template.

The code for the page would look something like this.

using Demo.Core;
using Microsoft.Phone.Controls;
using SQLite.Net;
using SQLite.Net.Platform.WindowsPhone8;
using System.IO;
using System.Windows;
using Windows.Storage;

namespace Demo.WP
{
    public partial class MainPage : PhoneApplicationPage
    {
        private SQLiteConnection _connection;


        public MainPage()
        {
            InitializeComponent();

            // Setup database
            var path = Path.Combine(Path.Combine(ApplicationData.Current.LocalFolder.Path, "test.sqlite"));
            _connection = new SQLiteConnection(new SQLitePlatformWP8(), path);

            // Wire events
            AddCarButton.Click += AddCarButton_Click;
        }

        void AddCarButton_Click(object sender, RoutedEventArgs e)
        {
            var repository = new CarRepository(_connection);

            var c = new Car();
            repository.Create(c);

            UpdateCarCount();
        }

        void UpdateCarCount()
        {
            var repository = new CarRepository(_connection);
            var count = repository.GetAll().Count;
            CarCountLabel.Text = count.ToString();
        }
    }
}

And it's all the same code again.

Summary

We've created a core PCL containing a repository and a car entity. The entity should perhaps be moved into an assembly of its own depending on business rules. In case you need to share entities with backend or something like that.

We then created separate projects for three different platforms, initializing the SQLite database and references the repository in the core PCL.

Other highlights

There is also a asynchronous support. Check out the project site for examples.

As you might have noticed, even the client code kinda looks identical. This should get you thinking about moving that code to a common layer instead. And that's probably what I'm going to do in the next article by using MVVM Cross.

Resources

The project site


Fresh install of Xamarin.Android and no assemblies to reference

This is just a little observation and I hope that it might help someone.

I installed Xamarin Studio and Xamarin.Android to try it out. I usually do my Android development using Xamarin and Visual Studio, but today I figured I'd give it a try on Mac. Just to see how it works.

After installing and creating my first Android app I discovered that most of the framework assemblies couldn't be referenced.


The solution was simple however.

1. Go to Tools -> Open Android SDK Manager
2. Install the SDK Platform for any of the newer versions of Android that you'd like to target
3. Restart Xamarin studio

You might also want to check out the Target Framework setting under the project options.

Friday, April 25, 2014

A build server for Mac

I would like to see a build server for Mac to enable building iOS apps from multiple clients and remoting of the iOS simulator. 

Is it technically possible? Is it simply a licence problem. That is, Apple being 4 years old about it?

Do I need to write one myself... :)

EDIT: confirmed that xamarin ha "no plans" to support this quoting Miquel himself. 

It's still the licence fee and the need for one Mac per developer that is the hardest part for me as a consultant when I try to sell app development using xamarin.

Thursday, April 24, 2014

Stupid space error in Xamarin studio (rant goes on)

Short version

When cloning a git repository with a space (%20) in the name. Rename the directory after cloning. The build engine will not find the project file otherwise.

Verbose version

I sat down to clone a git repository that I have hosted in visual studio online.

The project name was something like "Nice thingy" so the repository address looked something like below.

https://something.visualstudio.com/DefaultCollection/_git/Nice%20thingy

No worries, I just copied the url, started a bash and typed

git clone https://something.visualstudio.com/DefaultCollection/_git/Nice%20thingy

All went well and the code was cloned. But, I doesn't build. All I get is "Build failed. See the build log for details.".  First off, I couldn't find the build log.

After some google-fuu I stumbled upon a tip to check the Help->Open Log Directory and checked out the logs in there. It seems that the %20 confuses the build engine and it simply doesn't find the project to build.

So rename the folder and the project builds!

Also on my todo-list, clean the mac screen. My son played minecraft and had a donut at the same time

Resources

Monday, April 21, 2014

The outline of a mobile architecture using Xamarin

This post is going to be a little abstract. It's going to sum up about two years of best practices in mobile development using Xamarins products. Please feel free to criticise! :)

The overview

A common misconception about Xamarin (I use the name Xamarin to represent both Xamarin.Ios and Xamarin.Android) is that it's UI cross platform. It is not and that's a good thing. The rationalization for this is that if you use a UI cross platform tool, it is only going to be as good as the common denominator for all platforms you choose to include. This makes for a substandard app/product. You can also find the same reasoning at Xamarins own website.

This leads you to a setup that looks something like this.





In most of my projects I communicate to a JSON enabled REST-backend.

Inversion of control

I got to mention this early. This is a must have. A lot of code in core is dependent on platform specific implementations, such as Storage and Networking. We inject these platform specific bits of code using IoC. Use your favorite flavour. I, however, recommend Autofac since it plays nicely with all mobile platforms.

A note worth making is that we don't include any IoC bits in the core. It's all in the UI layer.

JSON serializer

If you're having a JSON/REST backend you need to serialize and deserialize objects. There are a lot of serializers out there. Personally I use Newtonsoft.json (also called json.net). In fact, I'm so hooked on it that I hardcode it into my networking and storage more than I should.

Everything has an ID

I always assume that each object/resource has an ID and that it is available at a unique URI. After all that is what REST is all about. The ID is really the unique Uri.

For example, a user object might have a database ID of 42. The User object exposed by REST has the unique id of http://www.mysite.com/users/42. When I cache and/or store objects locally I use either a shorthand (/users/42) or the entire URI as a key. There is also an advanced version of this where I store a timestamp and use it for concurrency and caching.

Entities/Models

This is often a PCL that I share between the projects. It doesn't have to be a binary/IL share really. I usually just do that since I'm lazy.

If you feel like creating C# objects from json, try out http://json2csharp.com/. Just paste your JSON and get a C# POCO back.

The core

This is a Portable Class Library (PCL). Try to fit all of your networking, storage and business logic into this library. The folder structure and naming is of course a matter of personal option and can be exchanged for anything you would like.

The boxes on the left aren't changed that often. I've got my base code that I might tweak between projects due to specific requirements. The boxes on the right are the ones that are very project specific.


Storage

Stores stuff locally on the mobile device. Often objects serialized as JSON. I like to keep storage as simple as possible, often just wrapped in an interface like this.

IKeyValueStorage
+ void Set(string key, string value)
+ string Get(string key)

The actual implementation differs on each UI platform.

Based on the IKeyValueStorage I usually create an IObjectStorage that takes care of the serialization of objects.

IObjectStorage
+ void Set(string key, object item)
+ T Get<T>(key);

The implementation would look something like this.

public class ObjectStorage : IObjectStorage
{
  private IKeyValueStorage _storage;
  public ObjectStorage(IKeyValueStorage storage)
  {
     _storage = storage;
   }

   public void Set(string key, object item)
   {
      _storage.Set(key, JsonConvert.SerializeObject(item));
   }

   public T Get<T>(string key)
   {
      return JsonConvert.DeserializeObject<T>(_storage.Get(key));
   }
}

You would need add error handling, logging and all that other stuff of course. The important part here is that we can implement the ObjectStorage in core since the platform specific parts are wrapped inside the implementations of IKeyValueStorage.

There is also one more kind of storage that I usually set up and that is the ISettings storage. It defines all the settings I need for a project. It is very project specific. This example stores a BaseUri that the RestClient needs.

public interface ISettings
{
   public string BaseUri { get; set; }
}

public class Settings : ISettings
{
   private IKeyValueStorage _storage;
   public Settings(IKeyValueStorage storage)
   {
      _storage = storage;
   }

   public string BaseUri
   {
      get { return _storage.Get("BaseUri"); }
      set { _storage.Set("BaseUri", value ); }
   }
}

And then add default handling and stuff like that. Set up the Settings-object in the IoC bootstrapper. Remember to initialize it at first run to ensure that we have default values or add handling of default values.

Networking

I often only have a couple of classes here. The main one being the RestClient along with its interface IRestClient. It's an async enabled wrapper built on top of HttpClient and extended with ModernHttpClient to gain some performance and stability, mostly on Android. I have a separate post about that here.

The rest client is built as generic as possible but do give you an option to use entities through generics.

var obj = _restClient.Get<MyObject>(_theUri);

The RestClient handles both what I call short URIs and complete URIs. The short version needs a base URI that the RestClient gets from the Settings.

To make the RestClient aware of the settings class we simply define it in the constructor as below. This is only a small part of a RestClient.

public class RestClient
{
   public RestClient(HttpMessageHandler handler, ISettings settings)
   {
      ... store local copies
   }

   public async Get<T>(string uri)
   {
      if(!uri.BeginsWith("http"))
      {
          uri = _settings.BaseUri + uri;
      }

      using(var client = new HttpClient(_handler))
      {
          var content = await client.GetStringAsync(uri));
          return JsonConvert.DeserializeObject<T>(content);
      }
   }
}

But wait, what is the HttpMessageHandler? Since we're using the ModernHttpClient we need to provide a platform specific HttpMessageHandler. You just have to set that up in the IoC bootstrapper for each platform to ensure that each platform gets the correct handler. 

Repositories

In my world I use repositores to wrap access to a single set of entites such as users. My repositories also handles caching if needed. The code below is pseudo code to make the point.

public class UserRepository
{
   public UserRepository(IRestClient restClient, IObjectStorage storage)
   {
      // store to local fields
   }

   public User FindById(int id)
   {
      string key = String.Format("Users/{0}", id);
     
      try
      {
         var user = _restClient.Get<User>(key);
         _storage.Set(key, user);
         return user;
      }
      catch(NetworkUnavailableException ex)
      {
         return _storage.Get(key);
      }
   }
}

Services

Sometimes you need to access multiple repositories and other resources. A service is what coordinates that into a single operation. A service can be used to assemble a viewmodel to return to the UI layer.

To sum up

  • Inversion of control is vital to keep a multiplatform project going. Once you wrap your head around it it does really simplify the development process.
  • We didn't touch testing, but with IoC, it's simple... Or at least doable...
  • Single Responsibility Principal is important, but don't go bananas. Sometimes shortcuts really saves a lot of time. I always hardcode the Json.net serializer since I know that I'm not going to exchange it for something else. It's not worth the extra abstractation layer in my book.
  • There is no one-size-fits-all solution

Thursday, April 17, 2014

Xamarin and Build 2014

I headed of to Build 2014 in San Fransisco with my mind pretty much set at hearing the announcement that Microsoft would buy Xamarin.

That did not happen...

At first I was kind of disappointed. But after a while I kinda changed opinion. What would happen with Xamarin if they were to be aquired. First of, the free spirit of Miguel de Icaza would not be so free anymore. And Xamarin is still to young to be chained down and having to ask Microsoft what direction to take.

Xamarin is growing fast, mostly due to venture capital I'd guess and they'll have to use this cash smart to get a firm grip of the developer base. I think they're on the right path. Suddenly everyone around me is talking about Xamarin and I'm not really used to that. It's usually me trying to push Xamarin onto developers, now they are pulling it out of me. That's a good change!

Still there are a few things on my list to make good better.

  • Lower entry level pricing. $1998 is to much cash for the small business. The cost for the license is still the part that I spend most of my time trying to justify.
  • A designer for iOS in Visual Studio
  • A build server for iOS, not the 1-1 relationship
Other than that, it's all good! :)




Xamarin.Geolocation.Geolocator async never returns

Sometimes I wish APIs would work the way you expect them to. Yesterday, I spent a couple of hours trying to figure out why the following code just hangs.

var loc = new Geolocator(this) { DesiredAccuracy = 50 }; 
var pos = await loc.GetPositionAsync(timeout: 4000);

The await-call never returns. From the look of it, I would expect it to return after 4 seconds or at least throw an exception.

So I posted a question on the Xamarin Android forum and as usual got some great feedback. The answer was simple, restart your device. There seems to be a bug deeper down in android that is well-known.

This is terrible, that means that I cannot rely on the async call to ever return. I guess the only way out of this is to wrap this in an API of my own that handles these hangs and informs the user to restart their device.

Sometimes I miss iOS... :)

Oh, and here's the original question on the forum.

Wednesday, April 16, 2014

HttpClient is unstable using Xamarin.Android

This post is about stabilizing the HttpClient. There is really no new information in this post of my behalf. It's more a summary of what's out there.

Short version, if HttpClient hangs for you on android, use ModernHttpClient, also available in the Xamarin Component Store for free.

To get async support for the HttpClient you need to install the Microsoft HTTP client libraries. Current version is 2.2.18 and it's available from Nuget under the id Microsoft.Net.Http.

This will give you a nice way of downloading stuff async.

var content = await client.GetStringAsync(relativeUrl);

However, at the current date, the HttpClient's async support for Xamarin.Android is unstable. I have not encountered any problems for iOS but for Android it often hangs and times out giving you a TaskCancelled-exception.

To be fair to Microsoft, there is no written support for Android or iOS. Hopefully they'll make a more stable version in the future.

Usually you'll wrap all this in a container and all that fancy stuff, but for the sake of simplicity I keep the code clean.

The solution to your problem is...

Use ModernHttpClient

The solution is to install the ModernHttpClient component from Xamarin Component Store and initiate the HttpClient using a better HttpMessageHandler.

For android it looks like this

var client = new HttpClient(new OkHttpNetworkHandler());

Always dispose your client

This is a very important thing. Always dispose the client on Android or it might lock up your entire http stack. (not verified, only experienced). The simplest way of doing so is to wrap it in a using statement.

using (var client = new HttpClient(new OkHttpNetworkHandler()))
{
    // Setup the client
    ....

    // Make the call
    var content = await client.GetStringAsync(theUrl);
}

Resources



interface of Duck is a Duck


Without giving it much though, I would like to see an interface<T> extension that effectively creates an interface of a class on the fly. Why would you do that? Just extract the interface of a class or inherit from it? Well, works fine, unless you add something to the original class.

Consider the following code:

 public class Duck
{
public int Age { get; set;}
public void Quack()
{
...
}
}

public class MockDuck : interface<Duck>
{
public int Age { get; set;}
public void Quack()
{
...
}
}

The Duck class is the original class. To create a mock duck I would have to inherit from it or extract an interface. The problem with inheritance is that if I add a method or a property to the base Duck class, the implementation would leak into my MockDuck. As intended in inheritance, but I'm not after inheritance. A simular problem occurs when you extract an interface. The interface would not be in sync with the original implementation. Also my duck source/binary might be outside of my control so I couldn't add the interface to it.


  • Anywhere any code needs a Duck, passing a class implementing interface<Duck> would be OK.
  • All methods and properties of the source class must be implemented


So what are the problems with this approach? Probably a lot of things... This is just an idea! :)