Redevelop a native app with Xamarin part 1
This blog series will give you insights in what it takes to (re)build your app based on the Xamarin development platform. It will cover the struggles, lessons learned, some code examples and the steps taken before we published it to the Google Playstore.
Suneco is investing a lot in exploring the landscape of mobile development. The investigation so far has led us to Xamarin as THE platform to use for developing cross-platform mobile apps. Most of the teams used Xamarin during Suneco’s mobile hackathon (written in Dutch) and John has shared the following blogs as a result of his research: Speed up your time to market with Xamarin and Boost your Xamarin native projects with MvvmCross.
As Xamarin seems the way to go for upcoming projects, it got time to put our knowledge to the test. Our mission is to build an app and publish it into the Play / App stores. In the end, we have the start to finish experience developing and publishing an app with Xamarin.
The app will be published to the big audience which means that it should be useful and that we must prevent a prototype look-and-feel that we normally have in a regular R&D project. Therefore, we decided to pick up an old and already published native app project that has been created for researching purposes. The app is called “BirdingApp” and is only published in the Google Play store because it is a native Android project created with Android Studio.
The app is basically a bird encyclopedia with a search engine, bird details, sound samples and a checklist function for creating a “bird must see bucket list”. The data of this app is driven by a WCF service with all the bird info required for the app.
In a series of blogs we will have a closer look to the struggles we had, recommendations, lessons learned and so on. This blog will kick-off the series which will hopefully give you some new insights.
Setting up functional and technical requirements
The goal was simple, we had to re-build the exact same app as described in the Google Play Store but with some minor adjustments.
- Google Analytics should be fed by the Google Tag Manager instead of the Google Analytics API. Using the Google Tag Manager enables us to use Google Firebase alongside Google Analytics and is more future-ready. Firebase does not have all the fancy functionality that Google Analytics has but its functionality will be expanded quickly.
- Bird details should be expanded with Wikipedia information.
- Implement a new and fresh design.
- Use Xamarin Native and MvvmCross to share business and presentation logic for the different platforms. The choice for Xamarin native over Xamarin Forms is still debatable but we have chosen Native over Forms because then we could re-use the presentation from the original axml files which saved us a lot of work.
The plan was simple. We had to setup a Xamarin blank native portable project in Visual Studio, install the required MvvmCross NuGet packages and adjust the business layer into Models, ViewModels and services. More info about this structure is described in the following blogpost Boost your Xamarin native projects with MvvmCross. For persistent storage, we used SQLite. The checklist items will be stored with this technique but we also used it for storing simple settings parameters because there is no Xamarin library or package available that can write to each of the several platforms local storage.
We were able to re-use a lot of the architecture that was created in the old native android project like the models and service logic. Also, much of the code could be re-used with minor syntax fixes because Java looks a lot like C#.
We want to reach our goal to publish the app with a minimum effort. That is why we first developed and published the Android version before beginning with the iOS and Windows Phone version. One of the biggest advantages of this approach is the presentation layer. The xml-based activities almost exactly match the axml activity files in the Android project. This was a matter of copy-pasting, fixing minor syntax differences and implement new resources for the new design.
The biggest difference in de codebase compared to the old Android Studio project is the MVVM approach. In new projects, we want to have as little logic as possible in the .cs files of the activities since we want this to be ‘shared’ logic in the ViewModels. Therefore presentation binding is used for all the UI interaction.
From this point on for each screen in the app it was a matter of:
- Copy activity xml;
- Create ViewModels for the activity and bind properties to the activity xml;
- Create services to connect to the online BirdAPI;
- Create services and use MvvmCross dependency injection for controlling platform specific functions in the ViewModels.
This journey wasn’t exactly a walk in the park. The world of Xamarin is relatively young so it still has some flaws and the set of available MvvmCross UI components is not yet complete to meet all our requirements. The following challenges will be covered in the blogseries:
- MvvmCross > Creating Bindable controls;
- MvvmCross > Creating Bindable ViewPager;
- MvvmCross > Creating Bindable EditSearchBox;
- MvvmCross > StringToTypeFaceConverter;
- MvvmCross > LinkerIncludeDummy;
- Implementing the TagManager;
- Clearing the activity stack with the mvxAndroidViewPresenter;
- Best way to translate a lot of string values;
- Publishing to the store.
Create Bindable Controls
When we take a closer look to Xamarin and the MvvmCross framework we can say that it’s a great platform but it still has its flaws and sometimes it feels like an unfinished product. MvvmCross comes with a set of controls that will cover the most frequently used UX-components but it is very likely that you need to bind data to a component that does not exists (yet) in the MvvmCross framework.
In our case, we had to implement a simple ImageGallery component which should be bound to a collection of Images in the ImagesDetailViewModel. This brought us to develop a Bindable ViewPager.
A wise man once said, “do NOT just start developing a component from scratch, someone else probably already did it”, and so I’ve found the following solution. Mr. Cheesebaron’s code setup looked alright, and with some minor adjustments it would fit perfectly in to my project!
The solution is based on a component that inherits from a ViewPager component. Using an adapter for controlling its data and presentation is the familiar way to go in Android development so this is all packed up in the BindablePagerAdapter. This is where most of the magic happens.
The ItemSource property in this adapter is set to the ObservableCollection in the ViewModel. The change event of this collection is bound to an eventHandler with the WeakSubscribe method:
The EventHandler calls the base.NotifyDataSetChanged() which causes the screen to apply changes and show the collection of any layout. These parts of code makes the ViewPager bindable.
In the BirdingApp we needed to not only bind the image but also the corresponding credits because all images are under the Creative Commons license model.
We have the ImagesDetailViewModel which holds the ObservableCollection of ImageViewModels:
The ImageViewModel is a very simple class that has a property for the image and the credits:
This ImageViewModel will be the context for a custom layout for each “Page” in the ViewPager:
Eventually implement the ViewPager and bind the Images collection to the ItemSource:
There you go, the ImageGallery with credits is born. The bindable ViewPager can serve multiple purposes and can be a pager control for any kind of layout. All you need to do is define another DetailItemTemplate.
This is it for part one! Hopefully this blog will give you insights in what it takes to (re)build your app based on the Xamarin development platform. It is not that hard, especially when you make use of MvvmCross where you can share a lot of presentation logic in ViewModels. This will reduce the impact of implementing the next mobile platform (iOS in our case).
It’s amazing how easy you can extend the set of bindable controls. We had a customized bindable ViewPager up and running within two hours based on Mr. Cheesebaron’s code, thanks a lot mate, you’re a hero!
Was this blog useful to you? Then keep an eye on ours blogs. The next part will be posted shortly.
Onze technische blogs zijn in het Engels. Dit doen wij omdat wij menen dat technische kennis van Sitecore en Sitefinity grensoverschrijdend moet zijn. Wij leren veel van buitenlandse developers, wij delen onze kennis ook graag met hen. Mochten er in de code fouten zitten of punten ter verbetering, dan gaan we graag het gesprek aan.