Realtime Databases with the Realm Mobile Platform



This is a special guest post from the Realm team, written by Andy Dent.

Andy Dent is a C# developer at Realm, working virtually in Copenhagen from the sunny state of Western Australia. When not sweating over code he can be found sweating at kung fu and online at

Today, Realm is announcing a couple of really neat things for Xamarin users, including the 1.0 release of the Realm Mobile Database, and support for Xamarin on the Realm Mobile Platform. With these tools, we wanted to show you how quickly you could make a collaborative app that syncs in realtime, while maybe having a little fun along the way, so we’ll be rewriting the RealmDraw app in Xamarin.

Xamarin introduced Skia Sharp in February 2016 so it was a natural choice when we needed a vector drawing library for our RealmDraw sample. The challenge had already been laid down by the Realm Cocoa Team showing how cool a shared drawing app can be with Realm. We wanted a Xamarin app to match that would also show how easily code can be shared across Android and iOS.

This tutorial shows how to build a simple freehand drawing app using SkiaSharp and then, with the aid of the Realm Mobile Platform (RMP), make it a shared drawing app. It assumes a reasonable familiarity with Xamarin Studio to build a Xamarin app.

Setting Up a Realm Object Server on Azure

Before we get into the app development, here’s a quick guide to setting up a Development server on Azure, mostly following the standard Microsoft guides. We will use the Ubuntu version of the server.

  • Follow the “Create a Linux VM on Azure using the Portal” documentation to create an instance of Ubuntu Server 16.04 LTS.
  • Follow the “Opening ports to a VM in Azure using the Azure portal” guide and allow through port 9080. Note that you do not need to create a new Network Security Group as one has already been created with your server – you will see it contains a definition for port 22 which is why you can use SSH to connect.
  • Use SSH to connect to your server so you have a terminal session.
  • Now we use the steps from Install the Realm Object Server below to install and start the Realm Object Server.

Setup with SkiaSharp

Our tutorial starts with some hardcoded drawing to prove your SkiaSharp installation works, then moves on to how to draw in response to touches, and concludes by integrating Realm. For more background on SkiaSharp, see the Xamarin blog post on SkiaSharp.

There is not yet a simple way to capture complex touch events, within Xamarin Forms, so this tutorial code uses native UI projects. That keeps things a little simpler so you can focus on the drawing code and particularly sharing drawing with RMP.

  • Start with a new Single View project for iOS and Android. We will use a Shared project for the common code.
  • Add the NuGet SkiaSharp.Views. That will also add SkiaSharp.
  • Now clean up each project to remove the template UI and add a SkiaCanvas
  • .

iOS Configuration

  • Open the Main.Storyboard with the visual editor.
  • Remove the <emHello World UIButton.
  • Select the main view. In the Properties Widget panel change the Name to Canvas and the Class to SKCanvasView.
  • How to Add SkiaSharp to the Storyboard

  • Open ViewController.cs, and remove the Button logic in ViewDidLoad.
  • Add using statements for SkiaSharp and SkiaSharp.Views.iOS.
  • Add an OnPainting method and set it up in ViewDidLoad so your entire file looks like this:

You can now build and run the iOS program and you should see a blue circle drawn on an otherwise white screen.

Android Configuration

To edit the AXML file in Android, for these simple changes, editing the layout files in text format will be easier – you can right-click on them in Xamarin Studio and choose Open With – Source Code Editor.

  • Open the Main.axml file under the Resource/layout directory.
  • Replace the line Button android:id="@+id/myButton” … with
  • In MainActivity.cs, add using SkiaSharp; and using SkiaSharp.Views.Android;.
  • Remove the standard Button setup in OnCreate.
  • Add an OnStart method to create the SKCanvasView so your MainActivity.cs looks like:

You can now build and run that and similarly see SkiaSharp working to draw a blue circle on white background.

Adding Touches to Draw

The app we’re building isn’t a shape vector drawing app but is more like a whiteboard – it tracks your touches and draws straight lines between them. The faster you draw, the more jagged your drawing will become. An Apple Pencil on an iPad Pro makes a fine test environment.

iOS Draw with Touches

All the changes are in ViewController.cs, adding fields to track the path we are building and compensate for device scaling:

The painting method now draws a path we have built:

To build the path, we need to respond to touch events by scaling points and adding lines:

Android Draw with Touches

All the changes are in MainActivity.cs, adding fields to remember the main view and track the path we are building:

The Painting method now only clears at the start, and otherwise draws the path we have built:

To build the path up, we track Touch events:

Remembering Points With Realm

Instead of drawing lines immediately as you touch the screen, we are now going to save them in a local Realm. This means you can quit the application and come back to it later with your drawing being loaded from disk.

Rather than just recording the points in order, we will group them into _Paths_ which are a continuous stroke. This is useful for changing colors and will be essential when we start sharing drawings.

Adding Realm

To begin, you need to add the Realm NuGet package to your iOS and Android projects. This will also add Realm.Database, Fody and a number of support System packages. It looks like a lot but many of them are only used at build time and don’t bulk out your app.

We will use two simple classes to track the drawing.

More of the logic now becomes shared – we’re getting more code sharing by stripping logic from the individual UI projects.

Here’s the LiteDrawer.cs entire file. You can see how drawing logic from the touch methods above has now been moved into DrawPaths and DrawAPath which work solely from the saved data in the Realm. These methods cleanly separate the Drawing action from the Input methods that record points.

We do still have a current _drawPath field which is used to remember the path to which points are being added. This could be retrieved from the Realm every time but keeping track of it in memory helps provide responsive drawing.

Did you notice a couple of little Realm idioms in there? You can read more about them in the main Realm docs. Most of the Realm SDK uses standard C# collection interfaces and LINQ so you don’t notice when you are using it. The main things to remember are:

  • All updates, adding or modifying data are wrapped in a _realm.Write().
  • Use All to iterate through all objects of a given class, eg: foreach (var drawPath in _realm.All()).
  • Iterating through the path’s related points is normal C# foreach (var point in drawPath.Points).

When you build and run this stage of the sample, you will see your drawings continuously accumulate. Quit the app and next time you launch, all your saved scribbles from before immediately draw. Realm is so fast we’re also cheating a bit and just doing these database operations on the UI thread.

iOS Draw With Realm

The ViewController.cs now becomes much more of a Controller just forwarding events to our LiteDrawer.

Start by replacing the local _path field with a LiteDrawer instead.

The OnPainting method is just a forwarder:

The Touches methods now call the Drawer to add data:

Android Draw With Realm

Similar trimming of the Android MainActivity.cs has it forwarding events to the Drawer:

Sharing Your Drawings With Realm Mobile Platform

The steps from using a local Realm to synchronised are very small.

  • You need to know where the server is – for now we use a fixed address.
  • Your client app needs to be authenticated to the server, we will cheat and specify a hardcoded address with username/password.
  • Drawing must be triggered by the Realm being updated, not by local touches.
  • Connecting to the Server

    The field _realm is no longer set in the LiteDrawer constructor but has to be created after a series of authentication steps. You can see below the use of Credentials.UsernamePassword – see our Authentication Documents for other methods.

    Instead of a local Realm named _SharedScribbles_ we refer to it on the server as an address passed into new SyncConfiguration(user, new Uri($"realm://{serverIP}/~/SharedScribbles"));.

    Reacting to Changes

    Just at the end of LoginToServerAsync above, you can see how we save a live query result _allPaths and subscribe to be notified when it is changed. We retain the _notificationToken as a field of LiteDrawer because otherwise, garbage collection would cause notifications to cease.

    We are only subscribing to the DrawPath objects. Both this app and others sharing the same server will be adding or updating paths, as they draw. In this unsophisticated version, we just redraw everything each time someone adds a single point, somewhere. That means our refresh method doesn’t need to care about the details of what has been changed.

    Remember in the purely local version, refreshing the screen was driven from the _outside inwards_ – a touch event in the GUI code caused a refresh. To trigger those refreshes from the shared code in LiteDrawer, it has a property set by the calling app:

    As a fun experiment, you can directly open the SharedScribbles Realm on the server with the Realm Browser (running on MacOS). If you delete a DrawPath, it will vanish from all the devices. If you edit its color, they all redraw with that path in a different color.

    Same Code for Local as Shared Realms

    The important thing about the changes to LiteDrawer above are what we didn’t change. There was no need to change any of the code writing paths and points into the Realm because they just work the same way. Once a synchronized Realm is opened, it acts like just another Realm. From the point of view of your application code, there’s no difference between a background thread doing some updates and shared data arriving from the Realm Object Server.

    iOS Draw With RMP

    As you probably expect, the ViewController.cs changes very little. Most importantly, we set the _drawer.RefreshOnRealmUpdate and then pass in credentials to login.

    The only other changes are removing the two View?.SetNeedsDisplay(); from TouchesMoved and TouchesEnded. Those two calls effectively moved into the _drawer.RefreshOnRealmUpdate.

    Android Draw With RMP

    Exactly the same changes occur in Android’s MainActivity.cs – move the refresh calls from OnTouch and login.

    The Final Point

    This article, and the sample code, is like an inverted triangle. Most of the work initially went into the GUI, being able to track touches and draw in response. Adding Realm to manage the data was little more work than adding a couple of classes to manage those data structure, and shifting from immediate drawing to using saved data to draw.

    The final, big step of making your drawings shared live was just a case of connecting to a server and changing how you trigger a screen refresh. Go create — we can’t wait to see what you’ll make with Realm and Xamarin.

    Source Code

    To help you get started and to check progress along the way, the source for this tutorial has been saved in a series of archives:

    1. Empty app with just SkiaSharp added to draw a basic blue circle. Archive
    2. Touches added to immediately scribble. Archive
    3. Your drawing stored in Realm so it’s now persistent. Archive
    4. Full shared drawing with Realm Mobile Platform. Archive

    Full Version Source

    The main RealmDraw sample is also available for Xamarin, along with other frameworks and includes a number of additional features:

    • Shake the device to clear
    • Enter login credentials, with error-handling
    • Optional Active Directory authentication
    • Change colors by tapping different pencils
    • Smooth drawing with various drawing optimizations, treating the immediate drawing separately from server updates
    • Normalise drawings to device scale so they draw fully on all tablets and phones
    • Properly cleanup notification tokens and other event handlers
    • Local persist settings including the last color used.
    Guest Blogger

    Follow Guest   

No Comments.