Add custom tiles to map in Xamarin Forms

If we want to use other maps than the platforms default in our apps we need to provide tiles to the map view. To do that we need to create a custom renderer per platform.

iOS
In iOS we need to create an url template that contains {x}, {y} and {z}. Those be replaced with values from the map engine.

protected override void OnElementChanged(ElementChangedEventArgs<View> e)
{
    if(e.NewElement != null)
    {
        var map = (MKMapView)Control;
 
        var urlTemplate = "https://urltomaptiles/{x}/{y}/{z}";
        var tileOverlay = new MKTileOverlay(urlTemplate);
 
        map.OverlayRenderer = OverlayRenderer;
 
        map.AddOverlay(tileOverlay);
    }
}
private MKOverlayRenderer RenderOverlay(MKMapView mapView, IMKOverlay overlay)
{
    var tileOverlay = overlay as MKTileOverlay;
 
    if(tileOverlay != null)
    {
         return new MKTileOverlayRenderer(tileOverlay);
    }
 
    return new MKOverlayRenderer(overlay);
}

If we are getting tiles from a service that not supporting the url format with x-,y- and z value we can customize the url. To do that we need to subclass MKTileOverlay and override the URLForTilePath method. In that method we will write the code that created the url. I recommend to create a helper class for that so we can reuse it on the other platforms.

public class CustomTileOverlay : MKTileOverlay
{
     public override void LoadTileAtPath(MKTileOverlayPath path, MKTileOverlayLoadTileCompletionHandler result)
     {
         base.LoadTileAtPath(path, result);
     }
 
     public override NSUrl URLForTilePath(MKTileOverlayPath path)
     {
         //Here we write the code for creating the url.
         var url = MapHelper.CreateTileUrl((int)path.X, (int)path.Y, (int)path.Z);
 
         return new NSUrl(url);
     }
}

Instead of creating a MKTileOverlay we will create a CustomTileOverlay and add it to the map.

map.AddOverlay(new CustomTileOverlay());

Android
Except to subclass MapRenderer we also need to implement the IOnMapReadyCallback interface. The method OnMapReady will handle when the GoogleMap object is ready so we can work with it. But first we need to request the GoogleMap object in the override of the OnElementChanged method.

public class ExtendedMapRenderer : MapRenderer, IOnMapReadyCallback
{
    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
    {
        base.OnElementChanged(e);
 
        if(e.NewElement != null)
        {
            ((MapView)Control).GetMapAsync(this);    
        }
    }
 
    public void OnMapReady(GoogleMap googleMap)
    { 
        var options = new TileOverlayOptions();
        options.InvokeTileProvider(new CustomTileProvider());
        googleMap.AddTileOverlay(options);
    }
}

In Android we always need to create an own tile provider.

public class CustomTileProvider : UrlTileProvider
{
    public CustomTileProvider() : base(256,256) {}
 
    public override URL GetTileUrl(int x, int y, int zoom)
    {
        //Here we write the code for creating the url.
        var url = MapHelper.CreateTileUrl(x, y, zoom);
 
        return new URL(url);
    }
}

UWP (Windows 10)
As in iOS, UWP using an url that contains {x},{y} and {z} that will be replaced by the map engine.

protected override void OnElementChanged(ElementChangedEventArgs<Map> e)
{
    base.OnElementChanged(e);
 
    if (e.NewElement != null)
    {
        map = Control as MapControl;
 
        HttpMapTileDataSource dataSource = new HttpMapTileDataSource("https://urltomaptiles/{x}/{y}/{z}");      
        MapTileSource tileSource = new MapTileSource(dataSource);
        map.TileSources.Add(tileSource);
 
     }
}

If we want to modify the url we using the UriRequested event on HttpMapTileDataSource.

HttpMapTileDataSource dataSource = new HttpMapTileDataSource();
dataSource.UriRequested += DataSource_UriRequested;

The code for modifying the url is placed in the event handler.

private void DataSource_UriRequested(HttpMapTileDataSource sender, MapTileUriRequestedEventArgs args)
{
    var deferral = args.Request.GetDeferral();
 
    //Here we write the code for creating the url.
    var url = MapHelper.CreateTileUrl(args.X, args.Y, args.ZoomLevel);
    args.Request.Uri = new Uri(url);
 
    deferral.Complete();
}

How to solve Xamarin.Forms android build error after updated to Forms 2.0+

Exception while loading assemblies: System.IO.FileNotFoundException: Could not load assembly 'Microsoft.Windows.Design.Extensibility, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. Perhaps it doesn't exist in the Mono for Android profile?

If you updated the nuget packages for Xamarin Forms to 2.0+ and the android project stops to build there are a simple solution. Just delete the references which ends with .Design. In my project it was: Xamarin.Forms.Core.Design, Xamarin.Forms.Xaml.Design and Xamarin.Android.Support.Design. I have read about a solution to add the assemblies Microsoft.Windows.Design.Extensibility and System.Xaml. I don’t know if it will work, I think to delete the .Design references is a better solution so I never tried to add those assemblies.

Xamarin.Forms and large images in android apps

Are you getting out of memory exception when your running your Android app? It’s common that the reason is that a large image is loaded. If it’s the case, take a look at this article at the Xamarin developer portal, http://developer.android.com/training/displaying-bitmaps/load-bitmap.html.

But how to implement it when you’re building your apps with Xamarin.Forms? In this post I will show one solution how to implement it. We will do it with an custom view and a custom renderer.

First we will create the new view that will inherit from the standard Image view, I will name it LargeImage. While we doesn’t want the default behavior we need to create our own source property of type string, I name it ImageSource. While we just want to change the behavior for the Android app and not for Windows and iOS we will set the base Source property in the property changed handler of the ImageSource property if the code not is running on Android.

public class LargeImage : Image
{
        public static readonly BindableProperty ImageSourceProperty =
        BindableProperty.Create("ImageSource", typeof(string), typeof(LargeImage), default(string), propertyChanged: (bindable, oldValue, newValue) => 
        {
            if (Device.OS != TargetPlatform.Android)
            {
                var image = (LargeImage)bindable;
 
                var baseImage = (Image)bindable;
                baseImage.Source = image.ImageSource; 
            }
        });
 
        public string ImageSource
        {
            get { return GetValue(ImageSourceProperty) as string; }
            set { SetValue(ImageSourceProperty, value); }
        }
}

Next step is to create a renderer for our new view. While we need the default Image behavior except for handling the source the renderer will inherit from ImageRenderer.

This renderer will only work for images in the Drawable folder, so if you have other type of image sources you need to modify the code.

In the renderer we need to handle the ImageSource property, we will do that in the OnPropertyChanged method. While we doesn’t want to run the code before the image has width and height we added a if-statement that check if width and height is greater than zero. But we just want it to run once because of that width and height is greater than zero, because of that i have added a flag that I named _isDecoded. If ImageSource changed the code will run because that e.PropertyName will be ImageSource.

[assembly: ExportRenderer(typeof(LargeImage), typeof(LargeImageRenderer))]
namespace SampleApp.Droid.Renderers
{
    public class LargeImageRenderer : ImageRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
        {
            base.OnElementChanged(e);
        }
 
        private bool _isDecoded;
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
 
            var largeImage = (LargeImage)Element;
 
            if ((Element.Width > 0 && Element.Height > 0 && !_isDecoded) || (e.PropertyName == "ImageSource" && largeImage.ImageSource != null)) 
            {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.InJustDecodeBounds = true;
 
                //Get the resource id for the image
                var field = typeof(Resource.Drawable).GetField(largeImage.ImageSource.Split('.').First());
                var value = (int)field.GetRawConstantValue();
 
                BitmapFactory.DecodeResource(Context.Resources, value,options);
 
                //The with and height of the elements (LargeImage) will be used to decode the image
                var width = (int)Element.Width;
                var height = (int)Element.Height;
                options.InSampleSize = CalculateInSampleSize(options, width, height);
 
                options.InJustDecodeBounds = false;
                var bitmap = BitmapFactory.DecodeResource(Context.Resources, value, options);
 
                //Set the bitmap to the native control
                Control.SetImageBitmap(bitmap);
 
                _isDecoded = true;
            }
 
        }
        public int CalculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight)
        {
            // Raw height and width of image
            float height = options.OutHeight;
            float width = options.OutWidth;
            double inSampleSize = 1D;
 
            if (height > reqHeight || width > reqWidth)
            {
                int halfHeight = (int)(height / 2);
                int halfWidth = (int)(width / 2);
 
                // Calculate a inSampleSize that is a power of 2 - the decoder will use a value that is a power of two anyway.
                while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth)
                {
                    inSampleSize *= 2;
                }
            }
 
            return (int)inSampleSize;
        }
    }
}

MvvmLight Navigation Extension

When navigating in iOS we can choose to do a modal navigation. That means that we open a page that is on top of the other pages and not included in the navigation stack. When using MvvmLight we only have one method (NavigateTo) when we want to open a new page.

While I want to use MvvmLight and open “modals” I have created a MvvmLight extension for iOS (for storyboards only in this pre version) and Android, https://www.nuget.org/packages/MvvmLightNavigationServiceExtension. If you’re interested in the source, it will be at GitHub, https://github.com/dhindrik/MvvmLightNavigationExtension.

While this is a pre release, feedback is very welcome!

Using the extension from shared code
To use it in your ViewModels you need to add the namespace to the class.

using MvvmLightNavigationExtension;
var navigation = ServiceLocator.Current.GetInstance();
navigation.OpenModal("Page2");

Setup
We will configure the NavigationService in same way as when we using NavigationService from MvvmLight but we using NavigationServiceExtension() instead of NavigationService and our instance of NavigationServiceExtension should be registered to both INavigationService and INavigationServiceExtension.

iOS:

 var nav = new MvvmLightNavigationExtension.iOS.NavigationServiceExtension();
 nav.Initialize((UINavigationController)Window.RootViewController);
 nav.Configure("Page1", "MainView");
 nav.Configure("Page2", "PageView");
 
container.RegisterInstance(nav);
container.RegisterInstance(nav);

Android:

 var nav = new MvvmLightNavigationExtension.Droid.NavigationServiceExtension();
 nav.Initialize():
 nav.Configure("Page1", "MainView");
 nav.Configure("Page2", "PageView");
 
container.RegisterInstance(nav);
container.RegisterInstance(nav);

MvvmLight and Xamarin.Android

Last week I wrote a blog post about Xamarin.iOS and MvvmLight. Now it’s time for the second post about MvvmLight, this time about how to use it with Xamarin.Android.

Because I put the ViewModels in a separate project I can use the same ViewModels for both Android and iOS.

First we install the NuGet package for MvvmLight to the Android project.

Install-package MvvmLightLibs

The ViewModels that we will use is the same as in the iOS app and it will look like this.

public class MainViewModel : ViewModelBase
    {
        private string _name;
 
        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
                RaisePropertyChanged("Name");
            }
        }
 
        public RelayCommand Send
        {
            get
            {
                return new RelayCommand(() =>
                {
                        var nav = ServiceLocator.Current.GetInstance<INavigationService>();
                        nav.NavigateTo(Views.Hello.ToString(), Name);                    
                });
            }
        }
    }

Navigation

MvvmLight has a INavigationService interface that uses for navigation and each platform will have their own implementation. For Android we will do the configuration in MainActivity. Important is to check if navigation already has been initialized. The code will just run once.

if(!_isInitialized)
{
      var nav = new NavigationService();            
      nav.Configure(Core.Views.Main.ToString(), typeof(MainActivity));
      nav.Configure(Core.Views.Hello.ToString(), typeof(HelloActivity));
 
     _isInitialized = true;
}

In my example I using Autofac for IoC, we can also use the IoC container that is in the MvvmLight package. When we have created the NavigationService we had to register it in the IoC container as a INavigationService.

var builder = new ContainerBuilder();
builder.RegisterInstance<INavigationService>(nav);
 
builder.RegisterType<MainViewModel>();
builder.RegisterType<HelloViewModel>();
 
var container = builder.Build();
 
var serviceLocator = new AutofacServiceLocator(container);
 
ServiceLocator.SetLocatorProvider(() => serviceLocator);

To navigate we will resolve the INavigationService interface and use the NavigateTo method.

var nav = ServiceLocator.Current.GetInstance<INavigationService>();
nav.NavigateTo(Views.Hello.ToString(), "Navigation paramter");

To retrieve the parameter we are using the GetAndRemoveParameter in the NavigationService class. Note that this is an Android specific method so we have to cast the INavigationService to NavigationService.

var nav = (NavigationService)ServiceLocator.Current.GetInstance<INavigationService>();
var param = nav.GetAndRemoveParameter<string>(Intent);
 
ViewModel = ServiceLocator.Current.GetInstance<HelloViewModel>();
ViewModel.Name = param;

Databindings

When using MVVM we want to use data bindings. In Android we have to create the bindnings in code. MvvmLight will help us with that. In the class for the Activity we hade to add a using to the MvvmLight helpers.

using GalaSoft.MvvmLight.Helpers;

The activity also has to inherit from ActivityBase (GalaSoft.MvvmLight.Views.ActivityBase).

public class HelloActivity : ActivityBase
{

The MvvmLight helper namespace will contains the extension methods SetBinding and SetCommand.

The fields that vi are creating bindings to need to be declared as public in the Activity.

public EditText Text { get; private set; }
 
protected override void OnCreate(Bundle bundle)
{
     var button = FindViewById<Button>(Resource.Id.send);
     Text = FindViewById <EditText>(Resource.Id.name);
 
     this.SetBinding(() => ViewModel.Name,() => Text.Text, BindingMode.TwoWay);
     button.SetCommand("Click", ViewModel.Send);
}

The SetCommand method’s first argument will be which event that will execute the command.

I create the ViewModel in the OnCreate method using the ServiceLocator, I prefer to create it with the ServiceLocator directly instead of wrapping it in a ViewModelLocator which is a common way to do it when using MvvmLight.

The complete code for this sample is on GitHub, https://github.com/dhindrik/XamarinMvvmLightSample

How to succeed with Xamarin.Forms

Xamarin.Forms makes it possible to write UI for all the major mobile platforms, iOS, Android and Windows Phone with one shared code base. Many developers think that Xamarin.Forms isn’t is good enough to create apps that will be published and they think Xamarin.Forms is more a tool for prototyping.

If you think Xamarin.Forms is a “magic” product that will fix everything, you will properly not succeed with Xamarin.Forms. For me Xamarin.Forms is a framework that helps me build apps for multiple platforms. If you look at Xamarin.Forms in that way you will increase your chances to success with Xamarin.Forms.

Xamarin.Forms is delivered with a lot of controls that uses the Xamarin.Forms framework to render native platform specific controls. A Xamarin.Forms control is in many way just a description of what the control can do. From that description is native controls rendered.

The power of Xamarin.Forms is that you can use the framework to create you own renderers if you want to renderer a control different then the standard renderer. You can also create your own controls by using custom renderers.

I guess one of the most common issues with Xamarin.Forms i ListView performance. It’s not surprising, you maybe have 5 or 6 controls for each cell (row). If cells are reused you might have 8 cells. It means that forms need to create at least 40 renderer objects. And if any of the controls is a StackLayout or a RelativeLayout where it’s render has do to a lot of calculations where to place controls I guess you will realize that it will use a lot of memory.

So if you instead create your own custom cell that has it own renderer, there will be only one renderer for each row or if you write a renderer for the whole list you will only have one renderer. Can you realize how much memory you will save on that? If not you will see it when you are scrolling in your ListView,

The biggest problem when using Xamarin.Forms is that the developers don’t know how Xamarin.Forms works and they don’t know much about the target platforms. If you want to create a excellent app with Xamarin.Forms you still need to have knowledge about the target platforms.

Now you maybe want to ask me why you should use Xamarin.Forms? The answer is that even if you have to write platform specific code for some views there are still much you can use of the controls that is delivered with Xamarin.Forms out of the box and the powerful Xamarin.Forms framework makes it possible to write platform specific code when what you get out of the box with Xamarin.Forms not is enough.

My recommendation is to so do as much as possible with what you get out of the box with forms and don’t care about performance and if it doesn’t look perfect from the beginning. When you have created your app and built all the business logic, then you can start to look at how to make the app perfect. Than you can start write platform specific code to get better performance and a better look of the app.

TechDays 2015

Den 20 oktober börjar TechDays med förkonferens, jag och Johan Karlsson kommer att dela med oss av våra kunskapar gällande cross-platformutveckling.

Att bygga cross-platformlösningar är alltid en stor utmaning då det i grunden är olika operativsystem, programmeringsspråk och utvecklingsmiljöer.
Xamarin löser en stor del av cross platform problematiken genom att man kan utveckla appar för iOS, OSX och Android med C#. iOS och Android kan även byggas i Visual Studio. Under dagen kommer vi gå genom hur man bygger arkitektur och gränssnitt för en optimal native upplevelse på varje plattform, det vill säga iOS, OSX, Android och Windows. Vi kommer också att visa hur man kan testa mobila applikationer på ett effektivt sätt med hjälp av Xamarin TestCloud.

Läse mer här, http://tdswe.kistamassan.se/Program-2015/Sessioner/Pre-Conf-Cross-Platform-pa-ratt-satt

Xamarin.Forms Android CardView

When Google introduced Material Design for Android they introduced a new view called CardView. Xamarin.Forms doesn’t have support for CardView by default but you can easily create your own view that renderers a CardView on Android.

First step is to create a Xamarin.Forms control in your shared project.

public class CardContentView : ContentView
{
 
 
		public static readonly BindableProperty CornerRadiusProperty = 
			BindableProperty.Create<CardContentView,float> 
		( p => p.CornderRadius, 3.0F);   
 
 
 
        public new static readonly BindableProperty BackgroundColorProperty =
            BindableProperty.Create<CardContentView, Color>
        (p => p.BackgroundColor, Color.White);
 
        public float CornderRadius
        {
            get { return (float)GetValue(CornerRadiusProperty); }
            set { SetValue(CornerRadiusProperty, value); }
        }
 
        public new Color BackgroundColor
        {
            get { return (Color)GetValue(BackgroundColorProperty); }
            set { SetValue(BackgroundColorProperty, value); }
        }
 
		protected override SizeRequest OnSizeRequest (double widthConstraint, double heightConstraint)
		{
			if (Content == null)
				return new SizeRequest(new Size(100, 100));
 
			return Content.GetSizeRequest (widthConstraint, heightConstraint);
		}
	}

Next step is to create a custom renderer for Android, on iOS and Windows it will be rendered as a regular ContentView.
You need to add a NuGet package named Xamarin.Android.Support.v7.CardView to get the Android CardView. The renderer will inherit form CardView and implement the IVisaulElementRenderer interface. To get card shadow on both Android KitKat and Android Lollipop you have to set UseCompatPadding to true. You have to remove all view from the ViewGroup, if you don’t do that you will get problems when you using the control in a ListView. The Load method on the VisualElementPackager will load content in to the Card.

[assembly:ExportRendererAttribute(typeof(CardContentView), typeof(CardViewRenderer))]
namespace CardViewFormsAndroid
{
	public class CardViewRenderer : CardView, 
		IVisualElementRenderer
	{
		public CardViewRenderer () : base (Forms.Context)
		{
		}
 
		public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
 
		bool init;
		ViewGroup packed;
		public void SetElement (VisualElement element)
		{
			var oldElement = this.Element;
 
			if (oldElement != null)
				oldElement.PropertyChanged -= HandlePropertyChanged;
 
			this.Element = element;
			if (this.Element != null) {
 
				this.Element.PropertyChanged += HandlePropertyChanged;
			}
 
            ViewGroup.RemoveAllViews();
				//sizes to match the forms view
				//updates properties, handles visual element properties
				Tracker = new VisualElementTracker (this);
 
            Packager = new VisualElementPackager(this);
            Packager.Load();
 
            UseCompatPadding = true;
 
            SetContentPadding((int)TheView.Padding.Left, (int)TheView.Padding.Top,
                   (int)TheView.Padding.Right, (int)TheView.Padding.Bottom);
 
                Radius = TheView.CornderRadius;
                SetCardBackgroundColor(TheView.BackgroundColor.ToAndroid());
 
			if(ElementChanged != null)
				ElementChanged (this, new VisualElementChangedEventArgs (oldElement, this.Element));
		}
 
 
 
 
		public CardContentView TheView
		{
			get { return this.Element == null ? null : (CardContentView)Element; }
		}
 
 
		void HandlePropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
		{
			if (e.PropertyName == "Content") {
 
                //Packager.Load();
 
                Tracker.UpdateLayout();
            } else if (e.PropertyName == CardContentView.PaddingProperty.PropertyName) {
				SetContentPadding ((int)TheView.Padding.Left, (int)TheView.Padding.Top,
					(int)TheView.Padding.Right, (int)TheView.Padding.Bottom);
			} else if (e.PropertyName == CardContentView.CornerRadiusProperty.PropertyName) {
				this.Radius = TheView.CornderRadius;
			} else if (e.PropertyName == CardContentView.BackgroundColorProperty.PropertyName) {
				if(TheView.BackgroundColor != null)
				SetCardBackgroundColor (TheView.BackgroundColor.ToAndroid ());
 
			}
		}
 
		public SizeRequest GetDesiredSize (int widthConstraint, int heightConstraint)
		{
			packed.Measure (widthConstraint, heightConstraint);
 
			//Measure child here and determine size
			return new SizeRequest (new Size (packed.MeasuredWidth, packed.MeasuredHeight));
		}
 
		public void UpdateLayout ()
		{
			if (Tracker == null)
				return;
 
			Tracker.UpdateLayout ();
		}
 
		public VisualElementTracker Tracker {
			get;
			private set;
		}
 
        public VisualElementPackager Packager
        {
            get;
            private set;
        }
 
        public Android.Views.ViewGroup ViewGroup {
			get{ return this; }
		}
 
		public VisualElement Element {
			get;
			private set;
		}
 
 
    }
}

You can browse the complete code with a working example on GitHub, https://github.com/dhindrik/Xamarin.Forms-Awesome-Controls
The repository is a fork from James Montemagno’s repository for awesome Xamarin.Forms controls. What I have done is that I have changed a few things so can have layouts as content, a StackLayout for example.

Preserve data when deploying Xamarin.Android app

By default all your data from your previous runs is deleted when you’re deploying an Xamarin.Android app. In many cases you don’t want the data to be deleted.

Visual Studio
To preserve data go to Tools -> Options -> Xamarin -> Android Settings and check “Preserve application data/cache on device between deploys”.Visual Studio

Xamarin Studio
To preserve data go to Tools -> Options -> Android and check “Preserve data/cache between application deploys”.
Xamarin Studio

Building a ScreenshotManager to capture the screen with code

This blog post will show you how to build a screenshot manager to use from shared code when building apps with Xamarin for Windows Phone, Android and iOS.

First of all we need to create an interface in the shared code library. In this example there will be one method in the screenshot manager. This method will capture the screen and return a byte array that you for example can save to a server.

 public interface IScreenshotManager
 {
        Task<byte[]> CaptureAsync();
 }

All platforms that we will target capture the screen in different ways. Therefor will each platform have a own implementation of the interface. If you register the interface with a platform specific implementation for each platform you can call the ScreenshotManager from shared code.

Windows Phone
For Windows Phone you need to render the root frame into a WritableBitmap.

public class ScreenshotManager : IScreenshotManager
    {
        public async Task<byte[]> CaptureAsync()
        {
            var rootFrame = Application.Current.RootVisual as PhoneApplicationFrame;
 
            var screenImage = new WriteableBitmap((int)rootFrame.ActualWidth, (int)rootFrame.ActualHeight);
            screenImage.Render(rootFrame, new MatrixTransform());
            screenImage.Invalidate();
 
            using (var stream = new MemoryStream())
            {
                screenImage.SaveJpeg(stream, screenImage.PixelWidth, screenImage.PixelHeight, 0, 100);
                var bytes = stream.ToArray();
                return bytes;
            }
        }
    }

iOS
For iOS you need the view from the RootViewController to create a screenshot from. This code will work for iOS7 and above.

public class ScreenshotManager : IScreenshotManager
    {
        public async System.Threading.Tasks.Task<byte[]> CaptureAsync()
        {
            var view = UIApplication.SharedApplication.KeyWindow.RootViewController.View;
 
            UIGraphics.BeginImageContext(view.Frame.Size);
            view.DrawViewHierarchy(view.Frame, true);
            var image = UIGraphics.GetImageFromCurrentImageContext();
            UIGraphics.EndImageContext();
 
            using(var imageData = image.AsPNG())
            {
                var bytes = new byte[imageData.Length];
                System.Runtime.InteropServices.Marshal.Copy(imageData.Bytes, bytes, 0, Convert.ToInt32(imageData.Length));
                return bytes;
            }
 
        }
    }

Android
To create a screenshot in Android you need to have access to a activity. The easiest way to access a activity is to create a static method on the ScreenshotManager that you setting before using the ScreenshotManager.

public class ScreenshotManager : IScreenshotManager
    {
        public static Activity Activity { get; set; }
 
        public async System.Threading.Tasks.Task<byte[]> CaptureAsync()
        {
            if(Activity == null)
            {
                throw new Exception("You have to set ScreenshotManager.Activity in your Android project");
            }
 
            var view = Activity.Window.DecorView;
            view.DrawingCacheEnabled = true;
 
            Bitmap bitmap = view.GetDrawingCache(true);
 
            byte[] bitmapData;
 
            using (var stream = new MemoryStream())
            {
                bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
                bitmapData = stream.ToArray();
            }
 
            return bitmapData;
        }
    }

Using Context Actions in Xamarin.Forms ListView

One of the news in Xamarin.Forms 1.3 is what Xamarin call context actions. With context actions you can make a ListView much more richer. What you can do is to add a menu to every row in the ListView. On Windows Phone and Android is the menu showing when you’re long pressing on a item, on iOS you will swipe left on the item to show the menu. As you can see on the screenshots below the menu looks different on each platform. On Windows Phone the menu will pop up, on iOS it will be be on the row and on Android at the top of the screen.

contextactions contextactions_android contextactions_ios

To use context action add them to the ViewCell in the ItemTemplate as shown in the code below.

 <ViewCell.ContextActions>
       <MenuItem Text="Share" />
       <MenuItem Text="Buy" Command="{Binding AddToBasket}" />
</ViewCell.ContextActions>

MenuItem has four properties that is good to know:
Text: What’s shown to the user
Clicked: Adds a event listener to the menu item.
Command: Bind a command to the menu item.
IsDestructive: Will make the menu item red on iOS if it’s set to true.

 <ListView ItemsSource="{Binding Products}" VerticalOptions="Start" RowHeight="40">
 
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <ViewCell.ContextActions>
              <MenuItem Text="Share" />
              <MenuItem Text="Buy" Command="{Binding AddToBasket}" />
            </ViewCell.ContextActions>
 
            <ContentView Padding="0,10">
              <Grid>
                <Grid.ColumnDefinitions>
                  <ColumnDefinition Width="2*" />
                  <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
 
              <Label Text="{Binding Product.Name}" TextColor="Black" />
              <Label Grid.Column="1" HorizontalOptions="End" Text="{Binding Product.Price, StringFormat='{0:0.00} kr'}" TextColor="Red" />
 
              </Grid>
            </ContentView>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>

Grouping a ListView – Xamarin.Forms

In many cases when you want a list of items you want to group them in the list. To use groups in a ListView with Xamarin.Forms is very easy.

Below are screenshots from Android, iOS and Windows Phone where there is no HeaderTemplate used.
android_groups ios_groups wp_groups

First step is to create a group class that inherits from ObservableCollection and create two properties, one for title and one for short title.

public class ListViewModel
{
     ObservableCollection<MyListViewGroup> Groups {get; set;}
}
 
public class MyListViewGroup : ObservableCollection<MyListViewItem>
{
     public string Title {get; set;}
     public string ShortTitle {get; set;}
}
 
public class MyListViewItem
{
     public string Name {get; set;}
}

IsGroupingEnabled is the keyword to enable grouping for the ListView, if it’s value is true the ListView will be grouped.

GroupTitle is the group title.

GroupShortTitle is the value that will be shown when you tap a group title in Windows Phone and the value at the left side on iOS. Android will not use GroupShortTitle. It will be used to jump a specific group.

To style the header use the GroupHeaderTemplate property.

 <ListView Grid.Row="1" ItemsSource="{Binding Groups}" 
           GroupShortNameBinding="{Binding ShortTitle}" IsGroupingEnabled="true" 
           GroupDisplayBinding="{ Binding Title }">
            <ListView.GroupHeaderTemplate>
              <DataTemplate>
                <ViewCell>
                  <ViewCell.View>
                    <Label Text="{Binding Title}" />
                  </ViewCell.View>
                </ViewCell>
              </DataTemplate>
            </ListView.GroupHeaderTemplate>
            <ListView.ItemTemplate>
              <DataTemplate>
                   <TextCell Text="{Binding Name}" />
              </DataTemplate>
            </ListView.ItemTemplate>
</ListView>

Monitor an app with Xamarin Insights

I Think it’s really important to monitor apps. Of course the most important part is to log errors in the app. But I also like to track how my users uses my apps. For the lastest app I have built I have used a monitoring tool from Xamarin called Insights, http://xamarin.com/insights.

While I alwas have crossplatform and testability in mind when I buildning apps I first create a logger interface.

public interface ILogger
{
     Task InitializeAsync();
 
    //Log exceptions
     void LogException(Exception ex);
 
     //Log information about events, for example view navigation
     Task TrackAsync(string identifier, Dictionary<string, string> details = null);
 
     //Log information about a user
     Task Identify(string userId, Dictionary<string, string> details = null);
}

While Xamarin Insights is compatible with Portable Class Library I writing the implementation in a project that I can share between platforms.

public class InsightsLogger : ILogger
{
     public virtual Task InitializeAsync()
     {
     }
 
     public void LogException(Exception ex)
     {
           Insights.Report(ex, ReportSeverity.Error);
     }
 
     public Task TrackAsync(string identifier, Dictionary<string, string> details = null)
     {
           Insights.Track(identifier, details);
     }
 
     public Task Identify(string userId, Dictionary<string, string> details = null)
     {
          Insights.Identify(userId, details);
     }
}

The InitializeAsync method is virtual so it can be overridden, when using Xamarin Insights each platform has to have the Initialize code. Because of that I also need to create a logger class for each platform.

While I don’t want errors from development together with production data I use to create two apps in Insights, one for development and one for production. I using conditional compile for to initialize with the right app key.

 public class WinPhoneInsightsLogger : Logging.InsightsLogger
    {
        public override async Task Initialize()
        {
#if DEBUG
            Insights.Initialize("key for debug use");
#else
            Insights.Initialize("key for production use");
#endif
        }
    }

if you want to read more about Xamarin Insights you can do it here, http://xamarin.com/insights

Crossplatform and storage strategies

Many applications need to store data related to the application. If you’re building applications for multiple platforms the APIs for storage is different.

Following five storage types is the most common ones:

Local storage
Storage to store application data locally on the device.

Remote storage
Storage to store application data in the cloud, for example OneDrive or iCloud. Data that is saved in the cloud could be accessible from different devices.

Cache storage
Storage to use when caching data. Platforms that have a separate storage for cache data will not contain cache storage in the backup, WinRT for an example. Cached data is not necessary to have in a backup, it will be cached again after restore of the backup.

Settings storage
Storage to store application settings locally on the device.

Remote settings storage
Storage to store application settings in the cloud, for example OneDrive or iCloud. Settings will be synced for all devices you have installed the application on.

You can handle storage in different ways, one strategy is to create one interface for each of the storage types above, for example ILocalStorage and IRemoteStorage. Every interface will have an implementation for each platform. With help of an IoC-container (Inversion of Control) we can use the interface to call platform specific code from shared code.

public interface ILocalStorage
{
     Task AddAsync(string key, object value);
     Task<T> GetAsync(string key, object value);
     Task<bool> ContainsAsync(string key);
     Task RemoveAsync(string key);
}

One other strategy is to create one storage interface, IStorage and have a method with storage type as an argument. As with the first strategy each platform will have a platform specific implementation that can be used from shared code with help of IoC.

public enum StorageTypes
{
    Local,
    Remote,
    Cache,
    Settings,
    RemoteSettings
}
 
public interface IStorage
{
     Task AddAsync(string key, object value, StorageTypes storageType);
     Task<T> GetAsync(string key, object value, StorageTypes storageType);
     Task<bool> ContainsAsync(string key, StorageTypes storageType);
     Task RemoveAsync(string key, StorageTypes storageType);
}
 
public class Storage : IStorage
{
     public async Task AddAsync(string key, object value, StorageTypes storageType)
     {
          switch(storageType)
          {
                 case StorageTypes.Local:
                      //code for local storage
                      break;  
                 case StorageTypes.Remote:
                      //code for remote storage
                      break;  
                 case StorageTypes.Cache:
                      //code for cache storage
                      break;  
                 case StorageTypes.Settings:
                      //code for settings storage
                      break;  
                 case StorageTypes.RemoteSettings:
                      //code for remote settings storage
                      break;  
          }     
     }

I prefer the first strategy beacause I like small classes with one role, the maintainability will be much higher and you can make changes to one implementation without the risk of breaking other functionality than that one you want to change.

As an example, one platform maybe don’t have CacheStorage, then the LocalStorage and CacheStorage will be pretty much the same. But if that platform will get CacheStorage in the future you can change the implementation of ICacheStorage without touching the working code for LocalStorage.

Extend Label in Xamarin.Forms with a font color property

The label control in Xamarin.Forms does not have a FontColor property. But the control is easy to extend.

First create a new class that inherits from Label.
Create a FontColor property of type string. The value of the FontColor will in this example be an RGBA string.

public class CustomLabel : Label
    {
 
         public static readonly BindableProperty FontColorProperty = 
             BindableProperty.Create<CustomLabel, string>( 
                 p => p.FontColor, ""); 
 
 
         public string FontColor
         { 
             get 
             { 
                 return (string)GetValue(FontColorProperty); 
             } 
             set 
             { 
                 SetValue(FontColorProperty, value); 
             } 
         } 
 
    }

Next step is to write a custom renderer for each platform.

iOS

[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace MyApp.iOS.Renderers
{
    public class CustomLabelRenderer : LabelRenderer
    {
 
        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
 
            if(e.PropertyName == "FontColor")
            {
                var view = (CustomLabel)Element;
 
                var values = view.FontColor.Split(',');
 
                Control.TextColor = UIColor.FromRGBA(int.Parse(values[0]), int.Parse(values[1]), int.Parse(values[2]), int.Parse(values[3]));
            }
        }
    }
}

Android

[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace MyApp.Android.Renderers
{
    public class CustomLabelRenderer : LabelRenderer
    {
 
        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
 
            if(e.PropertyName == "FontColor")
            {
                var view = (CustomLabel)Element;
 
                var values = view.FontColor.Split(',');
 
                var color = Color.Argb(int.Parse(values[3]),int.Parse(values[0]), int.Parse(values[1]), int.Parse(values[2]));
 
                Control.SetTextColor(color);            
            }
        }
    }
}

Windows Phone

[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace MyApp.WinPhone.Renderers
{
    public class CustomLabelRenderer : LabelRenderer
    {
 
        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
 
            if(e.PropertyName == "FontColor")
            {
                var view = (CustomLabel)Element;
 
                var values = view.FontColor.Split(',');
                Control.Foreground = new SolidColorBrush(System.Windows.Media.Color.FromArgb(byte.Parse(values[0]), byte.Parse(values[1]), byte.Parse(values[2]), byte.Parse(values[3])));
            }
        }
    }
}

To use the custom label in XAML you need to declare the namespace.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
					   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
					   x:Class="MyApp.Views.MyView"
            xmlns:controls="clr-namespace:MyApp.CustomControls;assembly=MyApp">

Then you can use the control i XAML like this:

<controls:CustomLabel FontColor="255,255,255,255" Text="My custom label" />

Xamarin, MvvmCross and ValueConverters

This post will show you how to use ValueConverters in an Android app built with Xamarin. For an introduction to Xamarin and MvvmCross read this blog post.

If you want to convert values before you bind it to a property you can use value converters. For example if you want to view an element if a string property is not null you can use a value converter to convert it to a boolean.

First you will create a new class that inherit from MvxValueConverter and then override the Convert method and write your code there, in this case a simple null check. The class has to name end with ValueConverter.

public class IsNullValueConverter : MvxValueConverter
{
    public override object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
          return !String.IsNullOrEmpty(value as string);
    } 
}

Then name of the value converter will be the first part of the class name, so my IsNullValueConverter class will be used as IsNull in the Android Xml and the argument will be the property in your view model that you want to use.

<LinearLayout
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        local:MvxBind="Visible IsNull(Name)">

ValueConverters is a very effective and simple way to do convert values without to create a property in the ViewModel for it.

Building a tabbed app using Xamarin.Forms

Xamarin.Forms is one of the biggest news with Xamarin 3. With Xamarin.Forms you can build UI for 3 platforms (Windows Phone, iOS and Android) with one shared codebase. What is unique for Xamarin.Forms is that the UI code you are writing with Xamarin.Forms will render native UI controls. That means that the UI will look like a Windows Phone app when running the code on a Windows Phone and it will look like a iPhone app when running the code on an iPhone and the same on Android.

Create a Xamarin.Forms project in Visual Studio
This post will show you the basics when building an app with Xamarin.Forms in Visual Studio 2013. You can also build apps using Xamarin.Forms with Xamarin Studio but for the Windows Phone project you need to use Visual Studio.

To create an app with Xamarin.Forms open the new project dialog. Xamarin.Forms project templates is located under “Mobile Apps”. There are three types of project you can create, a blank app with the code in a project of type portable class library (the project will be referenced in each client project), a blank app with shared code (you have to link the each file to each client project) and a class library of type portable class library.

In this tutorial I will use the first choice because I want Visual Studio to create the client projects (projects for Windows Phone, iOS and Android) and I think it’s easier to reference an assembly than linking files.

Create dialog

Now Visual Studio has created four projects, the client projects and a project for the shared UI code.

In the shared project I add a new item based on the template called “Forms Xaml Page”. Then a XAML-file and a code behind file is created.

Many of the tutorials I have read writes the most of the code in the code behind file, but I want to use XAML as much as possible. One disadvantage to use Visual Studio is that there is not intellisense for the XAML-code. If you miss it to much you can use Xamarin Studio instead.

Create an app with tabs

The app in this tutorial will be a app with two tabs/views and for that we will use a tabbed page. This post will just use standard styles. But you can both style the app for all platforms or you can do platform specific styling.

In the view we just created ad the code below. This will be a container for the views in the app.

<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
					   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
					   x:Class="FormsDemo.FirstView"
            Title="News">
 
</TabbedPage>

You also need to go to the code behind file and make the class inherit from “TabbedPage”.

Next step is to create the content views, this app will have one for news and one for settings, so I add two new forms xaml pages to the shared project. Before I starting to create each view I will add them to the tabbed page. This is done from the code behind file of our “container”.

public partial class FirstView : TabbedPage
    {
        public FirstView()
        {
            InitializeComponent();
 
            Children.Add(new NewsView());
            Children.Add(new SettingsView());
 
        }
    }

The title for the tabs will be the title we set as Title property on ContentPage for each view.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
					   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
					   x:Class="FormsDemo.NewsView" Title="News">

Add a list to the app
My first tab will be a list with news. For that I using the ListView control that is included in Xamarin.Forms.

<ListView x:Name="News" ItemsSource="{Binding News}" RowHeight="80" BackgroundColor="Transparent">
    <ListView.ItemTemplate>
      <DataTemplate>
        <ViewCell>
          <ViewCell.View>
            <StackLayout Orientation="Vertical" Spacing="0" Padding="10">
              <Label Font="Bold,20" Text="{Binding Header}" />
              <Label Font="16" Text="{Binding Text}" />
            </StackLayout>
          </ViewCell.View>
        </ViewCell>
      </DataTemplate>
    </ListView.ItemTemplate>
  </ListView>

And the code behind will look like this:

public partial class NewsView
    {
        public NewsView()
        {
            InitializeComponent();
 
            BindingContext = new NewsViewModel();
        }
    }
 
    public class NewsViewModel
    {
        public NewsViewModel()
        {
            News = new List<NewsItem>()
            {
                new NewsItem()
                {
                    Header = "Header 1",
                    Text = "Text 1"
                },
                new NewsItem()
                {
                    Header = "Header 2",
                    Text = "Text 2"
                }
            };
        }
 
        public List<NewsItem> News { get; set; }
    }
 
    public class NewsItem
    {
        public string Header { get; set; }
        public string Text { get; set; }
    }

iPhone

Windows Phone

Android

On the settings page I using the Switch control to turn news sources on or off.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
					   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
					   x:Class="FormsDemo.SettingsView">
  <StackLayout Orientation="Vertical" Padding="10">
	  <Label Font="Bold,20" Text="News sources" />
    <StackLayout Orientation="Horizontal">
      <Label Text="Xamarin" VerticalOptions="Center" />
      <Switch VerticalOptions="Center" />
    </StackLayout>
    <StackLayout Orientation="Horizontal">
      <Label Text="Microsoft" VerticalOptions="Center" />
      <Switch VerticalOptions="Center" />
    </StackLayout>
  </StackLayout>
</ContentPage>

Windows Phone

Android

iPhone


That was the basics to build an tabbed app with Xamarin.Forms. Of course you can do much more than this with Xamarin.Forms.

Debug Android emulator remotly

When developing apps for Android I’m using Xamarin and Visual Studio. I’m running Windows under Parallels.Therefor I can’t use the x86 emulator with HAXM for hardware acceleration. But Android emulator is really slow without hardware acceleration, because of that i running the emulator on the host OS, in my case OS X.

To set up remote debugging there are a few steps to follow.

  • Enable “Remote Login” in OS X. You find it under “System Preferences” – > “Sharing”.
  • Install the Android SDK on the host OS.
  • Open SDK manager and install the Intel x86 Atom System Image for the API version you want the emulator to run on. If you have Xamarin Studio installed I think that is the easist way to start the SDK manager.

SDK Manager

 

Create emualtor dialog

  • Start your new emulator, if it start and using HAXM successfully you will se the text “HAX is working and emulator runs in fast virt mode” during the startup process.
  • Kill the adb server on the host OS using the command adb kill-server.
  • Kill the adb server on the guest OS using the command adb kill-server.
  • Install Putty on your Windows machine, that can be downloaded from here, http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
  • Open Putty and type the hostname or IP address to your host OS.
  • Under SSH -> Tunnel, configure port forwarding on port 5554 and port 5555.

Putty

 

  • Open a new session and type your login credentials when Putty asks for them.
  • Start the adb server on the host OS using the command adb start-server. To verify that the emulator is connected use the command adb devices. 
  • You will now be ready to start debug your app in the emulator remotely.

TechDays 2014

Den 19-20 november (17-20 november med pre-conf inkluderat) anordnas utvecklarkonferensen TechDays av Microsoft. Jag och min Sogeti- och IO2GameLabs kollega Johan Karlsson har fått äran att vara med på den. Vi kommer att prata om det vi brinner mest för nämligen cross platform utveckling för mobila enheter.

På pre-conf (den 17 november) kommer vi tillsammans med Peter Bryntesson (Microsoft), Johan Lindfors (Coderox) och Anderas Hammar (Jayway) att hålla en heldag om hur man bygger appar för Windows (Windows Store och Windows Phone) och för iOS och Android med Xamarin. Läs mer här.

Under själva huvudkonferensen kommer jag och Johan att ägna ca en timme till att berätta hur vi har arbetat med vårt spel WordRoom för att göra det cross platform med Xamarin och Microsoft Azure. Läs mer här.

Tycker ni att detta låter intressant tycker jag ni ska komma till TechDays på Kistamässan, självklart kommer det bjudas på massa andra intressanta föreläsningar också. Se hela programmet här.

Xamarin and MvvmCross

A way to reuse so much code as possible when working with Xamarin is to use the MVVM-pattern. A framework for MVVM that works great with Xamarin is MvvmCross (http://www.nuget.org/packages/MvvmCross/3.1.1). This blog post shows the basics about to use MvvmCross with Xamarin for an Android app. More posts about Xamarin and MvvmCross will come later.

Installation
The easiest way to install MvvmCross is to installed above mention NuGet package. In order to share as much code as possible I have the code for ViewModels in a core project (a Portable Class Library) that I can share with apps for iOS and Windows. I have to install the NuGet package on both the client project and the core project.

ViewModels
Viewmodels will be shared over all platforms. The ViewModel has to inherit MvxViewModel and override the start method. In the start method, put the code that will run when the viewmodel is initialized. In my example I get the data there.

Each property needs to have a private variable that contains the data. But when you are setting the data you need to set the property, not the variable. The get method of the propery will just return the value of the variable. The set method also needs to call RaisePropertyChanged to notify the UI that the value of the property has changed.

private ISettings _settings;
 
public SettingsViewModel (ISettings settings)
{
            _settings = settings;
}
 
public async override void Start()
{
	base.Start ();
        Settings = _settings.GetSettings(); 
}
 
private List<Setting> _settingsList
public List<Setting> Settings
{
        get
        {
             return _settingsList;   
        }
        set 
        {
              _settingsList = value;
               RaisePropertyChanged(() => Settings);
        }
}

Databinding and views
Code to databind will be platform specific. For Android the binding code will be placed in the layout files.

To use bindings in your layout files you need to add a namespace to your root element.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto">

The easiest way to create a list of bound items is to use MvxListItem. Use the MvxBind property to set the item source for the list and MvxItemTemplate to set which template that will be used for each item.

<Mvx.MvxListView
        local:MvxBind="ItemsSource Settings"
        local:MvxItemTemplate="@layout/settings_item" />

In the layout file for the list item use MvxBind to bind text to the elements.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto">
        <TextView
            local:MvxBind="Text Key" />
        <TextView
            local:MvxBind="Text Value" />
</LinearLayout>

The Activity
Your activity need to inherit MvxActivity and override the ViewModel property. Notice the new keyword in the property head.

public new SettingsViewModel ViewModel
{
       get { return base.ViewModel as SettingsViewModel; }
       set { base.ViewModel = value; }
}

That is the only thing you need to do in your activity to start using MvvmCross.

Splash screen
When your app is starting it could be nice to show a splash screen to your users. MvvmCross makes it easier for you to do that. When you install MvvmCross you will get files in your project for a splash screen. Just edit it so it looks the way you want.

The splash screen will not be the main launcher, set the first activity to be the main launcher. If you have two main launchers the app will be in the app list twice.

That was the basics about MvvmCross, more to come in future posts.

Xamarin, Invalid or Corrupt License

If you get this message when developing Android apps with Xamarin, “Invalid or Corrupt License” it does not necessary means that it is something wrong with the licens. In my case it was API level 19 that caused the problems. After I unistalled it from SDK Manager I have not seen the message.  This seems to be a common problem, I have read about other developers having the same problem with API level 19.

Windows Azure Mobile Services in Portable Class Library

In my current project, a multiplayer game for mobile devices I only using Windows Azure Mobile Services as backend. The game will be available for multiple platforms and I will use Xamarin for iOS and android.

When using Xamarin I can reuse a lot of code if I using PCL (Portal Class Library) that i shipped with Visual Studio. When creating a new PCL-project you can choose which taget platforms the project will build for, in my case Windows Phone, Windows Store, Xamarin iOS and Xamarin Android.

In order to reuse so much code as possible I want to have the communication with my backend in PCL. When using Windows Azure Mobile Services I can have all communication there except for the code for authentication. But then I put an interface i PCL and each platform will have a specific implementation of the interface.

But where to find the Mobile Services assemblies for PCL? I installed Mobile Services via NUGET to my Windows Phone project (Windows Phone is my first platform). But Mobile Services was not just installed to my Windows Phone project, I also got the assemblies for PCL (and other platforms) i my packages folder. It enabled me to add the assemblies manually to the PCL-project.

Size limit on app download when using 3G

iOS and Windows Phone has size limit on how big apps you can downloaded when you’re not connected to a Wi-Fi-network. Windows Phone has a limit on 20 Mb and iOS has 50 Mb.  Android has not that type of limit, but an APK on Google Play is limited to 50 Mb, but you can add extensions that are much bigger than so.

When are you downloading apps to your phone? It’s often when you sitting on the bus or waiting for something. Do you have a Wi-Fi-connection then? Often not.

I think it could be a good thing to think about when developing apps. If a user found your app and cannot download it, the chance that they choose to download another app instead is big. If you have big content in you app, you maybe can have it on a server and download it when the user starting the app.

Probably the user don’t need that content from start and you have some time to download it, if they navigate to a part that need the content, show a loading dialog that tells the user that content is under download.

Authentication with Azure Mobile Services

When developed the multiplayer part of WordRoom we discussed to use different authentication providers. But it was a lot of code to integrate each provider. And we wanted more than one. Instead we developed our own solution.

But just ask yourself, do you want to create an account everywhere with different username and passwords. I don’t. When we discovered Azure Mobile Services it was an obvious choice. Mobile Service gives you authentication with Microsoft-, Google-, Facebook and Twitter account and it’s for free. You only need to connect it to a database server. But we already had a database server in Azure. So i next version of WordRoom, you can authenticate with your Microsoft-, Google-, Facebook- or Twitter account.

With just a few rows of code you can authenticate the user with one of the authentication providers.
That Mobile Service is for five different platforms is a huge strength. You can use it for Windows Store applications, Windows Phone, Android, iOS and HTML5/JavaScript. If you use Xamarin Studio for developing your Android and iOS apps, there is a third part library.

In a Windows Store application you just add the SDK, some rows in App.xaml.cs and one row where you want to authenticate the user.

user = await App.MobileService
                .LoginAsync(MobileServiceAuthenticationProvider.Facebook);

Read more about Mobile Services