Technology

Gzip Compression Using Xamarin.Forms

By April 15, 2015 2 Comments

In a recent project the RedBit team worked on, we decided to use Xamarin.Form to  build an app for Windows Phone, iOS and Android.  Xamarin Forms is still a v1 product but the Xamarin team is rapidly releasing updates to fill in some gaps. As a developer you still have the opportunity to extend Xamarin Forms, for example by building custom renderers. We’ll have a series of blog posts on some learnings from the team to help extend Xamarin.Forms and meet our client’s requirements.

In this first post, we’ll be looking at how to easily implement GZip Compression for HttpClient on iOS, Android and Windows. We will be leveraging this Gist from @dotMorten to implement GZip for Windows Phone. This works great, but unfortunately is outdated since we can now use the Microsoft.BCL.Compression library. The second unfortunate part is this does not work on iOS and Android using Xamarin.

Why implement GZip?

On mobile, you want things to be as fast as possible and this includes data being transmitted. Compressed data is faster to transmit than non-compressed data, but remember, there may be a slight performance hit de-compressing the data on the client side. Here is chart comparing compressed and uncompressed data taken from http://blogs.msdn.com/b/dotnet/archive/2013/06/06/portable-compression-and-httpclient-working-together.aspx

gzip

The next few steps go over this adding GZip support for a shared project for iOS, Android and Windows Phone using Xamarin.

Support for Windows Phone

With the release of Microsoft.BCL.Compression, which exposes the System.IO.Compression namespace, the team decided to extend the original Gist in combination with Microsoft.BCL.Compression package.  This was a fairly straight forward change and the following will list the steps. If you want to follow along you can download the code from GitHub tagged ‘StartHere’

First, open up the project and add a package reference to Microsoft.BCL.Compression using NuGet Package Manager

vs-open-dialog

Download the HttpGZipClientHandler.cs  from https://gist.github.com/dotMorten/4981198 and add to your project. Your shared project should look like the following

vs-solution

Updating the HttpGZipClientHandler

Open HttpGZipClientHandler.cs and change the implementation of HttpGzipContent to the following

gzip-code-1

Notice here we change the constructor to use the System.IO.Compression and the TryComputeLength() method to use the BaseStream.Length property instead since GZipStream.Length is not implemented. Everything else stays the same.

Updating MainPage.cs

Now that we have our HttpGZipClientHandler class ready we can update MainPage.cs.

First thing we need to do is add a member variable bool _useGzip;

Next, we need add some code to initialize a Switch to be able to enable or disable gzip for the request. Add the following to the top of the constructor of MainPage

code-2

Add the setting variable just created to the Children property of the StackLayout (approximately line 64). Your code should look like the following

gzip-code-3

Run the project on Windows Phone and your page should look like the following

wp-emu-1

Enabling GZip with HttpClient

Now that the UI is ready and the HttpGZipClientHandler is ready, we can enable it when making the request.  Change the implementation of CreateHttpClient to the following

gzip-code-4

Change the _url variable to http://en.wikipedia.org/wiki/Gzip, deploy the app to Windows Phone and make a request with and without gzip enabled. Your output should look like the following

wp-emu-2

Take a look at the debug console and you will see the following that shows the size of the data returned and the size of the uncompressed data.vs-debug-output

Support for iOS

One of the great advantages of Xamarin, is the ability to take your existing code, and with minimal changes, sometimes even no changes, you can have the same app working on iOS and Android and not just Windows. If you are following along, you can use the ‘start-ios’ tag as a starting point.

To enable support for iOS do the following

  1. Right click on the iOS project and click ‘Set as Startup project’
    vs-1

  2. Select the device you want to deploy to vs-2
  3. Build the app to see the errors; 8 in total, and they should look like the followingvs-3
  4. To fix the errors right click on the iOS References and clicking Add Referencevs-4
  5. In the Reference Manager dialog, add a reference to System.Net.Httpvs-5

Attempt to debug and run the project and you will get the following output

emu-1

A couple of things to note here

  1. The switch is not really accessible but this is easily fixable
  2. Content-Length is always 86641 whether GZip is enabled or not

Fixing the Switch on iOS

Since Xamarin.Forms wraps native controls there are sometimes nuances between platforms and having the switch under the titlebar on iOS is one of those. To fix this, we simply add a padding to the setting variable we created earlier with the following code change

code-1

Your app should look like the following nowemu-2

Showing the Right Content-Length

The next thing you will notice is showing the right Content-Length. For Windows Phone this just works, but for iOS (and Android) since we are using Mono’s implementation of System.IO.Compression and System.Net.Http.HttpClient, the implementation is slightly different.

To fix this, we can again take advantage of Device.OnPlatform like we did for the setting variable to fix the switch not accessible on iOS.  Open HttpGZipClientHandler and in the constructor of HttpGZipContent add the following line to the end

code-2-ios

With the code implemented you should now get the correct output for Content-Lengthemu-3

Support for Android

To support Android, the only thing we have to do is add reference to System.Net.Http similar to how we did for iOS. Assuming you successfully have done that here is what the output should look like (this is running on a Google Nexus 4). If you are having troubles you can get the final solution here.emu-1

Wrap Up

So in this article, we went through and updated some old code for Windows Phone to update using Microsoft.BCL.Compression package now available and to use the same code across iOS and Android with almost no changes. This is what makes Xamarin very powerful and why we use it for customer projects, because of the time saved to support new platforms while still getting the benefits of native code.

As always, all the code is available on GitHub at RedBit.Samples.Gzip and feel free to leave your comments or questions here or on GitHub.

Join the discussion 2 Comments

Leave a Reply