Monday, June 03, 2013

Issues when deploying a release version of a Xamarin app made with MVVMCross on a device (Android)

First, you can send to someone the .apk file representing the app and he can install it on the device.
There are few deployment options:
  • Via a Website – A Xamarin.Android application can be made available for download on a website, from which users may then install the application by clicking on a link.
  • By e-mail – It is possible for users to install a Xamarin.Android application from their e-mail. The application will be installed when the attachment is opened with an Android-powered device.
  • Through a Market – There are several application marketplaces that exist for distribution, such as Google Play or Amazon App Store for Android.
See more here http://docs.xamarin.com/guides/android/deployment,_testing,_and_metrics/publishing_an_application
I am trying to deploy the app on a device by sending the .apk file to someone to test it on his device.
First, I need to compile the app in Release mode and sign it. When compiling, Xamarin produces a signed version of the app.
In the \bin\Release folder, there is yourapp.apk and yourapp-Signed.apk files.

Second, I encountered different problems when running the app in Release mode on the device, there were a number of issues with MVVMCross.

The issues are related to the Xamarin linker. If you look to the build properties of the Xamarin app (In Xamarin Studio, that's project Options \ Build \ Android Build \ General tab), there are few linker options:

  1. Don't Link
  2. Link SDK Assemblies
  3. Link All Assemblies

Linking is described in Xamarin docs: http://docs.xamarin.com/guides/android/advanced_topics/linking
'Don't Link' option produces the largest app files, linker not being enabled. The app will definitely work without an issue.
Issues start appearing with the two options, becausue with these two options, the linker is enabled.
The issues appear at runtime, for example I was getting MvvMCross errors written in the application output, mentioning about bindings / events not working right.

When using the 'Don't link' linker option, the app size was 20 MB! When switching to 'Link SDK Assemblies', it was 7 MB!
The idea is to use 'Link SDK Assemblies' linker option and do the necessary to make linker do the right thing.

A solution is to force the linker include code from MVVMCross, using a dummy class.

class LinkerIncludePlease
{
private void IncludeVisibility(View widget)
{
widget.Visibility = widget.Visibility + 1;
}
private void IncludeClick(View widget)
{
widget.Click += (s,e) => {};
}
private void IncludeRelativeLayout(RelativeLayout relativeLayout)
{
relativeLayout.Click += (s, e) => { };
}
public void Include(INotifyCollectionChanged changed)
{
changed.CollectionChanged += (s,e) => { var test = string.Format("{0}{1}{2}{3}{4}", e.Action,e.NewItems, e.NewStartingIndex, e.OldItems, e.OldStartingIndex); } ;
}
}

 More info here:
http://stackoverflow.com/questions/16924178/issues-with-mvvmcross-and-linking-on-android/16924320?noredirect=1#comment24433662_16924320
http://stackoverflow.com/questions/11349864/mvvmcross-monotouch-fail-to-bind-properties-on-a-real-ipad-but-it-works-on-th (including the info and links from comments)
http://spouliot.wordpress.com/2011/08/11/when-to-link-monotouch-applications/

Note there are other options, in the same Build tab: Use shared Mono runtime and Fast assembly deployment. These are not meant to be used on Release (if you have over the options, the explanation is pretty good and you should get a good idea of how they work).



1 comment:

Slodge said...

You shouldn't do 'Link all assemblies' - instead just add your LinkerPleaseInclude.cs - or you can also use an xml link file - a bit like this one https://github.com/reactiveui/ReactiveUI/blob/rxui5-master/ReactiveUI.Platforms/Cocoa/Buildsupport/Linker.xml - but with monodroid entries