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.

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.

Test App – It Works!

We’re making good progress now that we’ve gotten over the problem with the app refusing to load the Facebook login dialog (see previous posts).
Note: I still need to sort that problem out properly (or hope someone posts a solution) but for the time being, my test package is called Com.Facebook.Android!

Anyway, I have managed to build this little test app with very C# style code. Any places where I must use Java style code has been encapsulated as tightly as possible so that from the outside is still looks neat.

The screens show:

  1. The welcome screen with login button
  2. After the login button is pressed, this Facebook dialog appears
  3. Type in your Facebook credentials and press the Log In button
  4. The dialog even has a built in Loading… dialog.
  5. The dialog returns control to my app informing me of the result. Pressing the Logout button asynchronously logs you out
  6. Final confirmation of being logged out.

Excellent!

Note: I realise that visually, it just looks exactly like the sample app. Not surprising really since I’ve simply copied the images and layout code from there. It’s the code behind the layout that is completely different. Also, it’s all been a valuable learning experience. Onwards and upwards!

Working Towards the Middle

Following on from the last post: I had a brand new Android application that used the Mono.Facebook library. I also had a sample application from Xamarin doing the same. Mine didn’t work. The sample did. I was getting the NoClassDefFoundError.

I had no idea how to go about working out the cause of the problem. Googling for answers didn’t seem to find anything.

So my tactic was to take a copy of the working project, and slowly comment things out to try to get it to look like my application that didn’t work.

This plan worked very well. I managed to comment out pretty much the entire application, eliminating all sorts of potential causes along the way until I eventually had barely any code left. But still the same worked and mine didn’t. But it was much easier to diagnose now. Something was different and there were almost no candidates left.

Surely it can’t be the namespace…? My app package was called FB2. The sample package was called com.facebook.android. So I changed the name of my app, and would you believe it…

So if you get an error that says:

Unhandled Exception:

Java.Lang.NoClassDefFoundError: com.facebook.android.R$drawable

… what it’s trying to tell you is that it is looking for the generated “R” class in the “com.facebook.android” namespace.

Obviously, now that I’ve diagnosed the source of the problem, I could search for a more appropriate solution. Here’s a StackOverflow post about this very problem. If I decipher the solution posted and figure out how to fix it, I’ll let you know.

Object vs Java.Lang.Object

Be careful when copying code from one file to another in Mono for Android. Missing namespaces are pretty easy to spot and diagnose. But if suddenly the compiler starts saying that one of your classes doesn’t implement strange methods, it might because the class derived from Object. But not .net’s Object, Java’s Object.

Check for this alias definition at the top of the file:


using Object = Java.Lang.Object;

class LoginDialogListener : Object, Facebook.IDialogListener

I should have spotted it earlier really – I mean, when do you ever explicitly state that your class derives from .net’s Object?