A Journey of Hunting Memory Leaks in Xamarin

My client was reporting performance issues with an existing app that was developed internally, and I had to find the problems. So, here is my journey on finding the issues and resolving them. The resolution was a reduction of the memory usage to 1/4 of what it was and usage was stabilised to this level (1/4). I am hopeful that this blog post can help you too in refining your app and pro-actively resolving any performance issues.

Capturing Telemetry Data

The first step in optimisation must be setting your benchmark, and in order to do that, we need to know where we stand. Thus, I set up an integration with Azure Application Insights to capture all memory warnings, errors, warnings, and battery level monitoring. For details on integrating with Azure App Insights, you can read more in my previous post here. The relevant part for us in this post is capturing memory warnings. There are three ways to capture memory warnings in iOS as I listed them on StackOverflow, we will stick with AppDelegate, as this is applicable to both traditional Xamarin and Xamarin Forms.


public partial class AppDelegate
{
	...
	public override void ReceiveMemoryWarning (UIApplication application)
	{
		// this (MemoryWarningsHandler) is a helper that I created 
		// to capture more info when a memory warning is raised. Things like (nav Stack, running time, etc)
		MemoryWarningsHandler.Record ();
	}
}


Always, Always, listen to these memory warning notifications from the OS, even if you are not actioning them now

In Android, we could also do the same using Application.OnLowMemory (See Android docos) as below:


public class MyApp : Application
{
	...
	public void OnLowMemory ()
	{
		MemoryWarningsHandler.Record ();
	}
}

Once we received and captured these memory warnings on Azure App Insights, we will then know that we have a memory warning, and whoever is looking at the report will keep bugging you until you fix this problem, if the app was not crashing due to low memory 🙂

Investigating Low Memory Issues

Once we identified that there is a problem with Memory, we need to figure out where the problem is occuring. To do this, we could use Xamarin Profiler. At the time of this writing (March 2016), Xamarin Profiler is still in preview and has many known bugs, but it still provides a good starting point.
We can monitor a number of performance indicators using Xamarin Profiler including:

  • Memory Allocation
  • Dependency Cycles
  • CPU Time
  • Few more aspects of the app Performance

For this post, we are interested in memory leaks, so we can start a profiler session, by choosing Memory Allocation when the profiler starts. More info on starting a profiler session can be found on Xamarin website.

In previous versions of Xamarin Profiler, I was able to view the call tree which gave me a great view on where the issue exactly was. This was based on call stacks and it tells you exactly how much memory is used in every entity/method. Unfortunately, in this version, I could not get this to show me this detailed view, but I was able to capture few memory snapshots and monitor the growth of used memory. My diagram looked like this:

Memory Usage before optimisation

Memory Usage before optimisation

This made it very clear that we have a problem in our memory consumption, the memory usage was racking up to 600 MB in some scenarios. The important part was now finding where the problem is.

Identify Problematic Code

In the absence of the call tree view, I started using the app and monitoring the memory usage. I established that it was a particular Page (Xamarin Forms Page) that was causing the memory usage to grow rapidly. As you can see at the start of the application, things were quite alright. Then, I focused my attention to that page. Looking at the page, it seemed harmless. It’s only a screen-saver-like page for a kiosk app. I could see a couple of small problems, but these are minor and would not cause the memory to grow that quickly. The code of this screen saver page can be seen below:

    public class ScreenSaverPage : ContentPage
    {
        private readonly List<string> _imageSourceList;
        private readonly List<FileImageSource> _cacheImageSource = new List<FileImageSource>();
 
        private readonly Image _screenSaver;
        private int _currentImageIndex;
        private readonly CancellationTokenSource _cts = new CancellationTokenSource();

        public ScreenSaverPage()
        {
            _imageSourceList = new List<string> { "Screensaver1.png", "Screensaver2.png", "Screensaver3.png", "Screensaver4.png" };
            
            // Caching it to Reduce loading from File all the time
            foreach (string fileName in _imageSourceList)
                _cacheImageSource.Add(new FileImageSource {File = fileName});

            _screenSaver = new Image
            {
                HorizontalOptions = LayoutOptions.FillAndExpand,
                VerticalOptions = LayoutOptions.FillAndExpand,
                Aspect = Aspect.AspectFill,
                Source = _cacheImageSource.FirstOrDefault()
            };
            var tapGestureRecognizer = new TapGestureRecognizer();
            tapGestureRecognizer.Tapped += async (s, e) =>
            {
                _cts.Cancel();
                await Task.Run(async () => await App.ResetInactivity(typeof (BaseViewModel)));
            };
            
            Content = _screenSaver;
            _screenSaver.GestureRecognizers.Add(tapGestureRecognizer);
            // Configure the OnAppearing to kick off the ScreenSaver
            Appearing += async (sender, args) =>
            {
                try
                {
                    await Task.Run(async () =>
                           {
                               while (true)
                               {
                                   if (_cts.IsCancellationRequested)
                                   {
					App.Logger.LogInfo("CANCELLED - In the Loop");
                                       break;
                                   }

                                   await Task.Delay(5000, _cts.Token).ContinueWith(async t =>
                                   {
                                       try
                                       {
                                           if (_cts.IsCancellationRequested)
                                           {
						App.Logger.LogInfo("CANCELLED - In the Action");
                                           }
                                           else
                                           {
                                               // this is the unnecessary Task
                                               await Task.Run(() =>
                                               {
                                                   _currentImageIndex = _currentImageIndex < _imageSourceList.Count 1 ? _currentImageIndex + 1 : 0;
                                                   Device.BeginInvokeOnMainThread(
                                                   () =>
                                                   {
                                                       _screenSaver.Source = _cacheImageSource[_currentImageIndex];
                                                    });
                                               });
                                           }
                                       }
                                       catch (Exception ex)
                                       {
					   App.Logger.Log(ex);
                                           throw;
                                       }
                                   }, _cts.Token);
                               }
                           });
                }
                catch (OperationCanceledException e)
                {
		    App.Logger.Log(e);
                    Device.BeginInvokeOnMainThread(async () =>
                    {
                        await Navigation.PopModalAsync();
                    });
                }
            };
        }
    }

Now, please do not ask me why it’s done this way, because this is just what I have been given from the existing app. The three problems that stood out to me were:

  1. Wiring OnAppearing event without unsubscribing.
  2. GestureRecogniser is added but not removed.
  3. A Task was being created every 5 sec unnecessarily.

However, these all were small compared to the main problem, and even removing all these together did not help in reducing the memory usage. so I switched off the part that swaps the screensaver images.


_screenSaver.Source = _cacheImageSource[_currentImageIndex];

At first, this looked harmless to me, and we were caching the FileImaeSource in a list, so we were not loading the images every time, we only loading them once and only swapping the source on the background image. However, it appeared that this was the root cause. Commenting this line out made the memory usage stay stable below the 200 MB mark, which was great news for me :).

Make sure that you have your benchmark before any optimisations, otherwise you would not know the impact of your changes.

Developing a Solution

To avoid swapping the image source, which by the way, I think it is a Xamarin Forms problem, but I will chase that separately, I started thinking of creating multiple static background images, and only toggle their visiblity. This meant that I would have 4 images loaded and all bound to fill the screen, but I only show (make visibile) one of them at a time. The Page code changed to be like this:


public class ScreenSaverPage : ContentPage
{
        private readonly List<string> _imageSourceList = new List<string> { "Screensaver1.png", "Screensaver2.png", "Screensaver3.png", "Screensaver4.png" };
        private readonly List<Image> _backgroundImages = new List<Image>();
	private  RelativeLayout _relativeLayout;
        private int _currentImageIndex;
        private readonly CancellationTokenSource _cts = new CancellationTokenSource();

        public ScreenSaverPage()
        {
            _relativeLayout = new RelativeLayout { HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand };

		LoadImages (_relativeLayout);
		_backgroundImages [0].IsVisible = true;

         	var tapGestureRecognizer = new TapGestureRecognizer();
         	tapGestureRecognizer.Tapped += async (s, e) =>
            	{
                	_cts.Cancel();
                	await Task.Run(async () => await App.ResetInactivity(typeof (BaseViewModel)));
            	};
            
		Content = _relativeLayout;
		_relativeLayout.GestureRecognizers.Add(tapGestureRecognizer);
        }

	protected async override void OnAppearing ()
	{
		base.OnAppearing ();
		try
		{
			await Task.Run(async () =>
			{
				while (true)
				{
					if (_cts.IsCancellationRequested)
					{
						App.Logger.LogInfo("CANCELLED - In the Loop");
						break;
					}
					await Task.Delay(5000, _cts.Token).ContinueWith(async t =>
					{
						try
						{
							if (_cts.IsCancellationRequested)
							{
								App.Logger.LogInfo("CANCELLED - In the Action");
							}
							else
							{
								_currentImageIndex = (_currentImageIndex < _imageSourceList.Count -1) ? _currentImageIndex +1 : 0;
								Device.BeginInvokeOnMainThread(
								() =>
								{
									SetBackgroundVisibility(_currentImageIndex);
								});
							}
						}
						catch (Exception ex)
						{
							App.Logger.Log(ex);
							throw;
						}
					}, _cts.Token);
				}
			});
		}
		catch (OperationCanceledException e)
		{
			App.Logger.Log(e);
			Device.BeginInvokeOnMainThread(async () =>
			{
				await Navigation.PopModalAsync();
			});
		}
	}

	private  void LoadImages (RelativeLayout layout)
	{
		foreach (string fileName in _imageSourceList) 
		{
			var image = CreateImageView (new FileImageSource { File = fileName });
			layout.Children.Add (image, Constraint.Constant (0), Constraint.Constant (0), Constraint.RelativeToParent (parent => parent.Width), Constraint.RelativeToParent (parent => parent.Height));
			_backgroundImages.Add (image);
		}
	}

	void SetBackgroundVisibility (int currentImageIndex)
	{
		for (int i = 0; i < _backgroundImages.Count; i++) 
		{
			_backgroundImages [i].IsVisible = i == currentImageIndex;
		}
	}

	private static Image CreateImageView (FileImageSource source)
	{
		return new Image
		{
			HorizontalOptions = LayoutOptions.FillAndExpand,
			VerticalOptions = LayoutOptions.FillAndExpand,
			Aspect = Aspect.AspectFill,
			Source = source, 
			IsVisible = false
		};
	}
}

You would agree that this is a big improvement on what we had originally, and it shows clearly on the Xamarin Profiler when we run the app with this new change. The memory plot on the Xamarin profiler was looking like this:

Memory usage after optimisation

Memory usage after optimisation

This is a great reduction, and it is less than one third of what the app was using before (~ 600 MB), but I was still thinking that it needs to be optimised further.

Can We Do Better?

The graph above was showing me that the memory usage was still going up, not by much but still growing. Also, when I switch between screens/pages, I noticed that the screensaver page was taking lots of memory to start with (~ 50 MB), which is to create the images and FileSourceImage objects. However, I noticed that when we move away from this page (screen saver), these entities are not being cleared quickly enough by the GC. Thus, I added the following:


public partial class ScreenSaverPage : ContentPage
{
	...
	protected override void OnDisappearing ()
	{
		base.OnDisappearing ();

		PrepareForDispose ();
	}

	void PrepareForDispose ()
	{
		foreach (var image in _backgroundImages) 
		{
			image.Source = null;
		}

		_backgroundImages.Clear();
		_relativeLayout.GestureRecognizers.RemoveAt (0);
		_relativeLayout = null;
		_cts.Dispose ();
		Content = null;
	}
}

This helped dispose of the images and the gesture recogniser quickly enough and helped me keep the memory usage at around 130 – 160 Mb, which is a great result considering that we started with 600 MB. The other pleasing part is that memory usage was very stable and no major peak were found. It fluctuates slightly when you move between pages, which is perfectly normal but it goes back to a steady level around 130 – 160 MB.

I hope you find this useful and please do check your Xamarin apps before you release or whenever you get the time, as these things are hard to see but they could bite you when you go to prod 🙂

Handling Complex Object Persistence and Messaging on Mobile

Data persistence and messaging is a very common task that you almost certainly need in your apps. Mobile platforms have come a long way in supporting data persistence mostly through the SQLite engine which has become the standard on all mobile platforms. However, SQLite is (as it’s name suggests) a lightweight engine and does not offer as many features as a full RDBMS.

This should not be a problem on a mobile device where persisting data is intended mostly for caching until the data reaches its ultimate destination on a backend server. With this in mind, how do we go about persisting complex objects on a mobile platform? How do we handle complex objects messaging? This is exactly what I will discuss in this blog post. This is not an introduction on how to use an ORM (Object Relational Mapping) to store objects in a database, it is rather how to handle the complex relationships between a data object and its children or siblings when storing or messaging that piece of data.

SQLite.NET PCL

I have been developing for mobile platforms for quite sometime and I have been really enjoying the use of SQLite.Net PCL. This is a very simple ORM built on top of SQLite.NET that adds support for PCLs (Portable Class Library). This library has made it very easy to store data in the database on a mobile device and it gives you a unified API on all platforms to do all data persistence related tasks. If you have not used this before, I would highly encourage you to have a look at it, and this blog post will assume the use of this framework for storing data locally.

Versioning

If your mobile application is intended for building a to-do list, then it might not be a major issue if you loose a single entry here or there, or you simply resolve conflicting items by taking the latest one. I am saying this and knowing that you might loose some customers if you take this approach :).

However, what if your mobile app was being used for emergency management, or used by health practitioners? This makes it a requirement to pre-define the logic for how items are stored, and how conflicts are resolved, and you are required to always keep all bits of information on all devices. I had a similar requirement where I needed to maintain the versioning of all items and define how a conflict will be resolved. Thus, I decided to use versioning for my data objects. This design incorporates the following decisions:

  1. Any change will be applied to the data objects as a change log.
  2. Change logs are globally and uniquely identifiable via unique IDs.
  3. Data objects will have a VERSION attribute, which is unique. This VERSION attribute will refer to the most recent Change Log Id.
  4. Each data object will have a list of Change Logs in an ordered list. The ordering of these logs represents the timeline of when these change logs were applied.
  5. For the sake of simplicity, we will assume that a data object has a list of properties/attributes that will be represented as table of key/value pairs.
  6. Other decisions/assumptions of the design will be ignored for the sake of this blog post. Such decision could include storing the type of change logs (changes created by a user, a result of data merge, etc), storing other security (authentication/authorisation) data on each data item, storing other metadata on each data object such as who changed what and when.

With that in mind, our data object diagram will look something like the following:

UML Diagram of our basic Item (versioning) design

UML Diagram of our basic Item (versioning) design

Enforcing Version-based Changes

Now that we have put together our basic design, we need to implement it in a way that is safe for a team of developers to work on. We cannot assume asking team members “hey, can you please use this method when you try to apply some changes? because it is necessary”, think that would work? :). I know you’re probably thinking this is absurd, but I have seen this sort of behaviour in some teams. If they do not say it this way, they would rely on comments in the code or other wiki/documentation to enforce the design logic. My approach is to make it fool-proof and to let the design document itself. I should not be required to explain this for people. Developers (my team members) should be able to use this without worrying about the internal implementation. So to do that we need the following:

1. Read Only Properties

To ensure that we are not going to change any property of our data object without using change logs, properties need to be read-only. This ensures that we cannot create a new version of the item without either using the applyChangeLog(log) method or using a constructor.

2. Fully defined constructor(s)

We cannot provide a constructor that would allow the consumer of our framework to create/instantiate a data object without specifying all its attributes. Therefore, our constructors should define all properties of an object at creation time.

3. Easy composition

Our framework needs to have an easy way to construct objects from a serialised version or from another version of the item. This is necessary when storing these data objects to the database or when trying to message them over the network.

With all that out of the way, our basic object implementation could look something like this:

  // our change log first
  public class ChangeLog 
  {
     public string Id {get;set;}
     public int Order {get;set;}
     public string CreatedBy {get;set;}
     public ChangeLogType Type {get;set;}
     public DateTime CreatedOn {get;set;}
     public string ParentId { get; set; }
     public Dictionary<string, object> ChangingAttributes {get;set;}
   }

   public class RegisterItem : ModelBase
   {
     public RegisterItem (string id, string name) 
             : this(id, name, string.Empty, new Dictionary<string,object>(), new List<ChangeLog>())
     {
     }

     public RegisterItem (string id, string name, 
                          string version, Dictionary<string, object> attributes, List<ChangeLog> changeLogs)
     {
        Id = id;
        name = name;
        _version = version;
        _attributes = attributes;
        _changeLogs = changeLogs;
     }

     // This is needed for the internal use (serialisation/De-serialisation, and db storage).
     // Bcoz this ctor is Obsolete, it will through a warning and the warn will be escalated to an error if used.     
     [Obsolete("This ctor is only for the deserialiser and the db layer. Use other ctor with full params")]
     public RegisterItem ()
     {			
     }

     public string Version { get {return _version;} private set { _version = value;}  }
     private string _version {get; set;}

     public string Name { get{ return _name; } private set { _name = value;}  }
     private string _name { get; set; }

     [Ignore]
     public List<ChangeLog> ChangeLogs { get { return _changeLogs; } private set { _changeLogs = value;}  }
     private List<ChangeLog> _changeLogs { get; set; }

     [Ignore]
     public Dictionary<string, object> Attributes {get{return _attributes; } private set { _attributes = value;}}
     private Dictionary<string, object> _attributes { get; set;}
   }

So far so good!

Thus far we have implemented our data objects with its basic versioning its children objects. Now the question is how do we store this in the database and how to serialise/deserialise the object to send it over the network. This is actually the second tricky part 🙂 because if you have worked with SQLite.Net before you would know that it is designed to enable mobile developers to store simple objects and basic typed attributes to the database. For our scenario, we have complex objects with children objects and other complex attributes (Dictionary).

Storing in the SQLite database

Our database will store basic information about the data objects (name, id, version) along with a full copy of the object that is serialised to a basic type like string (or could be a binary if you like). To make this smooth and simple to our consumers (developers who use this api), we added a property to the data object that is called AsJson. This property will serialise and store the full copy of the object when the object is stored to the database, and when the object is constructed from its basic attributes, it will populate the other properties (like children objects and other complex properties (ie Dictionary). A simple implementation of this property could be something like this:


[JsonIgnore]
public string AsJson 
{
  get
  {
     var json = MySerialiser.ToJson(this);
     return json;
  } 
  set
  {
     var json = value;
     if (!string.IsNullOrEmpty(json))
     {
         var originalObject = MySerialiser.LoadFromJson<RegisterItem>(json);
         if (originalObject != null)
         {
            //We could use something like AutoMapper here
            _changeLogs = originalObject.ChangeLogs;
            _attributes = originalObject.Attributes;
         }
      }									
  }
}

As you can see the property itself (AsJson) is ignored when serialising to JSON. Plus, our developers would not need to do anything when storing to or pulling from the database. Our AsJson property would do the work and get our items saved/constructed to/from the database. Also, notice how we had the [Ignore] attribute on our complex children objects. This belongs to our ORM (SQLite.Net) which will be understood as no need to store these objects to the database.

Messaging

A couple of months ago, I gave a talk at DDD Melbourne regarding messaging in Peer-2-Peer scenarios on mobile devices, you can find the slides deck here. And for this exact project, I needed to be able to serialise/deserialise my data object to send them over my P2P connections. This has been made much easier by the property that we discussed earlier which is called AsJson. The only tricky part is that when serialising, you need to modify the default settings of your JSON serialiser as it needs to be able to serialise/deserialise private properties of the data objects. Assuming that we use something like Newtowonsoft.Json, our serialiser will be something like this:

   var resolver = new PrivateSetterContractResolver();
   var settings = new JsonSerializerSettings{ ContractResolver = resolver };
   var obj = JsonConvert.DeserializeObject<T>(input, settings);

And that’s it. Hope you find this useful and you have picked a few ideas on how to handle storing and messaging of complex data objects on the mobile. If you have a question, comments, or maybe a suggestion to do things in a different/better way, I would love to hear from you, so get in touch.

Sharing HTTP sessions between WebView requests and HttpClient on Windows Phone

Introduction

I have been working on a hybrid mobile application that requires displaying/containing a few mobile apps in a WebView control. In the background, some HTTP requests need to go through to collect data and do further processing. We need to maintain the same session in all of the web requests going through the mobile app. This means all web (HTTP) requests originated by the Webview as well as our background (HttpClient) requests need to share cookies, cache, etc. So how can we achieve this?

System.Net.Http.HttpClient

HttpClient has become the go-to class for all things HTTP, especially with the support of HttpClient in PCLs (Portable Class Library), who can resist it? So my first thought when I considered this requirement was to use HttpClient with a HttpClientHandler, preserve the session cookies, and share them with the WebView. I started my initial research, and I found that somebody has done exactly that, you can find it here. This gave me some more confidence for a successful solution.

This first approach would mean using HttpClient (along with a HttpClientHandler) to hold cookies and share them with the WebView. However, this would be error-prone because I will need to continuously monitor both cookies and update the other group of requests. Plus, sharing the data cache between the WebView and HttpClient would still be an issue that I was not sure how to address.

Windows.Web.HttpClient

Before going further, I thought I would look for an alternative, and I found Windows.Web.HttpClient. This one seemed very similar to System.Net.Http.HttpClient, but the implementation is quite different, regardless of the exact matching of the name :). I found this video (below) from Microsoft’s //Build conference that refers to this different implementation of HttpClient for Windows specific development.

Five Great Reasons to Use the New HttpClient API to Connect to Web Services

Five Great Reasons to Use the New HttpClient API to Connect to Web Services

Apparently the Windows implementation of HttpClient gives you the ability customise all aspects your HTTP requests. The video above lists the following five reasons why you should use Windows.Web.HttpClient:

  1. Shared Cookies, Cache, and Credentials
  2. Strongly Typed headers => fewer bugs
  3. Access to Cookies and Shared Cookies
  4. Control over Cache and Shared Cache
  5. Inject your code modules into the processing pipe-line => cleaner integration.

When I read the first statement above, I really thought that this is too good to be true :), just exactly what I am looking for. So I decided to give it a go. As you can see some of the features listed for this HttpClient (Windows implementation) are similar to what we have in the System.Net world, but this gives us extra capabilities.

HttpClientHandlers vs HttpBaseProtocolFilter

It is worth mentioning that Windows.Web library does not have HttpClientHandlers that we are familiar with in System.Net, instead it gives you the ability do more with HttpBaseProtocolFilter, and this is a key point. HttpBaseProtocolFilter enables developers to customise/manipulate HTTP requests (headers, cookies, cache, etc) and the changes will be applied across the board in your application. This applies whether you are making a HTTP request programmatically using HttpClient or via the user interface (using a WebView for instance).

Code Time

  // creating the filter
  var myFilter = new HttpBaseProtocolFilter();
  myFilter.AllowAutoRedirect = true;
  myFilter.CacheControl.ReadBehavior = HttpCacheReadBehavior.Default;
  myFilter.CacheControl.WriteBehavior = HttpCacheWriteBehavior.Default;

  // get a reference to the cookieManager (this applies to all requests)
  var cookieManager = myFilter.CookieManager;

  // make the httpRequest
  using (var client = new HttpClient()) 
  {
     HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "your-url-address"); 
     
     // add any request-specific headers here
     // more code been omitted

     var result = await client.SendRequestAsync(request);
     result.EnsureSuccessStatusCode();

     var content = await result.Content.ReadAsStringAsync();

     // now we can do whatever we need with the html content we got here 🙂
     // Debug.WriteLine(content);
  }

  // assuming that the previous request created a session (set cookies, cached some data, etc)
  // subsequent requests in the webview will share this data
  myWebView.Navigate(new Uri("your-url-address"));
  

Hopefully this short code snippet gives you a good idea of what you can do with Windows Implementation of HttpClient. Notice that myWebView automatically shares the CookieManager implicitly.

Other Apps?

One might ask about how will this impact other apps? It doesn’t. The Windows.Web library was designed to work across all requests in one app. Therefore, you do not need to be concerned about impacting other apps or leaking your data to other external requests.

Conclusions

Someone wise once said “with great power, comes great responsibility”. This should be remembered when using HttpBaseProtocolFilter with your HTTP requests as it can (as mentioned above) impact all your subsequent requests. Hope you find this useful and I would love to hear your comments and feedback.

References:

Reachability.Net: A unified API for reachability (network connectivity) on Xamarin Android and iOS

Do you need to check for an active internet connection in your mobile app? Don’t we all do it often and on many platforms (and for almost all apps)? I found myself implementing it on iOS and Android and then pulling my implementation to almost all the mobile apps that I write. This is not efficient, and can be done better, right? 🙂

As a result I have created a library called Reachabiliy.Net which can be found as a nuget package for everything related to network connectivity. The library is open source and is hosted on Github. Currently, the solution only supports Xamarin iOS and Xamarin Android. I might add Windows Phone support and .NET 4.5 depending on the feedback I get. You will find examples listed on the main repository page.

I have included some sample code in the Github repostiroy.

The library provides a unified API across all platforms. The implementation of the library is based on the Xamarin Recipe on iOS, which can be found Xamarin’s Recipe Site. This is a good implementation and well tested.

On Android, the Xamarin Android recipe, is not really great and is based on the examples from the Android SDK docs, but it only checks whether the device is capable of connecting to the internet (or to wifi) or not and does not indicate the current connection status.

Therefore, I combined the Xamarin Android recipe with another check for connectivity to ensure correct results. More details on Reachability on Android can be found on this StackOverflow discussion.

OK, that’s all for me and I hope you enjoy using the library. Feel free to log any issues or feature requests on Github and I would love to hear your feedback.

Testing your mobile app – plan ahead before it’s too late

More than ever before, organisations are now preparing themselves to engage with their customers not only to attract business but also to get to know them better. This proliferation of information makes it possible to personalise user experience for a targeted audience. Building your own Mobile App is a great medium to achieve that. But be cautious – a poorly rated app can ruin everything!

The inspiration for this blog is a piece of work that we did for one of our customer few months back. We tried to find an optimum way of testing mobile apps that were being built targeting their Australian customers.

When you look at the eco-system of mobile app testing, it can be daunting and overwhelming – especially because of the immense risks involved for a poorly tested application that can negate the brand reputation in no time. That’s why it is even more so important that you set your strategy right, before jumping into ‘some sort’ of testing.

There are four dimensions of testing that we looked at –
four dimensions of testing

When you look at the challenges, they are countless. Unlike any other technology space, mobile industry is going through a rapid transformation which changes as little as in every few months. And if your testing has to keep pace with that market, you will probably experience what we call as the ‘minimal set of challenges’. So here are is our minimal set of challenges –

  1. Diversity
    1. Diverse platforms
    2. Innumerable devices
  2. Fragmentation
    1. A huge fragmentation in OS/hardware/firmware – especially in Android platform
  3. Dynamic
    1. Frequent OS upgrade
    2. Shorter App Release cycles
  4. Tools
    1. Relatively less matured test tools
    2. Predicting & simulating end user behaviour

And when you have to work through these challenges, you have to have certain principles in mind that will drive your testing effort. The two most prominent among them are –

  1. Target the maximum with the optimum effort: Target your audience. Think about how your tests can impact the majority of your app users. A simple example can be to analyse your usage data from some other sources, look into the demography of these users – how they use it, how they interact and how they consume resources. Build your tests around those priority areas. This can be the ‘cool’ features in your app, a set of devices, one/two specific platforms, anything.
  2. A proper support system to help your testing: To test an app successfully, you need to have adequate support from the tools, infrastructure and resources. Make sure that you have them in place, allowing you to maximise your automation capability, thus reducing your regression time and manual errors.

So, planning is important..right? Here are my top five “to-dos” when planning for your tests –

1. What are we testing?

Seems quite reasonable question but probably the most poorly answered one. If you do not know what are you trying to test, that’s a perfect recipe for failure. Below is a simple illustration of the tests that you like to identify in a heat-map.

testing heat map

2. Prioritise your tests.

There are innumerable ways that you can design and write your tests but unfortunately projects work within the sphere of triple constraints! So prioritisation is the mantra. You need to understand and decide which makes the most impact and give you the biggest win in the market.

test prioritisation image

test prioritisation image

3. Determine how you will handle different tests.

It is of paramount importance that you think about what goes into each of the tests, how will you test them, what tools will be required, test acceptability criteria and so on.

The table below illustrates the idea with the help of simple table that aims to capture all possible factors that may impact your tests outcome.

test factors

test factors

4. Get your test infrastructure in place.

If you have to test the things you want, make sure there are enablers that can help you to do just that. There are few bits and pieces that you will need organise to get you going –

  • Mobile Test Tools
  • Test management Tools
  • Test Lab/execution set up
  • Mobile device lab (on-prem / cloud)
  • External dependencies

This is a sample illustration of how you can integrate few of the industry-standard tools. All you are doing here is to find a way that each of the different components in your testing infrastructures gels with each other and makes your life a lot easier by seamlessly flowing information from one to another. Your test scripts can be created, organised and executed seamlessly from this kind of a set up.

test integration diagram

5. Pick the right tools.

This does overlap with the previous point and you may be wondering which one to do first. While deciding on the different infrastructure components and understanding how they interact is a critical task, this heavily depends on finding the right fit. There are a number of tooling options in the market for testing mobile apps, each one offering their own unique features. You will have to find out what matters most to you and your organisations.

I prefer to use selection criteria when I go to pick a tool. For mobile app testing, it is even beneficial to set the criteria at two levels where you can consider going to the next level when you think the first level criteria are satisfactorily met.

The diagram below can get you a good feel of the most important things that you need to consider while selecting the right fit.

test tool criteria

When you plan well with the right kind of dependencies, you become more confident of the things that you would like to achieve. Of course, there will be surprises – but they are less ‘uncertain’ and more ‘predictable’.

One more thing before I sign off (there is always a ‘one more thing’!) – there are countless ways that things can go wrong in a mobile world but this is also the biggest and the strongest opportunity to connect to your customers in a ‘connected’ world. So leverage it in the most effective way and get the maximum out of it.

If you are not sure how to embark on that journey, feel free to reach out to us – together we can make it happen!