Firstly, I have a confession to make … I am pretty lazy! Perhaps not Homer Simpson lazy, but it’s something I do aspire to… 😉 I take some solace from this quote attributed to Bill Gates:
“I choose a lazy person to do a hard job. Because a lazy person will find an easy way to do it.”
On a recent Xamarin.Forms project I was working on, the focus was a UI/UX refresh with a lot of non-linear lines and shapes. Accordingly, there was the need for a lot of images. The requirement was to support @1x, @2x and @3x resolutions on iOS, and mdpi, hdpi, xhdpi and xxhdpi on Android. So for every image required, there were actually 7 variations of the same image at different resolutions. On top of that, as the project went on sometimes images would need to get updated to get things pixel-perfect, while other times churn would be created as the machinations of the business got involved. This added up to many minutes lost to a tedious, error prone, recurring manual task. The pain of this process was particularly felt with Android, which uses the convention of a separate directory for each resolution.
I already had some PowerShell up my sleeve to mitigate some of the pain, but I decided to polish it up and make it available, for the simple joy of writing and shipping code without bureaucracy if nothing else. And so, the Xamarin Image Importer was born, in the form of a module in the PowerShell Gallery.
This little utility aims to do 2 things only – (1) copy images to the correct location in the file structure required by iOS / Android (2) add them to .csproj files so they will appear in Visual/Xamarin Studio. Many of the variables of the process can be inferred by convention. This worked well for the project I was working on, where the designer on the team would export images from a SVG using Illustrator then dump it into a Dropbox folder. From there, the PowerShell slurps in the images and does the rest.
While I have no immediate need to develop the tool further for myself right now, some potential additions I can imagine include:
A pretty simple change to cater for images other than .png
Handle project types other than Xamarin e.g. Telerik AppBuilder
Take a .svg as the import source, and then do the export into various resolutions automatically, reducing the need for the likes of Illustrator or Sketch purely for this mechanical task (version 2.0?)
Could perhaps use the logo.gen tool my colleague Poya Manouchehri has been working on
Something else somebody suggests and/or comes up with in a Pull Request
Anyway, hope this little tool helps some of you out there. Happy lazy coding!
By many accounts, Xamarin is a fantastic product that makes it easier for developers to build apps for a range of mobile devices. For me however, delivering that functionality well is only ‘par for the course’. That is, a seamless experience to develop an apk, ipk or appx is what I would simply expect for any offering that promises a common code base targeting multiple mobile platforms.
An approach that continues to strike me about Xamarin is their commitment to making the mobile software development life-cycle easy – the entire process of building, testing and monitoring to borrow from the company’s current mantra. The direction taken by Xamarin with the 4.0 release certainly builds upon the impressive suite of tools already available. One new feature of this release that I was particularly eager to get my hands on is the preview of the Xamarin Test Recorder. Whereas many other features available in the 4.0 release are evolutions of known tools, to my knowledge Test Recorder is a completely new offering. It is good to see the company not rest on their laurels!
To get the Test Recorder running, you first need to download and install the OSX package. However, there are several steps which are not explicit in the preview version of the documentation I was looking at. As such, I will outline them here should it help anybody.
1. You will need your Xamarin Test Cloud API key upon installation. This is available once you log in to your Test Cloud portal. In case you are wondering about hidden or unexpected costs, remember that all Xamarin subscribers have 60 free Test Cloud minutes each month!
2. If you wish to use the Test Recorder with an Android project, you will need to grant the ‘INTERNET’ permission in the Android Manifest.
3. Publish your apk or ipk locally. Then simply start Xamarin Test Recorder, select the apk/ipk you previously published and the magic begins!
Now, all you need to do is hit ‘Record’ and starting using your app. When you finish the sequence you wish to test, click ‘Stop’. From there, you can either ‘Play’ the test sequence again, copy the generated Xamarin.UITest output to the clipboard, export to file to import into your test project, or send it straight to Xamarin Test Cloud. As you can see below, I have put the Test Recorder in action on the sample timesheet app I recently made available.
Manual testing is of course time-consuming and somewhat error prone, but absolutely necessary in software development. This is perhaps even more true in the world of mobile apps where there is much competition. But Xamarin.UITest and Xamarin Test cloud already solves the problem, so why do we need the Test Recorder? The answer is of course, the significantly reduced time for developers to write tests! Furthermore, there is even potential for non-developers to generate tests! Imagine empowering your BA or QA team who are not well-versed with Xamarin to develop tests … or even watching and replicating how your non-technical grandmother breaks your app!
I do wish it was more complicated to get the Test Recorder running, as it would make this blog post look more insightful and myself more intelligent! 🙂 However, there really isn’t any significant barrier to entry if you are already an existing Xamarin developer. I can’t wait to use the Test Recorder on my next live project.
Xamarin, thank you for exceeding my expectations once again!
As part of studying for my Xamarin Certification, I wanted some extra practice before sitting the exam. As such, I decided to do a Xamarin iOS and Android version of the same Xamarin.Forms timesheet app I implemented and wrote about before. The added bonus of this is that it could potentially provide a basis of comparison between ‘vanilla’ Xamarin and Xamarin.Forms. So in case it helps anybody, I have made the source code available on GitHub.
I subsequently passed the exam … I am now certifiable certified! 🙂 That will most definitely do me for a while in terms of exams and certifications, having notched up my MSCD, PSM I and now Xamarin in the past 6 months. I’ve enjoyed the process and they were all valuable experiences, but for now it is time for me to get my hands ‘dirty’!
On a project my colleague @halkar and I were working on, we came across a puzzling issue. We only discovered this issue after converting our project from the Classic MonoTouch API to the Unified API. On the iOS simulator, our application would fun fine, but when we tried to run it against a real iOS device, we could get an error to the effect of “Native linking failed, undefined Objective-C class …”.
A quick search within our solution revealed no clues, and the subsequent Google search confirmed that EAAccessoryManager is indeed a native Objective-C class. So the class is clearly defined, but our compiler tells us otherwise?
As per the compiler error message, Google has multiple sources to suggest that the solution is to simply add a [Protocol] attribute to the offending C# class. However, here the code wasn’t in our application but in the Xamarin binding library that didn’t get linked to the corresponding Objective-C EAAccessoryManager.
Upon further investigation of the Xamarin.iOS Type Registrar to explain why the application worked in the simulator but not a real device, it turns out that Xamarin uses dynamic registration for simulator builds but static registration for device builds. The reason for this is speed, in that a development machine would have the necessary power to scan classes at runtime, whereas a new binary is always required to deploy to a device. Going down this path, a suggested solution is to use the legacy registrar, but this just results in a different compiler error indicating it is not allowed in a Unified API project.
So where to from here?
Enter the Xamarin Linker
This led to us having a deeper look at the Xamarin.iOS Linker. In short, our project compiled when we selected “Don’t link” for the Linker behaviour option. The default option is “Link SDK assemblies only”, which will mean the Xamarin linker will attempt to exclude all the symbols from the SDK it thinks is unnecessary. Unfortunately, it appeared in our case the static registration analysis was over-zealous. It should be mentioned also that the use of the word “Linker” by Xamarin is slightly counter-intuitive as noted by Adam Kemp and the behaviour is different to the conventional sense of the word. For my own understanding, I found it made more sense if it I substituted the word “Optimize” for “Link” – i.e. pick the “Don’t optimize” option!
But it has to be at least … three times bigger than this!
Please pardon the obscure Zoolander quote, but in practice you will need to consider the size of the generated IPA binary. It really depends on the exact nature of the application as to what the actual size difference would be, but roughly speaking it appears the “Don’t link” option can be 3-5 times larger than the default “Link SDK assemblies only”. App consumers these days are quite unforgiving, and so you really need to do everything in your power to provide a good first impression. This, of course, includes minimising the size of your app and therefore potential installation problems.
As such, the solution we settled for was to explicitly reference the EAAccessoryManager class in our code, allowing us to revert back to the“Link SDK assemblies only” option. This of course is merely a workaround, but it was the most elegant method we came up with to solve our problem. Hopefully Xamarin will address the issue with the Linker soon, but until then this workaround should do the trick.
var sharedAccessoryManager = EAAccessoryManager.SharedAccessoryManager;
Success! Time to go home.
Addendum – Xamarin Support
A big shout out to @kumpera and the Xamarin support team! We had a response within 24 hours after submitting a sample solution to replicate the problem. In our particular case, there were 2 issues that were at the root of the problem, neither of which was a fault with Xamarin. Firstly, a third party library we used did not contain ARM64 code, meaning linking failed when building for this architecture. Secondly, this library also had dependencies on frameworks such as the EAAccessoryManager. Anyway, instead of the workaround originally suggested, a better way to do achieve the same thing is to use the LinkWith attribute.
For Xamarin developers, getting an Android emulator working is a commonly faced challenge since the standard one provided by Google is unworkably slow. When different operating systems and virtual machines are in the equation as well, the potential for encountering problems obviously increases. It is a common scenario however, and is how I prefer to work. More specifically, where possible I develop in Visual Studio inside a Windows virtual machine using Parallels, with Mac OS as the host providing access to the iOS emulator and build host. This allows me to use the IDE I already use on a daily basis when I am not on a mobile project, while also being able to run iOS, Android and Windows Phone emulators all on the one machine.
There is some information out there describing how to get GenyMotion working in such cross-platform environments, which uses the same Oracle VirtualBox technology as the newly launched Xamarin Android Player (XAP) under the covers. However, it is a little inconsistent and often involves some sort of complicated SSH tunnelling. So my grand plan was to document this entire process from end-to-end specifically for XAP since Xamarin did not document this initially. That is … until I was almost there after doing the crazy SSH tunnelling myself … I discovered a new blog post by Xamarin’s James Montemagno on the subject!
Newer versions of XAP make it easier still. Now all you need to do is to get the IP Address by clicking on the settings cog wheel in your XAP. In my case, it is 10.71.34.101.
Then, all you need to do is open an ‘Android Adb Command Prompt’ from Visual Studio and enter adb connect. You can also enter adb devices to check your connection status if you wish.
Note that however, you will still need to enable ‘USB debugging mode‘ to allow the Visual Studio debugger to do its thing. For those who don’t know the secret Android developer handshake … on your emulated Android device:
1. Go to Settings
2. Go to About phone
3. Click on Build numberseven times
Hope that helps! And a big thank you to James and the Xamarin team for saving me from having to do the aforementioned crazy SSH tunnelling! 🙂
Xamarin often quote figures in the order of 70% for code re-use across iOS, Android and Windows applications. The illustration below, borrowed from Xamarin.com, demonstrates this conceptually.
But what about Xamarin.Forms? Xamarin claim that now UI code can be shared across the 3 platforms, often 90% or an even higher percentage of code and be written once and re-used, depending on the exact nature of the application. Again borrowed Xamarin.com, the graphic below aims to illustrate this.
So how valid are Xamarin’s claims, or is this just marketing hype? Are the quoted percentages too good to be true? Are the figures reflective of the lines of code, time and effort spent or some other random metric? What does this look like in practical terms? Let’s explore a little.
Case Study: Simple Timesheet App
For the purpose of this exercise, we will build a simple timesheet app inspired by a real project at Readify. We will define two user stories with acceptance criteria as per the below.
1. View Timesheet
As a user, I want to be able to view a list of my outstanding timesheets, so I can see which timesheets I haven’t submitted yet
– Date, Customer, Project read-only fields
– Loading indicator displayed while waiting for a response
2. Submit Timesheet
As a user, I want to be able to submit timesheets, to allow the business to invoice accurately
– Date, Customer, Project read-only fields
– Hours (.25 hour increments – 0 to 24) selection entry
– Comment text entry
– Sick Leave (yes/no) selection entry
– Submit button
– Loading indicator displayed while waiting for a response
– If successful, the user will be returned to the timesheet list page
– If unsuccessful, a friendly error will be displayed to the user
Under The Bonnet
Before you can use Xamarin.Forms, you will need at least an Indie license. Alternatively, you can obtain a trial Business license.
So, let’s set up the building blocks for our test drive. Our solution should contain 4 projects: one for iOS, Android and WinPhone, and of course a common project that contains all of our shared code where all of the action will be located unless noted otherwise. The common project can either be a Portable Class Library (PCL) or a Shared Project, but for this exercise we will implement it as a PCL.
One final note before we proceed any further – this blog post does not aim to be a tutorial so implementation details will not always be described at length, but they will be mentioned if they are a little out of the ordinary. However, all code is available on GitHub so you can follow along or examine anything in detail should you wish to, with commits corresponding roughly to the flow of this blog.
To model our data, we create a TimesheetEntry.cs class and put it under ‘Models’.
We create a service to handle the listing and submission of timesheet entries and put it under ‘Services’ like the below. Note that our implementation does not do anything like persist data – for the purpose of this exercise, we are aiming to do just enough to examine Xamarin.Forms in a meaningful way. So, our listing returns the same data every time and our submission won’t really save, but we make each method sleep for 2 seconds to simulate a call to an external data source over the wire.
Ready, Set, Go!
We can now concentrate on our UI code to see if Xamarin.Forms can deliver on what it promises. With Xamarin.Forms, you can either work in XAML or code, and here we will work with the latter. Both arguably have their advantages, such as a better separation of concerns versus the current availability of intellisense in Visual Studio respectively.
Firstly, we create the outstanding timesheet list page using a ListView control. ListView works well without much effort, but because our user story has identified 3 fields to display, we need to create a custom ViewCell for it as the standard implementation of ListView only allows for 2 lines of text. Our custom ViewCell will contain a StackLayout of our 3 fields.
The timesheet list page was easy enough to create with the only hurdle being each ViewCell requiring a height value. Otherwise, Xamarin.Forms has been adept at calculating screen real estate to this point, although there is some variation between how the list looks on iOS and Windows Phone. In our example, a ViewCell height of 80 works better on iOS and 100 on Windows. The official Xamarin.Forms documentation does acknowledge the issue, so perhaps Xamarin will address it in the near future.
For the timesheet entry page, we will use a vertical StackLayout control for the overarching structure of the page, with a nested horizontal StackLayout for each label and field combination.
From my experience, the basic layout and functionality for this page was achieved without significant loss of momentum. However, in working with the controls, I discovered a number of quirks with them and so I did get bogged down occasionally. In the opinion of this author, some of these issues can arguably be expected, while others not so much. As alluded to earlier, spacing, padding and alignment exhibited some variance between devices, which can perhaps be excused especially by developers coming from a web background where catering for multiple browsers is the norm. However, LayoutOptions that can be used with the StackLayout control behave inconsistently and unexpectedly for a singular device, let alone when compared between iOS, Android and Windows platforms. For example, it was by trial-and-error to determine whether to use End, EndAndExpand, Fill or FillAndExpand for the LayoutOptions of the ‘Hours’, ‘Comments’ and ‘Sick Leave’ input fields. In addition, the width of a label cannot be guaranteed with the developer only able to request a width, leading again to layout differences across devices. In hindsight, perhaps using GridLayout or rethinking the layout altogether would have been a better choice for this page instead of nested StackLayouts. When I get a chance to investigate the effect of GridLayout, I will update this post accordingly should there be anything pertinent to report.
Not So Fast …
Things get even more interesting once the ActivityIndicator control gets introduced. While the documentation for the Xamarin.Forms control gallery is generally quite good, it is very sparse for the ActivityIndicator and does not provide any context or examples of how to use it.
So where to from here? For the live project that actually preceded this exercise, we inferred the path forward with the ActivityIndicator by reading between the lines of other Xamarin.Forms documentation, with prior experience of Windows Phone or WPF on the team making this process faster. The answer we eventually arrived at: MVVM. When doing this for the first time in the real world we appeared stalled on the ActivityIndicator for a while, but providing the user with visibility when something is loading remained an important feature for our product owner, and rightfully so.
To cater for MVVM, we add View Models (VM) to sit between the Views (V) and Models (M) that we already have. In our solution, we also rename the ‘Pages’ folder and namespace to ‘Views’ to match MVVM nomenclature. Note that there is some overlap of verbiage which can cause confusion, with Views referring either to Xamarin.Forms controls or the MVVM sense of the word. In addition, we use a Fody add-in (available via NuGet) to allow MVVM data annotations. However, another quirk discovered with Xamarin.Forms is that data binding of the Picker control is not yet supported.
Now that our solution has the MVVM building blocks in place, the ActivityIndicator is bound easily to the ‘IsLoading’ property in our ViewModels so it displays at the appropriate times. In our particular implementation, there is a ‘BaseViewModel’ with the ‘IsLoading’ property that other view models inherit from.
However, getting the ActivityIndicator to display, and getting it to display where you want it to is an entirely different story. Placing the loading indicator at the centre is a common design paradigm in apps, and so the first approach attempted was to overlay the ActivityIndicator using RelativeLayout with this in mind, and the second was to likewise try AbsoluteLayout – both yielded similar results. Despite there being no changes apart from overlaying the ActivityIndicator with either relative or absolute layout, the scrollable area on the listing page now gets cut off when the list is pulled down as if to refresh data on a typical app. Meanwhile, the alignment and padding on the entry page goes askew no matter which layout is used. In the series of screenshots below as displayed on the iPhone emulator, the affected areas described have been highlighted in purple.
To be fair, Xamarin do realise their layout controls need more attention and have been transparent about this.
In terms of sharing UI logic, Xamarin.Forms does theoretically deliver. In our simple example, we created zero platform-specific UI code and so any figures Xamarin quote in the order of 90%-100% I would technically find believable.
However, whether such figures are meaningful in the real world is another story. Layouts are problematic to work with and is somewhat of a time-consuming, trial-and-error process, especially once they get nested. Chances are, significant time will be spent getting your applications to look consistent across devices too, but instead of developing platform specific UI logic, effort will be required to find solutions or workarounds for the controls provided by Xamarin.Forms. Other controls, such as the Picker or the ActivityIndicator, have yet to be implemented or documented properly respectively.
Overall, Xamarin.Forms undoubted has enormous potential, but I would suggest that it is not quite ready for production yet except perhaps for apps with reasonably simple layouts, prototypes, or if your product owner is flexible and does not require the app to be pixel-perfect. It will be very interesting indeed to see how it matures in the near future as Xamarin appear to be investing into this offering, and I have seen evidence of progress in the brief time I have worked with the technology. As such, despite present shortcomings, I am optimistic for the future of Xamarin.Forms and will be keeping a close eye on it.