Appearance
Migrating an application from Xamarin.Android to Kotlin
Disclaimer: this article isn’t about the why but more about the how and what.
Introduction
Earlier this year I was fortunate to be able to attend Google IO once again. One of the big announcements was that Kotlin was now fully supported by Google for use in Android. At IO17 I attended a few of the sessions on Kotlin and also did a few of the Code Labs and came away thinking this is a neat language. I started to think that it would be worthwhile to convert one of my applications over to Kotlin. This article details my experience in this process.
My Mobile Background
I started building native mobile applications in 2009, first on iOS in Objective C. In late 2010 I started looking at Xamarin as a cross-platform way to write mobile apps using C# as the language. I ported one of my apps from Objective C to Xamarin iOS. At that point I also needed to create an Android version of this application and rather than writing in Java I chose to use Xamarin Android (XA). Although I have some experience in Java/JNI (dating back to 1995ish) in the WORA (write once, run anywhere) era I’ve never done a lot with Java. Since 2010 I’ve written many applications for clients using the Xamarin toolset.
One thing to point out in Xamarin development is that there are two major approaches to application development
- write to the native APIs using a thin wrapper
- use Xamarin Forms
For various reasons I have always written to the native APIs for both iOS and Android. This point is key as you will see it was a factor that made my migration easier.
The Project
The application I chose (a sports application) is only about 11k lines of C# code (this excludes the 7k line Resource.designer.cs file). Although many of you might consider this to be trivially sized, I believe this to be an good size for a first migration. Additionally this application also exercises various features including a local SQLite database, REST services, push notifications, administrative login and score input.
Getting Started
After I got back from IO17 I downloaded the alpha build of Android Studio 3 and created a test project and did the basic “Hello World” Android app. In order to learn Kotlin (besides googling and the Kotlin language website) I used these resources
- Kotlin Koans exercises
- the print version of Kotlin in Action
- Kotlin for Android by Antonio Leiva
I also was able to attend 2 other conferences which were helpful:
- 360|AnDev (Denver in July)
- KotlinConf (San Francisco in November)
After the Hello World project I played around with a few of the templates in Android Studio and settled upon one that mimicked my application (drawer navigation). One key point:
TIP
Don’t try to get everything right initially—just go and start writing code initially so you can learn.
In other words during the early stages I suggest you write to learn, but plan on throwing it away. Don’t worry if it is good code. I used this approach for about 2 months (on a very part-time basis) while I tried out various things and extended the Android test app, Finally in July I created a new project that would eventually be the foundation of my production app
Porting
First off with the bad news:
You can’t be half pregnant
If you have an Android app written in Java you can start learning Kotlin by adding in new features in Kotlin. Conversely, in Xamarin this is an all or nothing endeavor. You’ll want to carefully weigh the number of lines of code and consider what third party components, libraries, etc. you are using and what you will replace them with.
The good news in porting from XA is that if you’ve written to the native APIs your resource files will work with no modifications. In addition, all of your Fragment and Activity lifecycle methods will match and so structurally your code will be very similar.
Note: If you’re wanting to port an application written in Xamarin Forms you will have a lot more work ahead of you. All of your layout files (XAML) will need to be redone using Android layout files. Additionally all of your C# MVVM code will need to be rewritten.
I chose to create the resources manually in Android Studio and then copy/paste the XML from XA into each resource file. I did this so that as I worked through the app I could look at the XML to make sure there were no parsing errors, etc. I did find a few cases where I used attributes that were deprecated or just bad.
In most cases porting from C# to Kotlin is pretty straightforward. Although there is no copy/paste converter for C# to Kotlin, I don’t find this to be a big loss. I do not recommend using a converter as you will learn more by converting your code manually. I did find one occasion to use the Java to Kotlin converter when I needed to convert a Separated List adapter. Many years ago I ported it from Android to C#. I found it easier to go back to the original Java source code and use the Java to Kotlin converter and then modify it as appropriate.
One challenge I found was figuring out constants/enums, etc. as it seems like the Xamarin guys took some liberty in naming values and putting them in completely different namespaces from the Java/Kotlin namespaces. For example:
csharp
C#
DescendantFocusability.BlockDescendants
kotlin
Kotlin/Java
ViewGroup.FOCUS_BLOCK_DESCENDANTS
Another challenge I ran into was with asynchronous programming. If you’ve adopted C#’s async/await you’ll need to think about what approach you wish to use in Android. After attending the Kotlin Conference and watching Roman Elizarov’s sessions on coroutines I opted to use coroutines even though they are marked experimental. Note: Jetbrains is encouraging people to use coroutines in production; experimental is a misnomer in my opinion.
The following snippet is what I came up with–this example is one of the few cases where the Kotlin code was slightly more verbose than the C#.
csharp
C#
games = await service.Load(id, field.Id);
renderResults()
kotlin
Kotlin
launch(UI) {
games = service.Load(id, field.Id).await()
renderResults()
}
Some of the components I used are listed below along with their Kotlin/Android equivalents.
Xamarin | Kotlin |
---|---|
AndHUD | Anko Indeterminate Progress Dialog |
SQLite.net | Anko SQLite |
ServiceStack C# | ServiceStack Android |
Redth GCM.Client | Firebase Cloud Messaging |
Crypto Obfuscator | Proguard |
Azure Mobile Center | Firebase Crashlytics |
Technical Debt
Rather than port an outdated technology or piece of code I chose to address a few areas of technical debt by updating them to the latest technology.
- Added in moderate use of Databinding
- Updated Google Cloud Messaging (GCM) to Firebase Cloud Messaging (FCM). This also required a back-end server change as well.
- Added notification channels (albeit just one)
- Added Google Analytics (perhaps not considered technical debt but rather a feature)
- Converted Icons to Android O Adaptive Icons
Are We There Yet?
Even after finally getting to feature complete I was reminded of this:
Hofstadter’s Law: It always takes longer than you expect, even when you take into account Hofstadter’s Law.
Some issues I ran into included dealing with
- back stack and fragment crashes
- manifest merge issues related to FCM and permissions. I had to use a setting to remove the merged attributes
- crashes related to proguard
- crashes related to errors in porting code (usually due to carelessness on my part)
A lot of hours were spent in testing and debugging code during the final phase.
Takeaways
As I write this now the Kotlin version of the application has been released to the Google Play store. Time will tell how well the port stands up with regards to maintenance, time to add new features, stability, etc.
This project took a total of 6 months. However, there were many weeks where nothing was done as this was a low priority project.
The Kotlin application is significantly smaller in both APK size and lines of code (LOC).
Xamarin | Kotlin |
---|---|
11k LOC | 4.4k LOC |
APK 22MB | APK 2.3MB |
Some of you will look at that and wonder why the Kotlin LOC was so much smaller than the C#. Some of this was due to elimination of dead or commented out code. Another portion of code was in a shared library between iOS & Android and some of that shared code wasn’t being used in Android and so it wasn’t ported. C# POCO classes are a lot more verbose than Kotlin’s data classes (that amounted to about a 1K difference). I’ll have to do further analysis to figure out where the other differences were.
As for the APK size difference, the Kotlin APK was generated using Proguard while the Xamarin version did not. However, the Proguard optimizations only reduced the APK size by around 1MB in size. I believe the main size differences were to the number of DLLs that Xamarin includes in the APK. When you’re designing for the next billion every megabyte counts and this was a big win for Kotlin.
One other surprising benefit of the migration is performance–the Kotlin version is notably faster and I was not expecting that. The Xamarin version has never felt slow but next to the Kotlin version I found myself waiting longer for screens to load, etc.
All in all I’m pretty happy with how the application turned out. The Android Studio environment is also top notch. If you’re considering a similar migration I hope this article will be of help in making the decision to port or not to.