Mono for Android: Just too expensive

There has been much talk in the office about mobile development.

I work with several devs that are building mobile apps in various different techs on different platforms.

For ages, I’ve been flying the Xamarin flag and fighting its corner. I’ve got the guys to come to Stuart Lodge’s MVVM Cross talks etc. As a development environment, I like it very much and I’m comfortable. I’m a c# WPF developer and so I like C# and Visual Studio.

But with the new pricing, I feel as though I’ve been let down.

$1000 is just way too high for the hobbiest app developer. Not to mention that that is per dev, so the guys that are in a small team of 3 or 4 – is their app going to make back $4000? Not any time soon that’s for sure.

And so they are going the Javascript, Typescript, Angular etc route under PhoneGap or whatever. And I don’t blame them.

Meanwhile, I’ve 11 months left of my annual subscription to build something in Mono for Android before the $1000 bill comes around again. And I feel I’ll have a hard time justifying it.

Common UI? Spotify on WP8 != Spotify on Android

Welcome Spotify!

Several friends of mine have the beautiful Nokia 920 running Windows Phone 8. It is a nice piece of hardware and it showcases WP8 very nicely.

One notable omission from the WP app store until now has been Spotify.

I’ve been a big supporter of Spotify ever since the beginning and happily pay my monthly premium subscription. Being able to store music offline on my phone is an absolute killer feature.

And so I am genuinely pleased that it has made it to the WP platform.

A Common UI

A hot topic of recent conversation amongst the boys has been HTML5 and the possibility of a common UI across multiple platforms. The conversation typically includes:

“You can write it once and it’ll run on desktops, iPads, mobiles…”

I have been developing in Mono for Android which allows for the code from the “viewmodel” (a logical representation of the view), interaction and business logic, service calls, etc to be shared.

Crucially though, the view, the UI, is not shared. And I believe this is a good strategy.

Users of Android expect their apps to be Android-like. Ditto for iDevices and Windows Phone.

Looking at screenshots of the new WP8 Spotify app, it is clear that the UI has been redesigned specifically for the Windows Phone. And rightly so.

So I applaud Spotify for making this (what I believe to be the) correct decision.

 

http://blogs.windows.com/windows_phone/b/windowsphone/archive/2013/02/08/spotify-arrives-on-windows-phone-8.aspx

Pausable Observable

There are many times when we might need to “pause” a live stream of data.

For example, your app is receiving live updates to a screen and then the user opens some sort of popup. We might choose to pause the live updates until the popup is closed. Once the popup closes, we need to apply the updates that have arrived in the mean time.

Often, it isn’t possible to actually pause the source of the data, such as a server. We also wouldn’t want to unsubscribe temporarily because updates could be missed.

Here is an extension method that takes an RX stream and makes it pausable. It is controlled by an observable which indicates whether the stream is paused or not. Updates are buffered whilst the stream is paused. When the stream is unpaused, buffered updates are pumped.

PausableObservable: https://gist.github.com/4317938
Unit tests: https://gist.github.com/4317948

public static IObservable<T> Pausable<T>(
           this IObservable<T> sourceStream,
           IObservable<bool> isPausedStream,
           bool startPaused = false)
        {
            return Observable.Create<T>(o =>
            {
                var subscriptions = new SerialDisposable();
                var replaySubjects = new SerialDisposable();
 
                var subscription = sourceStream.Publish(stream =>
                {
                    Func<ReplaySubject<T>> replaySubjectFactory = () =>
                    {
                        var rs = new ReplaySubject<T>();
 
                        replaySubjects.Disposable = rs;
                        subscriptions.Disposable = stream.Subscribe(rs);
 
                        return rs;
                    };
 
                    var replaySubject = replaySubjectFactory();
 
                    Func<bool, IObservable<T>> switcher = isPaused =>
                    {
                        if (isPaused)
                        {
                            replaySubject = replaySubjectFactory();
 
                            return Observable.Empty<T>();
                        }
                        else
                        {
                            return replaySubject.Concat(stream);
                        }
                    };
 
                    return isPausedStream
                        .StartWith(startPaused)
                        .DistinctUntilChanged()
                        .Select(switcher)
                        .Switch();
                }).Subscribe(o);
 
                return new CompositeDisposable(subscription, subscriptions);
            });
        }

This is based on an answer to a question on StackOverflow. However, there was a small issue which I had to fix – and I also needed to be able to specify in which state the pausable stream started.

Observable Cache

Source Code: https://gist.github.com/4115023

Given: An async operation that returns a value e.g web/service call or complex calculation
When: I request the value multiple times
Then: I only perform the operation once and cache the value

When: I haven’t requested the value
Then: Don’t perform the operation

When: I clear the cached value
Then: requesting the value again performs the async operation again

My current solution:


    public class Cache<T> : IDisposable
    {
        private readonly IConnectableObservable<T> _source;
        private IDisposable _connection;

        public Cache(IObservable<T> source)
        {
            _source = Observable.Create<T>(o => source.Subscribe(o))
                                .Replay(1, Scheduler.Immediate);
        }

        public IObservable<T> GetValue()
        {
            return Observable.Create<T>(o =>
                                         {
                                             var subscription = _source.Subscribe(o);
                                             _connection = _source.Connect();
                                             return subscription;
                                         });
        }

        public void Clear()
        {
            if (_connection != null)
            {
                _connection.Dispose();
                _connection = null;
            }
        }

        public void Dispose()
        {
            Clear();
        }
    }

DateTime.MinValue – be careful!

We’ve just had a support call at work where the user was running our application in Singapore.

Our investigation uncovered an interesting “feature” of using DateTime.MinValue.

Have a look at the following test:

namespace Stuff
{
    using System;
    using NUnit.Framework;

    [TestFixture]
    public class MinDateTimeOffset
    {
        [Test]
        public void Testing_MinValue_in_DateTime()
        {
            Action<string> p = Console.WriteLine;

            // This is Now in the current timezone
            var nowOffset = new DateTimeOffset(DateTime.Now);
            p("Current time:");
            p("- current timezone: " + nowOffset);
            p("- UTC equivilent time: " + nowOffset.ToUniversalTime());
            p("");

            // This is the minimum time allowed in the current timezone
            var minOffset = DateTimeOffset.MinValue;
            p("DateTimeOffset.MinValue:");
            p("- current timezone: " + minOffset);
            p("- UTC equivilent time: " + minOffset.ToUniversalTime());
            p("");

            // This is UTC minimum time
            var minValue = DateTime.MinValue;
            p("DateTime.MinValue:");
            p("- current timezone: " + minValue);
            p("- UTC equivilent time: " + minValue.ToUniversalTime());
            p("");

            // Converted to the current timezone
            try
            {
                p("Trying to cast DateTime.Min to DateTimeOffset:");

                var minDateTimeAsDateTimeOffset = (DateTimeOffset)minValue;
                p("- current timezone: " + minDateTimeAsDateTimeOffset);
                p("- UTC equivilent time: " + minDateTimeAsDateTimeOffset.ToUniversalTime());
            }
            catch (Exception ex)
            {
                p("Error: " + ex.Message);
            }
        }
    }
}

We are based in London, and when we run it, we see this output:


Current time:
- current timezone: 31/10/2012 11:46:35 +00:00
- UTC equivilent time: 31/10/2012 11:46:35 +00:00

DateTimeOffset.MinValue:
- current timezone: 01/01/0001 00:00:00 +00:00
- UTC equivilent time: 01/01/0001 00:00:00 +00:00

DateTime.MinValue:
- current timezone: 01/01/0001 00:00:00
- UTC equivilent time: 01/01/0001 00:00:00

Trying to cast DateTime.Min to DateTimeOffset:
- current timezone: 01/01/0001 00:00:00 +00:00
- UTC equivilent time: 01/01/0001 00:00:00 +00:00

However, when run in Singapore, you get this:

Current time:
- current timezone: 31/10/2012 19:47:38 +08:00
- UTC equivilent time: 31/10/2012 11:47:38 +00:00

DateTimeOffset.MinValue:
- current timezone: 01/01/0001 00:00:00 +00:00
- UTC equivilent time: 01/01/0001 00:00:00 +00:00

DateTime.MinValue:
- current timezone: 01/01/0001 00:00:00
- UTC equivilent time: 01/01/0001 00:00:00

Trying to cast DateTime.Min to DateTimeOffset:
Error: The UTC time represented when the offset is applied must be between year 0 and 10,000.
Parameter name: offset

In New York, you get this :

Current time:
- current timezone: 31/10/2012 07:48:50 -04:00
- UTC equivilent time: 31/10/2012 11:48:50 +00:00

DateTimeOffset.MinValue:
- current timezone: 01/01/0001 00:00:00 +00:00
- UTC equivilent time: 01/01/0001 00:00:00 +00:00

DateTime.MinValue:
- current timezone: 01/01/0001 00:00:00
- UTC equivilent time: 01/01/0001 05:00:00

Trying to cast DateTime.Min to DateTimeOffset:
- current timezone: 01/01/0001 00:00:00 -05:00
- UTC equivilent time: 01/01/0001 05:00:00 +00:00

The value of DateTime.MinValue can not be cast to a DateTimeOffset if you are east of London!

MonoDroid Unit Tests

A well known approach to unit testing class libraries that target Silverlight, Mono for Android, MonoTouch etc is to make a “real” .net  class library project which contains all of your non-ui code, and link those files through to a project that targets the runtime. This way, we can use our full unit test tools such as nUnit, nCrunch and Resharper.

The main drawback of it though is that if your runtime environment has some peculiar difference, then tests that pass in full .net go on to fail in the target run time.

I encountered a problem in using TinyIOC. I needed to resolve the same instance of Mono.Facebook in several places. Despite registering it as a Singleton, every time my different components resolved it, they got a new instance.

This was a tricky problem to diagnose without unit tests. Continually running the app, setting breakpoints in the constructors and then looking at facebook.GetHashCode().

Some unit tests written in full .net all passed using  dummy objects registered in the container. Mono.Facebook could not be referenced in the full .net unit tests though because it is a Mono for Android library.

What I needed was a way to run unit tests within Android. Enter monodroid-unittest!

This allowed me to create a unit test project native to Mono for Android, and to run the unit tests in my target run time.

I soon had unit test for my real library up and running, and the problem resolved!

TinyIOC

As my Mono for Android app continues, I’ve been introducing more and more libraries to try to sort out its structure.

One of the largest changes to my development many moons ago was the use of a dependency injection container. There is only so far that I can go in any project before needing one – even if it’s just a test project.

Greg Shackles wrote about using either TinyIoC or Func with Mono for Android back in Feb 2011.

So I’ve added TinyIoC  to my app and have been registering the classes, adding interfaces to separate component dependencies etc.

Now in WPF / Silverlight, we’ve been spoilt by the powerful AutoFac. It seems a little heavyweight for a phone app though, but that doesn’t stop me wanting some of its power.

I chose to try TinyIoC because:

  • it’s just a single cs file that you include in your project – simples!
  • it had support for automatic factories – so you register T and can then inject Func<T>

What I’ve found that is that many of my components have a mixture of dependencies and parameters in the constructor. AutoFac just copes with this automagically, but I’ve been having to register custom factories for everything in TinyIoC. It’s ok for now but will get tedious quickly. It also uses a slightly cumbersome string object dictionary for custom parameters.

If you’re doing IoC correctly, then none of the components should be affected by which container you’re using – so I might try a different container shortly.