Real-time Mobile Apps with AppBuilder, Xamarin and SignalR

It’s 2014 and we’re living a constantly connected mobile lifestyle, where we have come to expect near real-time digital communication between the Internet & our devices. The needs for real-time communication are endless – stock tickers, chat, document collaboration, multiplayer games – just to name a few. Yet for developers coding real-time communication between applications/devices meant that we had to navigate the rough waters of deciding our network transport layer (periodic polling, long polling, web sockets, server sent events etc.) and also figuring out cross-platform compatibility between server/various clients. That’s no fun.

Enter SignalR. Part of the Microsoft ASP.NET stack but open sourced, SignalR allows developers to easily add real-time communication to our web applications. Drop the SignalR library into your ASP.NET application (web forms or MVC), and it abstracts away the network transport layer between server & client, thus allowing the desired bidirectional communications (functions invoked over RPC & easy APIs).  And SignalR powered backend applications can empower real-time communication on a variety of client platforms – web, desktop or mobile.

SignalR is just like any other ASP.NET component out of the box – so let’s not write any more fake progress bars, agreed? In this article, we’ll walk through building a cross-platform mobile chat application with real-time communication enabled through SignalR.

Real-time for the Web

The best place to get started incorporating real-time in your apps is the SignalR home page that has detailed documentation and examples. The quintessential first real-time web app is invariably a chat application – it’s simple and proves the point. A detailed run-down of how to use SignalR to build a simple chat application can be found here or my colleague, Ignacio Fuentes, also wrote one on this site here.

For this article, I have created a simple demo MVC web application that provides SignalR powered chat functionality, both as a web app and also serving as backend service. The basic steps to do this are:

  1. Create an empty ASP.NET web application.
  2. Add a SignalR Hub class to the project or bring in the SignalR pieces via NuGet.
  3. In either case, the required DLLs on the server side and the SignalR JavaScript bits on the client side get added automatically.
  4. Code a SignalR Hub with desired functionality and hook it up from a client view using JavaScript.

The Server Side

The one line of code necessary in my ChatHub class on the server is the following:

public class ChatHub : Hub
{
   public void PushChatMessageToClients(string message)
   {
       Clients.All.addChatMessage(message);
   }
}

That’s it on the server! We’ll look at some of the client side code in just a bit.

If we were to fire up the web app running on LocalHost in two different browser windows, the real-time chat communication is exactly as we had hoped.

WebChat

Real-time for Mobile

There is nothing stopping you from making this web version of the app mobile friendly. You could easily use responsive design in the client views, for example by incorporating a framework like Twitter Bootstrap, Zurb Foundation or even the MVC mobile friendly views.  But, you still wouldn’t get the native app experience or the Store monetization/publicity. So, let’s build some native mobile apps that exude in SignalR powered real-time communication.

When building anything on the .NET stack, like for Windows Phone or Windows 8/8.1 apps, the choice is obvious – grab the SignalR .NET Client NuGet and communicate easily with the same web app backend we just built. However, we don’t live in a silo, so you’ll want to go cross-platform to support iOS and Android.

The good news is – whether you love your HTML5/JS or C# everywhere, you have options. Let’s dig in!

Telerik AppBuilder

Using AppBuilder, you can use one code base, with HTML/CSS/JavaScript code, for cross-platform mobile apps that are compiled as native app package. AppBuilder let’s you edit and debug your app in real-time, gain access to native device APIs (via Apache Cordova), and publish to directly to app marketplaces. Better yet, you get to use your choice of IDE – Windows client, Visual Studio extension, CLI, Sublime Text or plain old browser for a web client. You can read more more about it on the AppBuilder home page.

Since our ASP.NET web application backend is already set and the client views were written in simple HTML/JavaScript, we can port over the code as is to create an app! Sign up for Telerik AppBuilder free trial, if you haven’t already, and grab your favorite IDE. You get the same starter project templates everywhere (the Visual Studio extension is shown below) that offer a boilerplate project, including the required Cordova JavaScript (shown below in my web client view). If you choose Kendo UI Mobile as the UI layer, it will include a lot of widgets that can render adaptively based on the type of device that is running the app, which can lead to a much smoother user experience (UX).

AppBuilderVSExtension

AppBuilderStarter

Now, for our AppBuilder cross-platform mobile app to communicate in real-time to the ChatHub we had created before in the backend, we need the client-side SignalR JavaScript support. The first step would be to copy over the jQuery script and the SignalR/jQuery script files over into our scripts directory.  Next, we write the following HTML markup and a little JavaScript code in the index.html file:


<script src="scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="scripts/jquery.signalR-2.0.3.min.js" type="text/javascript"></script>
<script type="text/javascript" src="http://localhost:53478/signalr/hubs"></script>

<div id='container'>
<br /><br />
<div id='chat' style="margin-left: 30px;">
<b>Chatroom:</b>
<br /><br />
<input type="text" id="message" maxlength="100" style="width: 200px;" />
<br /><br />
<input type="button" id="broadcast" value="Broadcast" />
<input type="button" id="clear" value="Clear" />
<br /><br />
<ul id="chatdialog"></ul>
</div>
</div>

<script type="text/javascript">

$(function () {
// Create the connection to our SignalR-powered Chat Hub on the server.
$.connection.hub.url = "http://localhost:53478/signalr";
var signalRChatHub = $.connection.chatHub;

// Add chat messages from server to dialog.
// Method invoked from server.
signalRChatHub.client.addChatMessage = function (message){
$('#chatdialog').append('<li>' + message + '</li>');
};

// Click event-handler for broadcasting chat messages.
$('#broadcast').click(function (){
// Call Server method.
signalRChatHub.server.pushChatMessageToClients($('#message').val());
$('#message').val("");
});

// Start the SignalR Hub.
$.connection.hub.start(function (){
// Do stuff here, if needed.
});

// Click event-handler for clearing chat messages.
$('#clear').click(function (){
$('ul li').remove();
});
});

</script>

This code is actually no different from what we would have had to write on the client-side for the web app. The markup builds a simple chat UI. The JavaScript code points to the SignalR Hub’s URL (in my case, this is http://localhost:53478/signalr), establishes a continuous connection (without you having to worry about the transport layer) and wires up the UI event handlers.

You’ll notice that from within our JavaScript code, we invoke a server side ChatHub method, which, in turn, calls a JavaScript function on every connected client, including our mobile app – kinda magical. So, let’s fire up the build/deploy to see if our code works. Voila – we have our simple chat UI showing as an iPhone app!

AppBuilderSimulator1

The AppBuilder simulator works the same way from windows/web clients and can be a mobile developer’s best friend. You can easily switch the deployment of your app package to an iOS, Android or Windows Phone devices as well as being able to target specific OS versions once a device is picked. You also get to simulate between smartphone/tablet form factors, mimic geolocation, network connectivity and users, as demonstrated in the few screenshots below.

AppBuilderSimulator2

AppBuilderSimulator3

AppBuilderSimulator4

To test the real-time nature of our app, let’s keep our backend web application open and fire up the AppBuilder simulator simultaneously. Sure enough – we have true real-time chat working between the web and our mobile app on any device. How cool is that?

HybridWebChat

Xamarin

Now, if writing cross-platform hybrid mobile apps in HTML/JavaScript isn’t your cup of tea, another option you might consider is the C# everywhere route that Xamarin offers. You can learn more about Xamarin on their home page.

Using this option, you get to consume platform specific APIs in C# and all your C# code will get cross-compiled down to native app packages in their respective mobile platforms. Interestingly, building a SignalR powered real-time app in Xamarin mirrors the technique you would use to build a pure .NET app, as you might expect.

Xamarin also offers you a choice of IDE – Visual Studio integration or the Xamarin Studio, which is available both on Windows and Mac. One caveat to keep in mind, however, is that building/deploying iOS apps in Xamarin does require a Mac, though you can still develop Android apps on Windows.

With Xamarin, your goal would be to maximize code abstraction through Portable Class Libraries for sharing, and then building the unique UIs for each platform. Let’s build a simple Android app in Xamarin Studio that talks real-time to our SignalR ChatHub backend. We’ll start with a default Android project template and need to bring in the SignalR .NET client NuGet for real-time communication. Unlike the Visual Studio Extension, Xamarin Studio does not have a package manager built in, but it offers plug and play. This post offers the step-by-step on getting this set up and, once done, all packages in the NuGet gallery become available.

Of course, we’ll need grab the SignalR .NET client. You can see a screenshot of the project references below – notice the SignalR DLL and the Newtonsoft DLL. The latter DLL deals with automatic JSon serialization/deserialization when SignalR needs to deal with custom objects.

XamarinProjectStructure

Now, the Main.xaml under Resources/layout in the project structure is the default UI for the first Android app view. Let’s tweak it to have our simple chat UI, by adding the code below:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/ChatInput" />
<Button
android:id="@+id/ChatButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Send Chat!" />
<ListView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/ChatMessages" />

</LinearLayout>

MainActivity.cs is where the program execution begins once the Android app launches. Let’s write some custom code in there as well, which is shown below:

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

using Microsoft.AspNet.SignalR.Client;
using System.Collections.Generic;

namespace SignalRWithXamarin
{
[Activity (Label = "SignalRWithXamarin", MainLauncher = true)]
public class MainActivity : Activity
{
   HubConnection chatConnection;
   IHubProxy SignalRChatHub;
   public event EventHandler<string> OnMessageReceived;

protected override void OnCreate (Bundle bundle)
{
  base.OnCreate (bundle);
  SetContentView (Resource.Layout.Main);

  chatConnection = new HubConnection("http://169.254.80.80:54810/");
  SignalRChatHub = chatConnection.CreateHubProxy("ChatHub");

  SignalRChatHub.On<string>("addChatMessage", message =>
  {
    if (OnMessageReceived != null)
      OnMessageReceived(this, string.Format("{0}", message));
  });

  JoinChat ();

  var input = FindViewById<EditText>(Resource.Id.ChatInput);
  var messages = FindViewById<ListView>(Resource.Id.ChatMessages);

  var adapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, new List<string>());
  messages.Adapter = adapter;
  OnMessageReceived += (sender, message) => RunOnUiThread(() =>
  adapter.Add(message));

  Button button = FindViewById<Button> (Resource.Id.ChatButton);
  button.Click += delegate {
  if (string.IsNullOrEmpty(input.Text))
      return;

  Chat(input.Text);
  input.Text = "";
  };
}

public async virtual void JoinChat()
{
  try
  {
     await chatConnection.Start();
  }
 catch (Exception)
  {
    // Do some error handling.
  }
}

public async virtual void Chat(string phoneChatMessage)
{
  if (chatConnection.State == ConnectionState.Connected)
     await SignalRChatHub.Invoke("PushChatMessageToClients", phoneChatMessage);
}
}
}

You’ll notice that we refer back to the SignalR ChatHub URL, but this time, it’s not LocalHost. Instead it uses a fully qualified with IP address/port number so that we can reach the backend service. We create a proxy to the named Hub on the backend server and invoke methods through it when the Android user needs to post a chat message.  Also, we wire up an event handler to listen to chat messages coming in from the SignalR hub.

The result is SignalR powered real-time communication in a native Android app, as shown below.

AndroidWebChat

Conclusion

It’s 2014, and users have justifiably high expectations from their mobile apps. They expect to be able to send/receive the data they need, in real-time – and SignalR not only provides this capability, but makes it trivial to implement. Users also expect that they can get the apps they depend on across whatever mobile platforms they use, and both Telerik AppBuilder – using HTML and JavaScript, and Xamarin – using C# – lets you meet that cross-platform expectation.

Comments

  • i tried integrating signalr did same as you mentioned in appbuilder but i get error saying cannot read property of client