Wednesday 19 September 2012

The simplest chat ever... just got simpler

In my last post I described a simple chat implementation using the SignalR framework. At the time of writing it I thought it’s really as simple and clean as it can get. However, my work colleague Lukasz Budnik proved me wrong by suggesting a simpler solution that they used while creating hackathon.pl portal. He suggested replacing my server side components with a cloud hosted push notifications provider.

I admit I was thinking in a more traditional way, where all application components are hosted in-house, on servers owned by our company or our clients. Nowadays, it’s often a better idea to use exiting cloud hosted solutions than implementing some system components by ourselves. I definitely recommend considering this option if you have no important blockers preventing you from using SaaS solutions (e.g. like legal issues related to sending some data to third parties). Advantages that come with cloud are topic for another discussion though.

Let’s have a look how our chat application changes with this new approach. First of all, we need to choose a push provider. And yet again - Lukasz to the rescue with his latest post, describing various SaaS solutions. I decided to go with the PubNub, as its documentation already contains a chat example. So it’s a no-brainer, really.

The entire solution is now enclosed within a single html file. As mentioned at the beginning you don’t need to write any server code. The additional benefit is easier development and testing, as you don’t even need a web server, just your regular web browser.

The html file looks as follows. Please note that the html components are exactly the same as in my previous solution. In addition, PubNub allows you to bind events to DOM elements, so we don’t need jQuery in this example.

<label for="nick">Your chat nickname:</label>
<input id="nick" name="nick" type="text" />
<label for="message">Message:</label>
<input id="message" maxlength="100" name="message" type="text" />
<div id="chatWindow"></div>

<div pub-key="MY_PUBLISHER_KEY" sub-key="MY_SUBSCRIBER_KEY" ssl="off" origin="pubsub.pubnub.com" id="pubnub"></div>    
<script src="http://cdn.pubnub.com/pubnub-3.1.min.js"></script>
<script type="text/javascript"></script>

<script type="text/javascript">
(function () {
    // declare some vars first
    var chatWin = PUBNUB.$('chatWindow'),
        nick = PUBNUB.$('nick'),
        input = PUBNUB.$('message'),
        channel = 'chat';

    // subscribe to chat channel and define a method for handling incoming messages
     PUBNUB.subscribe({
          channel: channel,
          callback: function (message) {
              chatWin.innerHTML = chatWin.innerHTML + message;
          }
     });

     // submit message to channel when Enter key is pressed
     PUBNUB.bind('keyup', input, function (e) {
         if ((e.keyCode || e.charCode) === 13) {
             PUBNUB.publish({
                 channel: channel,
                 message: nick.value + ': ' + input.value
             });
         }
     });
})();
</script>

Thursday 13 September 2012

The simplest chat ever with SignalR (and Asp.Net MVC)

Lately I was investigating some technologies for my current project and at some point I was advised to check out the SignalR library. I admit I’ve never heard about it before (shame on me). It was mentioned to me in the context of asynchronous web applications, with the main example being a web chat. Hmm, an interesting exercise I thought! Plus it should give me the general framework understanding. Let’s do it!

It was only later that I realised the chat implementation is the most common example for SignalR usage that you can find on the Web. One more can hurt though, so here is my version :)

Overview

In short, the app works in the following way: people can visit a single chat url and they join our chat automatically. This mean they will see all the messages posted to the chat since they have joined it. They can also post messages that will be seen by other chat members.

I’ve built it as part of a sample MVC4 application, although this could probably be any Asp.Net page, as I’m not using any MVC functionality at all. Two most important parts of this app are the view and the hub. The view displays chat components and handles user actions (i.e. sending messages to the hub). The hub listens for messages and publishes them to all connected clients.

The code

You will need to downlaod the SignalR library for the following code to work. The easiest way to do that is by searching for 'SignalR' in your Nuget package manager.

So I have my Chat controller, which is only used to display the view. As you can see it’s doing nothing else, so the view could probably be a static html page instead:

public class ChatController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

It’s a web chat, so we need some input fields for nickname & message. We also need an area for displaying our conversation. All these belong naturally to our view:




Now that we have basic visual components, let’s make them work. Firstly, we need to reference jQuery & SignalR libraries. I have those defined as bundles in my MVC app, but you can reference all files directly:

@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/SignalR")
Notice the third reference - we reference a script, that doesn’t physically exist. SignalR will handle that script request, generating in response javascript code allowing us to communicate with the chat hub. The /signalr part of the uri is configurable.

Now it’s time for the javascript code (see comments for explanation):

$(function () {
    // get the reference to chat hub, generated by SignalR
    var chatHub = $.connection.chat;
 
    // add a method that can be called by the hub to update the chat
    chatHub.publishMessage = function (nick, msg) {
        var chatWin = $("#chatWindow");
        chatWin.html(chatWin.html() + nick + ": " + msg );
    };
    
    // start the connection with the hub
    $.connection.hub.start();
    
    $(document).keypress(function (e) {
        if (e.which == 13) {
            // when the 'Enter' key is pressed, send the message to the hub
            chatHub.sendMessage($("#nick").val(), $("#message").val());
            $("#message").val("");
        }
    });
});
The hub code could not be any simpler. We need to implement a method that can be called by a client wishing to send a message. The method broadcasts that message to all connected clients:
public class Chat : Hub
{
    public void SendMessage(string nick, string message)
    {
        Clients.PublishMessage(nick, message);
    }
 }
In case you haven't noticed yet: we execute a hub server method from our client javascript code (see line 17 of js code) and the other way around i.e. client side js function from our C# hub code (see line 5 of hub code). How cool is that?!?

I must say I'm pressed how easy it is to use for programmers. If you are wondering how it's working under the hood I recommend you reading SignalR documentation on their GitHub page. And finally, here's the screenshot I've taken testing that chat using 2 different browsers:

You can download my VC2012 solution from here: DOWNLOAD.

Monday 10 September 2012

AdMob ads in PhoneGap apps

Adding ads to your free mobile apps is one of the most common way of earning money in this business. There are multiple ads engine providers, but Google is still the leader. Google ads provider for mobile devices is called AdMob. It offers easy integration with Android, iPhone/IPad and WP7.

While integration with native apps is quite straightwforwrd and well documented, things get more complicated if you create your apps using PhoneGap and HTML5. In the past Admob offered "Smartphone Web" option, that could be presented within your HTML code for smartphone devices. Since May 2012 it's no longer available, as Google wants to make a clear division: use AdMob for purely mobile apps and AdSense for web pages.

Since mobile apps created using PhoneGap are actually web pages displayed within the native app and rendered using default browser engine it seems that AdSense is the way to go. It doesn't work though, with one of the reasons being that Google wants to crawl the sites it displays AdSense ads on.

Solution

So how do we display Google ads in HTML code that belongs to our PhoneGap app?
The answer is: WE DON'T! :)

Instead, we modify our native app container, that displays the HTML. Default PhoneGap templates for all systems (Android, WP7, iOS, ..) create a native, full-screen container for displaying your web app. We can shrink that main container and then display ads on the remaining free space using native AdMob SDK.

The only limitation of this method is that you cannot place your ad inside of your actual HTML appliaction. However, you can still place your ads in most commonly used spaces i.e. header or footer.

Android example

The sample code below presents the MainActivity of an Android app that uses PhoneGap. The code adds AdMob banner at the bottom of a mobile app:
import android.os.Bundle;
import org.apache.cordova.*;
import android.widget.LinearLayout; 
import com.google.ads.*;

public class MainActivity extends DroidGap {
    private static final String MY_AD_UNIT_ID = "YOUR_AD_UNIT_IT"; 
    private AdView adView;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        // Loading your HTML as per PhoneGap tutorial
        super.onCreate(savedInstanceState);
        super.loadUrl("file:///android_asset/www/index.html");
        
        // Adding AdMob banner
        adView = new AdView(this, AdSize.BANNER, MY_AD_UNIT_ID); 
        LinearLayout layout = super.root;  
        layout.addView(adView); 
        adView.loadAd(new AdRequest());
   }    
}

WP7 example

The sample code below presents default XAML created by PhoneGap template for WP7, modified to display AdMob banner at the bottom of a mobile app.

    
       
        
    
    
    
    
    

    
    
    

Thursday 6 September 2012

jQuery Mobile apps flicker on page transitions

Flickering screen on page transtions seems to be a common issue in mobile applications created using JQuery Mobile (and most likely packed with PhoneGap). The most common solution you will find on the Web is to add the following piece of CSS to your html:
.ui-page {
    -webkit-backface-visibility: hidden;
}
The problem with that solution is that it breaks Select list on your forms (and apparentally any other form input fields as well) on Android system. This makes your forms unusable.

Some people create an additional workaround for that issue i.e. they change this style property direct before the page transition occures and disable it right after it completes. A bit messy, don't you think?

Luckly, there is a much simpler solution. I realised that this flicekring is caused by the default transition effect used i.e. 'fade' for page transitions and 'pop' for dialogs. The simplest way to fix it seems to disable any effects of page/dialog transitions. Here is how you can do that with a little javascript code:

$(document).bind("mobileinit", function(){
    $.mobile.defaultDialogTransition = "none";
    $.mobile.defaultPageTransition = "none";
});