Loving and hating Xamarin
Don’t get the wrong impression from the title, I really love Xamarin! And there are enough alternatives for cross- and hybrid-development to work with. I mean – it was and is my own decision to work with Xamarin. Mainly because I like the idea of a clean codebase with just one language. And even before working with mobile applications, I already got very used to writing UIs with XAML, which is great! So for backend, desktop and mobile, you can cover everything with .NET and Xamarin in C# and XAML. And for writing websites I prefer Typescript and Angular, which – using the MVVM pattern – makes the gaps between cloud-, website-, desktop- and mobile-development pretty small.
So – what is this post about? The thing is that I’m working with Xamarin since quite a while. Especially with Xamarin.Forms, you can feel real productive, keep the software neat and clean and can reduce the amount of software pieces as small as possible. But during the project I’m working on at the moment, I had several setbacks because the Xamarin projects started to behave very very strangely. Causing app crashes and exceptions from deep within the OS, and without error messages, and during startup even before hitting any breakpoint. Also compiler errors or missing assembly references after making little changes, for example adding a nuget package that seems to have nothing to do with the concerning reference.
During the many bug tracking sessions I had, I stumbled over a lot of threads in the Xamarin support forums which, after reading many posts, very often ended in … nothing! But the good thing I learned from this was that I am not alone. A lot of people having the same symptoms, even though it’s often due to very different reasons.
To make it short – I think Xamarin is a great solution for covering the different platforms. But by offering access to all native functionality, and at the same time trying to ‘facading’ different platform worlds, it produces a certain instability – at least during DEV. I’m sure that any software which is well written and tested in Xamarin, is perfectly reliable once released. But the way to the release can really be exhausting, especially when writing alone on different projects at the same time.
I’m aware that I created a lot of smoke so far. But I really needed to write this down, because after thinking that I had my DEV project pretty much stable, tested and under control, very similar problems with the Xamarin projects appeared again, after I was working some weeks on the (Azure) backend. So now, I’ll try to remember the lessons I learned and fix my project the same way I did before, hoping that it will also help some of you fixing similar problems…
Here are some of the symptoms and errors I fought with:
- Missing assembly references in Android project, although the packages are installed
- Compiler erros about missing assembly references
- App crashes on startup without any useful error message
Now let’s remember that Xamarin is solving a pretty difficult task: bringing completely different platforms together in one solution, and offering lots of packages facading platform specialties – the best example is Xamarin.Forms. And in this case, about the dependencies to the Android Support packages for example, you really have to be careful to not mess up the right combination of package- and assembly-versions. Because even though nuget is pretty good, it cannot guarantee you to always provide compatible setups.
So, to reduce the probability that it’s about a mess of assemblies and dependencies, I really clean up the projects, for which I follow this todo list. Some of these steps seem redundant and unnecessary. But I can tell you that this manual cleanup often worked wonders. So when you have problems with your projects, just invest a little time and try them out. Perhaps you’ll be positively surprised with the results.
- delete nuget packages from the platform project and the portable libraries
- delete assembly references (that belong to the packages) from project files
- delete references of ‘dependent’ assemblies in Web.config or App.config
- close Visual Studio and delete packages folder manually
- open the solution again
Now comes the tricky part: adding all necessary nuget packages back in. Let me give you some advice:
- Use the nuget package manager for the whole solution, not for each single project
- Install the packages top-down, meaning: If a package depends on other packages, directly install the top-level package and let it pull in its dependencies automatically.
- Directly install a package to all the projects in which you need them in one step
Example: After completely removing all packages, I install Prism.Unity.Forms directly into the projects ‘portable’, ‘Android’ and ‘iOS’. This package then automatically pulls in all dependencies to Prism.Forms, Prism.Core, Xamarin.Forms and (in the platform projects) all necessary platform support packages, and in the correct versions of course!
Of course, this means that you have to know your packages and dependencies pretty well. But for me, it’s an important task to investigate about packages before using them. You should get used to that as well!
So, these steps helped me save quite some headaches so far. But of course, not everything is so straight-forward like the example of Xamarin.Forms with Prism. Recently, I wanted to add the package Xamarin.Facebook.Android to my Android project, and it has a dependency Xamarin.Android.Support.v4 (>= 25.1.1). So during install, it updates these support packages from 23.3.0. to 25.1.1. But waaaait! Xamarin.Forms has a dependency Xamarin.Android.Support.v4 (= 23.3.0). So by installing a facebook SDK, you can mess up the entire Android project, because after doing so, the symptoms I described above reappeared. This is the moment when programmers start breaking equipment and scaring collegues.
But this time, I was prepared. So let me give you one more advice: Always keep your projects in source control, even though you work alone on them, and on one single machine. And get used to always commiting everything before touching any package. Or even better, create a branch! And before committing extensive changes, test everything, and on each platform project! And when something breaks, roll back to the stable version and try to include additional functionality again, just better. In my case (the facebook package), I just chose an older package version that was build against Xamarin.Android.Support.v4 (>= 23.3.0), and it didn’t mess up my dependencies anymore.
Here I’m coming back to my basic principles: Keep the circles small, and close the circles, meaning to add automatic tests to every functionality, so you can test all your functions easily after making some changes to your project.
So, I hope this will help some of you as well to reduce headaches and bad mood with Xamarin! So long….