FuelAdvisor: Lessons And Insights From Converting A Native Android App to Xamarin
Charles Tatum II
Software developer with experience in mobile and web, and skills in UX, QA & technical writing
INTRODUCTION
I’ve been doing mobile app development for over a decade, and as stimulating an intellectual practice as it is, an app project can still be marked by surprises and landmines on the way to release. My background in mobile started in earnest with the Palm OS platform before I picked up Android, then Windows (Universal Windows Platform, or UWP), and iOS last, and I’ve seen challenges developing for all three.
This article brings a lot of that knowledge together, because it involves a single app being deployed to all three app markets – Google Play Store (Android), Windows Store (UWP), and the iPhone App Store (iOS).
This article is really targeted at relative newbies to Xamarin Forms, even as Microsoft is working on its successor, .NET MAUI (effectively Xamarin 6). Managers unfamiliar with Xamarin technology may find it interesting on a technical level, and those evaluating the use of cross-platform tools may find some gems of wisdom here also – Xamarin’s main competitors are React Native (from Facebook) and Flutter (from Google).
THE APP
FuelAdvisor is the first app I produced for Android, for what was then called the Android Market, now the Google Play Store. The app is a fuel cost calculator that, with three key pieces of information (price per gallon, miles per gallon for a vehicle, and a vehicle’s tank size) and additional input can provide useful numbers for motoroists wanting to control what they spend on gas. The cost of doing a full fill-up, or the number of miles one can drive for a certain amount of money are two examples of figures FuelAdvisor provides, more easily that running the numbers in one’s head.
The app had originally been written in Java back in 2009. It was originally released free of charge, as the Android Market didn’t have infrastructure for handling paid apps, and besides, I’m betting Google wanted to draw as much interest to their shiny new app store as quickly as possible, to take on Apple, which had staked its claim in the marketplace, prior.
The concept for FuelAdvisor was mine, and created at a time when – much like today – fuel prices had spiked. My thought was, if there was a simple way to run the numbers, particularly for those who loathe math, there was an opportunity there. I conceived the screen layout, graphics, and even created a custom TrueType font for the numerals (to look like LCD displays at modern gas stations on their pumps).
But when global conflict erupted recently, and gas prices shot up again (one user told me prices are around $6 a gallon in California for premium-grade fuel!), I figured it would be a good opportunity to re-introduce FuelAdvisor to the marketplace. As stated, I had already done a version for Android, but years later (2017) I produced a native iOS version using Swift for the iPhone platform. A version for Windows had never been done. And I also wanted to give it a refresh in terms of look and feel. Many years of working on software in industry have given me more insight on the design of an app, and I was eager to give my understanding of UI/UX a try for this product.
THE TIMELINE
In mid-March, I started by scratching out notes in an ordinary, spiral-bound notebook with a ballpoint pen. No need to use a fancy wireframe application; having worked on many other applications, I had, in my head, a general direction of where I wanted the new version of FuelAdvisor to go.
Ten days later, I had done my first commit for the project on GitHub to a private repository. At the excellent advice of a former manager, I kept commits frequent, with useful comments documenting my progress.
The month of April was where most of the dirty work was done. After fleshing out the main screens from the original Android version, I played with new graphical backgrounds and new fonts. Xamarin Forms, along with Microsoft’s Visual Studio (my favorite code editor) was the tech stack. I redesigned the icon fairly early in the process.
Even though this was a revisit of a previous version of an app, I decided to keep the color scheme I had chosen before – a different background color for each function screen. I picked a new font, though, rather than letting app text default to a system font – this would provide a more consistent look across platforms.
But there was something I wanted to redesign, and it was the way users entered mileage driven. The original version of the app asked for users to enter the number of miles they thought they’d driven in six “buckets”: weekdays, weeknights, Saturday days, Saturday nights, Sunday days, and Sunday nights. Or, if someone’s “week” ran Tuesday to Tuesday instead, they could repurpose those entry fields accordingly.
My goal with FuelAdvisor is to give good, but not laser-sharp, estimates on how much fuel a motorist is consuming, and how much they’re paying. So I conceived a different way – let the user enter the number of annual miles, and the age of the vehicle in months, divide one by the other, and get an average number of monthly miles driven.
Most of the functionality – trip costs, fill-up costs, distance analysis – didn’t change. But after I’d gotten a semi-final draft, I had an idea: why not add one more screen to let motorists compare two fuel prices for potential savings?
And so the newest feature to FuelAdvisor in 10 years was added. Users enter a first gas price, and then a second. Then they can enter the number of gallons they last put in their vehicle. The calculation tells folks what they might have saved, had they gone with the lower-priced fuel. I drive a pretty energy-efficient subcompact so the differences for me aren’t usually dramatic, but for those who drive SUV’s, large trucks, or anything even larger, this comparison may prove considerably more valuable.
I didn’t stop there. Borrowing from the Fuel Cost Analysis screen, which shows expected expenditures on gas for four time frames running from a week to a month, I added those same four time frames to the Savings Analysis screen to show potential savings for those four time frames.
Anyone who keeps a budget will find this information helpful. And it also shows that maybe five or six cents’ difference in the cost of two gas brands might not add up to the savings we think, even if one station has $3.999 a gallon and the one across the street has $4.019. The Savings Analysis feature helps show this.
DEPLOYMENT
The Android version was ready first, and via the Google Play Console for developers, I got all the assets and metadata out to the Google Play Store. It went live on April 24.
The Windows version was next, but it would be a little bit before I could release it for two reasons. First, while the Debug mode tests of the app were perfect, the Release mode tests had a surprising issue: the custom fonts I had added weren’t showing up – that is, the system fonts were showing everywhere.
Searches online didn’t turn up much, and I figured with Microsoft spending most of their efforts on getting .NET MAUI out, Xamarin Forms was not likely to be a priority. So I raided a previous Xamarin Forms project – Checkbook Genius, a personal finance app for Android – where I had crafted my own handling of custom fonts, retrofitted that into the FuelAdvisor code, and continued.
The second issue was that the Windows Store submission process had changed...dramatically! Microsoft added something called a Partner Center which I had to configure and then I also had to create an Azure account (thankfully for free) because Microsoft’s infrastructure now uses Azure to process UWP app submissions. For a few days, I thought that Microsoft had finally managed to surpass Apple in complexity.
But, eventually, and with a bit of help from some good Microsoft folks, I was able to get FuelAdvisor submitted to the Windows Store. The Windows version went live on May 2.
The iOS release would turn out to be the most surprising and problematic under Xamarin Forms. As with the Windows platform, running the iOS version of the app on physical iOS devices (iPhone and iPad, I have both) would look great – fonts, layouts, everything. So I archived the contents – in which, as I understand it, Xamarin Forms “calls” Apple’s iOS services to generate the resulting digitally-signed IPA executable file.
Using Apple’s Transporter program, I delivered the IPA file to the App Store, and I thought that would be the end of it.
I took a trip the following weekend to visit friends, excited to tell them about my new app. One of them downloaded it, but when she pressed the buttons on the home screen, nothing happened. They were supposed to take you to other pages, but they were completely non-responsive. And I heard from another user of the legacy version of FuelAdvisor that he was observing the same issue.
I nabbed the app from the App Store and was stunned that indeed, most of the buttons on the home screen were non-responsive. Embarrassed, but also a bit angered, I began the process of triage. I downgraded Visual Studio from 2022 to 2019. I simplified some of the code, adding checks for the iOS platform. Nothing worked. So I opened a new GitHub issue with the Xamarin Forms folks – joining two others I had flagged prior – and figured I’d have to brush off the legacy Swift code instead.
Which is what I did. I updated the logo to match the Android and UWP versions, and made a few cosmetic changes but the previous iPhone version of FuelAdvisor written with Swift is substantially the same as the one from 2017. It appears that somewhere between Xamarin’s processing and Microsoft’s, something failed.
To double-check, I pulled down another app I had delivered the previous year, using the same process, but an earlier version of Xamarin Forms. No button issues. What could have happened in the one year is beyond me. When something as basic and critical as an event handler loses something between a Debug run and a Release executable package, something is very wrong.
The iOS release of FuelAdvisor went over the finish line on May 4.
BIGGEST LESSONS AND INSIGHTS
So, for all that activity, I thought it could be beneficial to others who may be evaluating Xamarin Forms at this point in time. Many folks have already dismissed Xamarin Forms as dead or dying, and that .NET MAUI won’t be any better. I still think Xamarin in general as a platform is great for cross-platform development, and many agree with me, but Microsoft has work to do stabilizing it.
Here’s what I learned on this particular project:
Lesson: Xamarin continues to be a work in progress. During this roughly 7-week period, I observed three major bugs, each of which I opened as issues formally on their GitHub portal. One of the biggest was that MAUI, the next version of Xamarin, doesn’t work in terms of inspecting one platform of code at a time, flagging errors from the platforms that aren’t in use. I started off wanting to do FuelAdvisor with .NET MAUI even before it went general availability, but I just couldn’t – the bugs were too obstructive to work around. Even as of the day I wrote this, one of my issues was folded into a new “catch-all” issue to address multiple issues reported by others. This project, though, taught me how to open an issue on GitHub that Microsoft’s developers will see, so it wasn’t a total loss. And, related to that…
领英推荐
Lesson: Xamarin still doesn’t quite get iOS visual rendering entirely correct. In order to get text centered horizontally and vertically on the app’s title bar, I had to add my own special code.
Lesson: Xamarin sometimes mysteriously loses contact via the Pair To Mac service. I observed this for the first time late last year, wondering if my inability to figure out the issue would mean my computer was going bad.
Pair To Mac is a service that Xamarin requires in order to “talk” to a Mac computer as a server for iOS-based instructions and operations, like the archival of IPA files. A pop-up window requires you to specify a Mac computer on your network (wireless or wired, doesn’t matter) at a particular IP address.
From there, Xamarin goes through a series of operations, one of which is creating an SSH connection. But sometimes, that process “gives up” with an unhelpful, general message saying the connection can’t be made.
I was surprised that few other people online were having this problem, but found the solution on one obscure page. It recommended locating a folder called “MonoTouch” using the Windows file manager, and clearing it of a couple of files. I took it a step further and cleared all the files (there’s about a half-dozen of them) before restarting the Pair To Mac wizard. I had to do this several times during the development process.
Lesson: Implementing a dark theme in Xamarin is actually pretty easy. It can be done in the XAML code with a simple attribute that can be bound.
Lesson: A bit of ingenuity can produce a really cool new feature. In FuelAdvisor, when I first did it back in 2009 (!) my thought was that users would know roughly how many miles they drove five days a week, and on weekends. But then I realized that some wouldn’t know that information, and there might be a better way to do it.
My thinking was that the number of miles driven in a week could be computed a variety of ways. One way was based on a simple calculation – take the number of miles on your car and divide it by 52. Over the course of a year, that’s an average, but I’m not after laser surgery here – just a way to give users an idea of what they’re spending. And as far as determining the age of a car (or the amount of time someone had been driving one) I made it easy for users – just enter the month and year you took possession of the vehicle (new or used). It computes the number of months from there. That might sound obvious to some of you, but remember – the whole idea of any kind of calculator is convenience. We could try to grind through the numbers in our heads, but why?
Lesson: Haptic feedback is pretty slick. I’ve used apps that give a little vibrational “jolt” when you touch the screen. I found a way to make that happen for the Android version of FuelAdvisor.
Lesson: Let automation help you write code. When Visual Studio flags a coding error with a red squiggle under the incorrect instruction, if you mouse over the squiggle for 1 or 2 seconds, you’ll see a pop-up hint, “Show potential fixes”. I really like this, and had seen a similar feature in Android Studio.
Lesson: After your app is deployed, if possible, try a download yourself, from the app store where it wound up. This may require login with another account or e-mail address on the mobile platform, but it can be hugely helpful seeing the installation experience from the end user’s perspective. Delete the debug-compiled version of the app from your physical device, then go from square one, from looking up the app with the search box, to tapping “Install”, “Get”, or whatever button or link downloads the app.
Lesson: Cable “rot” could be the reason your app isn’t working as planned, or why it’s taking longer for compilation to complete. During the middle part of my development process, I’d sometimes see Xamarin seemingly stall out at various points in the process. If that’s happening too often, your cable connecting your smartphone to your workstation may be going bad.
How could that happen? Who knows? But I’ve seen it happen consistently over the years, even with better “premium” cables. Since mobile software is all about communication with a remote device – that is, another device a computer “talks” to – a cable that’s in good shape and not producing digital “noise” in the line for whatever reason is critical. Don’t be afraid to swap out cables from time to time, even if they “look” fine – behaviors like stalled compilations should be your first indication a cable is on its way to conking out.
Lesson: Using a font editor to create a custom font adds another bit of visual distinction. Rather than using the system font for numerals – and because I’m a big geek and fan of 7-segment displays – I created my own TrueType font for use in my app. Years ago I learned how to do this with an early version of the well-known Corel Draw program. Now I do it with an excellent application from FontLab called TypeTool 3. For about $50, you can generate your own TrueType font set, useful for your own numerals, symbols, or icons. Once done, you can use your own creations for other projects.
Lesson: You don’t need a fancy wireframe editor to do layouts. I did all of my layouts in a spiral bound notebook, scribbling my ideas with a ballpoint pen. Sometimes fancy tools can get in the way of your natural thought process, and you can get distracted designing something to a particular tool rather than thinking of how the product will look on its own.
Lesson: Amazon’s Appstore is easier to use than Google’s. I was already aware of this, but wanted to include it as a point for some of you out there. Did you know there are actually TWO Android app markets? Most of us know about Google Play Store, which is Google’s own baby. But Amazon has its own store, also, tied to Amazon’s walled-garded ecosystem of Fire devices. Fire OS, in fact, is a fork of Android, but predictably altered with hooks for Amazon.
Google’s workflow used to be relatively simple, but it has mushroomed into at least a dozen different screens you have to know how to navigate to get everything ready. Amazon has a simpler six-tab approach that doesn’t require you to click around as much. I’d like to see Google adapt a simpler approach to submitting Android apps, but I’m not holding my breath, as the new Google Play Console was put into service in recent years.
Lesson: AAB is it for Android distribution, unless you want to distribute an APK “loose”, by yourself. I had read that Google Play Store was going to require all new app installation files to use AAB or Android App Bundle, another format for submitting app works. Within Visual Studio there’s a single drop-down setting to change to select AAB over APK. I thought this was going to be more trouble, but was pleasantly surprised that it wasn’t.
Lesson: Microsoft’s mobile platform complexity doesn’t come from its compiler – it comes from its administrative portal. It had been a while since I released an app for the Windows Store. UWP – Universal Windows Platform – has changed some in recent years. It used to be that all that was necessary was to run a special vertification program that’s part and parcel of Visual Studio, and then uploading the executable file was all that was needed.
For FuelAdvisor for Windows, I was stunned to discover that I now had to create accounts with Microsoft’s Partner Center and also create an Azure account because app submissions now go through an Azure operation. And I was greeted with a whole new bunch of confusing and conflicting terms – Tenant ID, Client ID, Client Key – each of which were referred to with a different name elsewhere.
And now, a UI rant on the UWP submission page: the actual process of submitting individual files – icons or otherwise – does not use an Open Files dialog box where you can choose a group of files. No. You have to specify each file one at a time. And the black Save button is buried all the way at the bottom of the page – a long page of entry fields and other controls. Something as critical as a Save button should either float somehow, always in view, or be at the top of the page. (End of rant.)
Lesson: UWP under Visual Studio has a bug or two of its own. When the time comes to deploy an app to the Windows Store, you have to have a wide variety of different icon file resolutions. Visual Studio tries to make this easy, but it doesn’t work all the way.
On the screen where icons are defined, there are two sections – one for Medium Tiles, and another for the App Icon. The trouble I ran into was a sort of back-and-forth thing. If I defined a tile set that worked for one section, say, Medium Tiles, it would be flagged as the wrong sizes for the App Icon section. And if I made the corrections for the App Icon section, it failed on the Medium Tiles.
I found a workaround, but little things like this can slow down progress.
Tip: If you can use a screen recorder while you work through the machinations of submitting to an app store, do it. My favorite screen recording software is ShareX, a Windows-based application, that is free of charge. (Apple users can use QuickTime, I believe.) The thing about recording your keystrokes in this manner is that it’s easy to go back and watch, on video, just how the heck you got that package upload to work.
Lesson: Running an app in a debugger vs a digitally-signed executable package are potentially two different experiences, and I got burned majorly on this point when in the process of releasing FuelAdvisor. I didn’t have this issue with Android, but I did for both Windows and iOS using Xamarin Forms 5, and it’s a whopper of a problem in my opinion.
From other work environments over the years, I’d observed how running code with a debugger or emulator can look fine, but running the same code as its own standalone executable on a physical device can produce surprising errors or crashes. Working in this situation reminded me of that in an unpleasant way.
For Windows, the ExportFont directive worked just fine as a Debug run, but no custom fonts appeared when an executable package (Release mode) was spun off. I wasn’t the only dev who experienced that, either, and saw much frustration, when searching forums online for solutions.
For iOS, the result was more insidious. Despite the rather complicated nature of the iOS process that developers go through, I was especially shocked when, after using Apple’s own Transporter program to upload the finished IPA package, and once approval by the App Store was granted and I downloaded the finished product, that many of the buttons were NON-RESPONSIVE. That is, you could tap a button expecting something to happen and...nothing would happen.
One user noticed this and I have to say it was embarrassing trying to explain what I thought had happened (some users think software developers are all idiots anyway). I wound up opening a GitHub bug report, but with Microsoft developers trying to bring an already late .NET MAUI (Xamarin Forms 6, originally due November 2021) to completion, I doubt this particular issue will be addressed in a timely manner.
To call this flaw a disappointment for me is a colossal understatement. I had written another app for iOS using Xamarin Forms one year prior, that didn’t have this problem. And I had done a considerable amount of work improving the look and feel of FuelAdvisor (as stated earlier, I do my own UI/UX work), so not being able to roll that out for iOS was a major blow for me. I wound up giving only a slight cosmetic update to the legacy iOS version of the app (which I released back in 2017).
Combined with my strong preference for using Visual Studio as an editor and compilation environment, this issue basically spells the practical end of my interest in iOS as a platform that can be worked on with any hybrid tool. You see, as I understand it, Visual Studio and Xamarin don’t generate the signed executable packages themselves – they call a Mac computer as a server and use Apple’s own processes to get the finished result. And it didn’t work.
If you’re wondering why I seem averse to writing native iOS code, it’s because, frankly, I like very little about Apple and iOS, and I know I’m not alone there. I’m not a fan of Xcode – it’s not as polished an editor as Visual Studio (my favorite) or Android Studio (my second favorite). The way to “wire up” controls – IBOutlets – where you click and drag to make connections – may be well-intentioned but I don’t care for it. And then Apple makes you jump through all kinds of hoops technically – app ID’s, provisioning profiles, distribution certificates, keychains, AND having to get all such assets through their computers in Cupertino. Both Android and Windows let you create digital certificates locally, on your own workstation.
TAKEAWAYS
For the time being, I’m more or less done with iOS (I took a look at Cordova around the time I wrote this, but that won’t be useful for larger offerings). I’ll always have the benefit of having worked on both Objective C and Swift applications, as well as dealing with the Apple ecosystem. But I got into software development originally because I’m a big nerd, and I enjoy so much about it. iOS and Apple have become overly complicated, to the point that even using a cross-platform development tool like Xamarin Forms, doesn’t work.
I have never made a single cent from any apps with iOS (I have with both Android and Windows) so it’s becoming increasingly harder to justify sending that $99 every year just to keep my apps in the App Store.
I’m also reminded that system-level developers – the ones who give us the tools on which we depend to build applications for the public – have limits, also. They’re limited by time, by budgets, by many other complicating factors. And the result of that is, sometimes, stuff just doesn’t work.
Android is a very strong mobile platform, even though Apple’s marketing machine has an almost hypnotic influence over American culture and its user base. But Windows, based on best-of-breed editor Visual Studio and the .NET platform, reinforced, in my mind, the notion that it’s a decent platform, also, even if no one uses Windows Phones anymore.
I was once asked in an interview what I thought a key technology would be for the next 20 years. My answer was the C# language, which Microsoft created and owns. C# is largely what Xamarin Forms (and also the Xamarin native variants) are written in, and is a rich, powerful and consistent language with the very good Intellisense feature. Kotlin and Swift have their benefits (I have used both), but C# is my language now. And Xamarin Forms, in whatever form it takes, be it .NET MAUI or something else, will be my first consideration if I want to release an app for multiple mobile platforms.
#xamarin #xamarinforms #mobile #mobiledevelopment #android #google #ios #swift #windows #windowsstore #software #softwaredevelopment #smartphone #smartphones #app #applications #visualstudio #xcode #androidstudio #csharp #dotnet #maui #dotnetmaui?