Using SignalR in native Android and iOS apps

Andrew Wroe

As part of this year’s Dev Camp we’ll be using the ASP.NET SignalR real-time communication library to synchronise between multiple views/clients of an HTML-based presentation.

Some of those clients will be Android and iOS apps and so really we want to be able to use the SignalR library within those apps, and whilst we’re thinking about it, it’d be nice to be able to write the bulk of the code for those apps using C#. Not that long ago this would not have been possible as Android apps are written in Java and iOS apps in Objective-C, but a toolkit called Xamarin has been gaining traction to allow developers to do just that.

Xamarin allows you to create native iOS, Android and (less surprisingly) Windows apps from a common C# codebase, which can include third party and Microsoft libraries like the .Net Framework and SignalR. You can find out how it does this on the Xamarin site.

We tested it out by building a basic Android chat app.

Showing the web app (left) talking to the Android app (right)
Showing the web app (left) talking to the Android app (right)

Getting Started

You’ll need to set up the following things:

Creating the Android Chat Client

Create a new Xamarin Android Application. I used Visual Studio, but Xamarin Studio would likely work just as well.

Add a reference to the Microsoft.AspNet.SignalR.Client.Portable libraries you built earlier.

Add in a new layout and some basic UI controls. There is a text input for typing in new messages, a text output for displaying received messages, and a button for sending messages.

var layout = new LinearLayout(this);
layout.Orientation = Orientation.Vertical;

var chatMessagesLabel = new TextView(this);
chatMessagesLabel.Text = "Chat Messages";

/// <summary>
/// The text view in which the chat messages are displayed
/// </summary>
var chatTextView = new TextView(this);

var chatInputLabel = new TextView(this);
chatInputLabel.Text = "Enter the text to chat here";

/// <summary>
/// The text view which is the chat message to be broadcast
/// </summary>
var chatInput = new EditText(this);

/// <summary>
/// The button that sends the chat message
/// </summary>
var chatButton = new Button(this);
chatButton.Text = "Chat";

layout.AddView(chatMessagesLabel);
layout.AddView(chatTextView);
layout.AddView(chatInputLabel);
layout.AddView(chatInput);
layout.AddView(chatButton);
SetContentView(layout);

To call a SignalR hub from within C#, you need to know the address of the hub and the name of the hub and hub methods.

/// <summary>
/// URL of the Hub server.
/// </summary>
private const string HUB_URL = "http://<your hub IP>/ChatServer/signalr";

/// <summary>
/// The name of the Chat Hub
/// </summary>
/// <remarks>
/// This is the name specified by the HubName attribute,
/// defaulting to the camelCase version of the hub class name
/// </remarks>
private const string HUB_NAME = "chatHub";

/// <summary>
/// The name of the method the hub uses to broadcast chat messages
/// </summary>
/// <remarks>
/// This is the name of the method called on the Clients object
/// </remarks>
private const string SOMEONE_ELSE_IS_CHATTING_METHOD = "addNewMessageToPage";

/// <summary>
/// The name of the method the hub listens for to receive new chat messages
/// </summary>
/// <remarks>
/// This is the name specified by the HubMethodName attribute,
/// defaulting to the name of the C# method
/// </remarks>
private const string I_AM_CHATTING_METHOD = "Send";

Now we need code to connect to the SignalR chat hub and to send and receive chat messages. This is the same code you would use in any C# SignalR client (see the Microsoft Hubs API Guide).

//Create the Hub Proxy connection
HubConnection connection = new HubConnection(HUB_URL);
IHubProxy hubProxy = connection.CreateHubProxy(HUB_NAME);

//Receive chat messages
hubProxy.On<string, string>(
   SOMEONE_ELSE_IS_CHATTING_METHOD,
   (p1, p2) =>
   {
      //Need to ensure the changes are in the UI thread,
      //since SignalR can fire the events from a different thread
      RunOnUiThread(() =>
         chatTextView.Append(String.Format("{0}: {1}n", p1, p2))
      );
   });

//Send out chat messages
chatButton.Click += (sender, e) =>
{
   hubProxy.Invoke<String[]>(
      I_AM_CHATTING_METHOD,
      new String[] { "Android", chatInput.Text });
   chatInput.Text = "";
};

//Start the link with the hub
connection.Start().Wait();

And that’s it!

The trickiest bit was in making the UI update – you have to make sure any UI changes are done in the UI thread, and that isn’t necessarily the one that SignalR fires the event in. Fortunately, this is as simple as wrapping the relevant changes with RunOnUiThread().

Next step for us is to refactor the code so that all the SignalR accesses are in a Portable Class Library, and add in UIs for other devices.