Monday, September 3, 2012

Windows Azure Mobile Services and Mono for Android

This blog entry is based on the article from Chris Risner, which you find here:

 In this article, we’ll walk through creating a new Mobile Service and then connecting an Mono for Android  client to it.  By the end of this walkthrough, we’ll have reproduced an Android client, with all of the capabilities of the initial Todos Windows 8 Mobile Services demo. You’ll be able to:
·         Add new todos.
·         List those todos.
·         Mark todos complete
Please follow Chris’ tutorial until it states: Starting the iOS Client
We do not want to do this, instead we are going to create a Mono for Android client, the result of this blog entry looks like this:

Prerequisites

First you need to install the prerequisites. Basically you will need Mono for Android, MonoDroid and the Android SDK. You will find more info here: http://docs.xamarin.com/android
Next ou will need the Android.Dialog Project from here:
https://github.com/sam-lippert/Android.Dialog, which I use to create the tableview.

I recommend to start the provided C# client for your Mobile Service created in Azure and enter some ToDoItems, this will make your life a bit easier later on as you will actually see some results.

Starting the Mono for Android Client

If you can't wait, you will find the source code here:
Start up MonoDroid and create a new project using the Mono for Android Application Template

You can name your project whatever you want (I’ve named mine, “AndroidAzure”).  
The next steps are:

  • Add a reference to Android.Dialog
  • Add  a reference to System.Json
  • Add dialog_multiline_labelfieldbelow.xml to the layout folder.
  • Add a folder SupportLib in Resources and put android-support-v4.jar there
  • Change the build action to AndroidJavaLibrary
Your project should look like this up to now:


Now it’s time to start coding. Open Activity1.cs and add the following code snippets:
·         Add the required using statements

using Android.Dialog;
using System.Threading;
using System.Net;
using System.IO;
using System.Json;

·         Add the connection information
string kGetAllUrl = @"https://yoursubdomain.azure-mobile.net/tables/TodoItem?$filter=(complete%20eq%20false)";
string kAddUrl = @"https://yoursubdomain.azure-mobile.net/tables/TodoItem";
string kUpdateUrl = @"https://yoursubdomain.azure-mobile.net/tables/TodoItem/";
string kMobileServiceAppId = @"yourappkey";

You’ll want to replace “yoursubdomain” with the URL you’ve set up for your site and the app ID with the key you pulled out of the Manage Keys modal earlier on.  Let’s stop for a second and take a look at these URLs.  This is our first insight into how Mobile Services works.  kGetAllUrl has at the end /tables/TodoItem which corresponds to the TodoItem table we created earlier.  After there is a query string parameter to specify a filter.  Here, we’re telling it to only pull back todo items which have a complete flag of false.  If we dropped the filter, we’d get back all the todo items.  kAddUrl and kUpdateUrl are the nearly the same, however, the update url has the slash at the end.  The reason for this is that when we  create, we just need to specify which table we’re going to create something in.  If we update, we need to include the ID of the item we’re updating in the query (after the slash).  
·         Change the OnCreate method to show a ProgressDialog and start to read the Azure data using the ThreadPool class in an async way.
protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);
 
    _pd = ProgressDialog.Show(this, "Please wait...", 
                       "Querying Azure!");
 
    ThreadPool.QueueUserWorkItem(delegate
    {
        var root = BuildRoot(kGetAllUrl);

        RunOnUiThread(delegate
        {
            var da = new DialogAdapter(this, root);
            var lv = new ListView(this) { Adapter = da };

            SetContentView(lv);
            _pd.Dismiss();
            _pd.Dispose();
        });
 
    });
}


·         The root element is build in the BuildRoot method
private RootElement BuildRoot(string url)
{
    var root = new RootElement(String.Empty);
    var section = new Section("TodoItems");
    root.Add(section);
    var result = GetAzureResult(url);

    foreach (JsonObject item in result)
    {
        section.Add(new StringElement(item["text"]));
    }
    return root;
}
·         And finally the heart of the work we need to do, actually read the azure data.

public JsonArray GetAzureResult(string url)
{
 
    var request = (HttpWebRequest)WebRequest.Create(url);
    request.Method = WebRequestMethods.Http.Get;
    request.Accept = "application/json";
    request.Headers.Add("X-ZUMO-APPLICATION", kMobileServiceAppId);
    request.AutomaticDecompression = DecompressionMethods.GZip | 
               DecompressionMethods.Deflate;
 
    using (var response = (HttpWebResponse)request.GetResponse())
    {
        using (var streamReader = new StreamReader(response.GetResponseStream()))
        {
            JsonValue root = JsonValue.Load(streamReader);
            return ((JsonArray)root);
        }
    }
}

The only thing really interesting here is that we’re sending over the application key as a header named X-ZUMO-APPLICATION.  If you don’t send this to Mobile Services (code named Zumo prior to launch) then you’ll receive back a 401 unauthorized error from the server.

Running the application for the first time

Now if you run your application, you won’t see anything (unless you also ran the Win8 program first and created Todos) spectacular, you will see the please wait dialog and a blank screen.  


But if you tried the C# Client provided by Microsoft and you were entering some todo items, you will see them in your client:

In the next part we will add new items to the azure todolist.....



CSharpCodeFormatter