I should have written this post months ago, I kept postponing it but now
here it is.
For the first half of the year I’ve been writing a relatively big Android
application for German Sony branch. They were promoting Sony Xperia Android line
of devices and as a part of this promotion they wanted an application that would
guide bikers through the cities of Berlin and Munich. They also arranged
rent-a-bicycle with Xperia 2 phone mounted on the cradle (cradle that would
allow charging through pedaling, no less).
The application allows user to:
- make a reservation for free rent-a-bicycle (expired, not available any
more) - selection of city (Berlin, Munich)
- selection of three routes for each city
- customization of predefined route points
- rich information for every route point
- starting, pausing and stopping route
- voice information when either point of interest or route point Is hit
- turn-by-turn navigation
- 2d/3d map perspective
The application itself is written in C# with Xamarin for Android. There were two reasons for choice of Xamarin. One is multiplatform capability and the other is that I am much more skilled/productive in .net environment. The architecture of choice is, of course, MVVM (custom stuff, INPC provided by Fody) which yield numerous advantages, mostly big percentage of code sharing among different platforms (nice separation from UI) and combined with DI/IoC (Autofac) very unit-testy (Nunit, Moq). The (huge pile of) data (multimedia stuff, route points, points of interest, etc.) is loaded when application starts using HttpClient and Json.NET. If data changes, only the changes are downloaded next time to avoid data traffic as much as possible. Almost all the logic is implemented in a PCL because of portability and testability (this way one can use unit tests written in Windows library to avoid unnecessary troubles with Android world).
Besides the usual Android UI views I used Google Maps Android for map display and The Google Directions API for turn-by-turn navigation and route calculation (it requires data connection).
For debugging during the development I’ve used Genymotion, the fastest and most feature rich emulator there is. The only problem with it is that it doesn’t have Google Play support baked into Android images (it is required because of Google Maps) because of … Google legal issues, I guess. There is a workaround and everything works quite well (though Android guest might report a crash in one of Google Play applications here and there). The other part of testing was done on real devices, such as Galaxy Nexus (yes, the old one) and Xperia2 mini (the device used on rent-a-bicycles).
There were some interesting takeaways I’ve learned during the development.
- First and most important is that Xamarin is suitable for Android development-no surprise here. I was/still am on beta channel and as all beta updates I had minor problems here and there, but only at development time. No problems for release version.
- Double garbage collection might bite you if you are not careful. Typical example I had is that during activity creation I’ve initialized maps fragment and if activity was recreated a few times (i.e. during device rotation) the application would crash due to the out of memory exception. I wasn’t doing anything wrong but still the app kept crashing in this situation. The reason is documented but it might not be that obvious. The thing is that Xamarin doesn’t know the memory pressure (nor you can inform it, like you can with .net) when it holds reference to a Java object (i.e. maps fragment). Thus each time the activity was recreated the Java memory kept raising “dramatically” but the memory from Xamarin point of view was increased only by a reference to Java object (few bytes that is). So the Xamarin GC wasn’t aware that it held quite a lot of memory (though it knew the Xamarin objects were ready for GC) and app crashed eventually. The solution is to invoke garbage collection manually in such situations.
- Avoid compass. Compass readings have to be avoided when moving as it just offsets the faster you go. And even when not moving, different devices might go just nuts and create all sort of false readings (calibration might help). GPS readings are much more reliable but it requires movement.
- Good luck talking to Google for using Directions API for business
Since the Stadthelden application has been published for free in June, it was downloaded between 10.000 an 50.000 times so far. Currently it is rated 3.4 which is quite good I’d say. Some rationale for ratings really surprised me though, most interesting was a guy rating it 1 because it supports only two cities.
Anyway, overall it has been a pleasant experience developing it and using Visual Studio/Xamarin tools. If I were to do it again I’d probably go with Xamarin Forms, but that wasn’t available back then.