If you are developing an app, you want to reach as many users as you can and the easiest and the most obvious target is a web application. It is easily accessible irrespective of the platform users are on. However, not all applications\scenarios can be delivered through a browser and this is why we have desktops\laptops, wearables and mobile apps. So now you have to write software that supports these platforms as well. Will life be easier if you could write code just once that would work on all these platforms?
Only 2 platforms (or form factors) - desktops\laptops can be Windows, Mac or Linux. Phones are either Android or iOS. This is not even considering the huge market of Tablets and Wearables. It is also not considering the various versions of those devices running various versions of the operating system on them.
In this article, we will take a look at Uno Platform to develop our app for Windows, Mac, Linux and Android.
Note: We will discuss a bit more about cross-platform development, challenges and alternatives to the Uno Platform in part 2 of this article.
Uno Platform is an open source UI platform to build apps with a single codebase that can target a wide variety of platforms. You write code in C# and XAML to target all these platforms. It builds on existing capabilities provided by each platform internally, so that you can focus on developing your app. It does allow you to add\modify the app's behaviour based on where your app is running.
GitHub docs has a good summary on how Uno works for build, runtime and rendering across platforms.
We will look at creating a simplified version of the Portfolio Tracker web app that I previously wrote about. The constraint I have imposed is, I shouldn't have to modify my service or database. It has to work with the existing set of APIs.
My requirement boils down to this -
- Use this current available data and write an app that runs on Windows, Linux, Mac and Android.
- Reuse as much code as possible from the previous Web Assembly project that I've created.
Note: Uno supports more platforms than the ones I'm targeting. It supports iOS, Tizen and Web Assembly as well. I cannot try out iOS and Tizen so I've excluded those and since I already tried out Web Assembly using Blazor I didn't include that as well.
I have used Visual Studio 2019 on Windows and Visual Studio 2019 for Mac. Uno Platform getting started guide for both platforms are available here.
Here is the Visual Studio project structure for this app -
- The Mac target project is unloaded as it is not supported on Windows.
- The Shared project is only a list of files. They are shared by each target platform and built for each as well.
- Each target project can have items specific to itself - fonts and image assets for each platform are couple of examples.
- Any reference\NuGet package to be added, has to be added to all target platforms.
- MainPage.xaml in the shared project is where the navigation is setup using the NavigationView. Also the default view is set in Main.xaml.cs and in this case, Dashboard is set as default.
From the actual code perspective, it is writing a C#\XAML UWP app. We're working on the UI and we need UI controls. I will come back to this in part 2 to talk a bit more but I will mention the Windows Community Toolkit here. There is a section in the docs on how to use it, which is ported onto other platforms. I did include DataGrid, NavigationView, ProgressBar in the project and it worked fine.
I could not try out gesture support as I tried the app in the Android emulator and not on a physical device.
In a real production app, it may be the case that we will need platform specific behaviour. I didn't really have such a scenario for this app but I wanted to try it out anyway, so this is what I did - on Android I wanted the navigation menu to be the hamburger menu (3 stacked dashes), on the top left. For desktops\laptops, we have plenty of screen space so I did not want a hamburger menu and instead as menu items with the selected one being underlined.
#if __ANDROID__ RootNavigationView.PaneDisplayMode = NavigationViewPaneDisplayMode.Auto; #else RootNavigationView.PaneDisplayMode = NavigationViewPaneDisplayMode.Top; #endif
Couple of app screenshots here from Linux and Android - Linux was a virtual machine on Windows 10 running Kubuntu 18.04.
Android screenshot is from the emulator as I didn't root my phone to install this locally developed app. Yeah the app does not look great, thanks to my choice of painting it gray.
You can target a wide variety of platforms with a single codebase and that is neat. It includes Web Assembly as well so it covers the browser space too. In the app, the code in the folders under Shared project (Models, Interfaces, Services, Helpers etc.) are code that I've used as-is from the previous project. This is the biggest advantage I've seen writing this app with Uno. I have my service and database and I have all the code to fetch and handle it. The focus is only on building the UI. Unless we need\want to do something platform specific, Uno abstracts it from us.
XAML Hot Reload is super useful, especially if we're used to, say React development for example. Uno does have an active Discord channel where core members participate, which is encouraging to see.
There is also decent support for 3rd party libraries (I'm excluding UI controls here, which I talk about in part 2) including presentation frameworks like MVVM Light and theming options like Material UI as well.
Link to the GitHub repo for this app.
Cover image credit