Last.fm API for a Windows Phone App – Auth

As per the request of many Beem users, I am implementing Last.fm track scrobbling. The first part of this task is to implement an API client for the Last.fm web service, and step one is user authentication. Last.fm is not using OAuth, but rather its own implementation of an authentication engine that relies on a composite MD5 secret.

But let’s begin with the basics. As it is a mobile application, I need to perform a request to the core endpoint with the auth.getMobileSession method. The URL is https://ws.audioscrobbler.com/2.0/. Remember to use HTTPS, as it is an inherent requirement for the request to be successful. Two required components of the request are the API key and the API secret – both can be obtained as you register your own application on the Last.fm developer portal.

NOTE: Ignore the is+[space] part and just use the code that comes afterwards.

The API call is complete only when it is accompanied by a signature. The signature is generated by building a composite string, made of each parameter and value concatenated together (with no delimiters) in alphabetical order, followed by the API secret, that are later hashed with an MD5 helper. Since by default the Windows Phone 7.1 SDK comes without the standard .NET MD5CryptoServiceProvider, I have to carry an internal implementation. You could take a look at the specifics of the MD5 algorithm here, or you could download a ready-to-go class created by Reid Borsuk and Jenny Zheng here (which is what I am using in the app). The method I am using to get the signature looks like this:

 public string GetSignature(Dictionary<string, string> parameters)
{
string result = string.Empty;

IOrderedEnumerable<KeyValuePair<string, string>> data = parameters.OrderBy(x=>x.Key);

foreach (var s in data)
{
result += s.Key + s.Value;
}

result += SECRET;
result = MD5Core.GetHashString(Encoding.UTF8.GetBytes(result));

return result;
}

The next step is to perform the authentication request itself, to get the session key. A raw implementation of the necessary method can look like this:

 public void GetMobileSession(string userName, string password, Action<string> onCompletion)
{
var parameters = new Dictionary<string, string>();
parameters.Add("username", userName);
parameters.Add("password", password);
parameters.Add("method", "auth.getMobileSession");
parameters.Add("api_key", API_KEY);

string signature = GetSignature(parameters);

string comboUrl = string.Concat(CORE_URL, "?method=auth.getMobileSession", "&api_key=", API_KEY,
"&username=", userName, "&password=", password, "&api_sig=", signature);

var client = new WebClient();
client.UploadStringAsync(new Uri(comboUrl),string.Empty);
client.UploadStringCompleted += (s, e) =>
{
try
{
onCompletion(e.Result);
}
catch (WebException ex)
{
HttpWebResponse response = (HttpWebResponse)ex.Response;
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
Debug.WriteLine(reader.ReadToEnd());
}
}
};
}

As the signature is obtained, I still need to include the parameters in the URL, including the method, API key and the proper credentials. The request has to be a POST one, therefore I am using UploadStringAsync instead of DownloadStringAsync, which will execute a GET request.

Simple as that, you have the auth session key.

FallFury is now in the Windows Store

With the full tutorial series and the PDF eBook, it would only be logical that the next step in the FallFury story would be releasing the game in the Windows Store. Today, I am happy to announce that my first big game development project successfully passed certification and is now available in most of the locations worldwide in the Windows Store.

clip_image010[6]

You can download it here.

It is a project that I am constantly improving, so more levels and items will be added. Feel free to review the game and give me some feedback on how the overall gameplay experience can be better.

FallFury eBook Available

Almost a week ago, my FallFury series (building a hybrid Windows Store XAML/DirectX/C++ game) was released on Channel9. 12 articles and associated videos is a lot to go through, and you might not always have an active internet connection.

That’s why Brian Peek tackled the task of creating a PDF version of the series, and he did a fantastic job at it. 130 pages of content that will help you get started with creating games for Windows Store.

Download Here

Also, remember that you can download the FallFury source code on the official project CodePlex page.

FallFury – now available on Channel9 Coding4Fun and CodePlex

If you follow this blog, you probably know that I spent the Summer of 2012 in Redmond, WA, working on the Channel9 Coding4Fun team. My project for that period was FallFury – a 2D game that was designed to demonstrate the capabilities of the Windows 8 (specifically, Windows Store) development platform when it comes to creating hybrid applications (C++/XAML/DirectX).

There is a total of 12 parts, both videos and articles (choose whichever you method you like to learn more). You can find those here:

Last.fm API for a Windows Phone App – Scrobbling a Track

As I discussed the basic of authentication in my previous post, the most important Last.fm feature that is added to Beem in itself is track scrobbling, which will allow you to keep records of what you listened to from your favorite music aggregation service. The implementation of the method used to send the track from the app to Last.fm is extremely similar to GetMobileSession.


public void ScrobbleTrack(string artist, string track, string sessionKey,
Action<string> onCompletion)
{
string currentTimestamp = DateHelper.GetUnixTimestamp();

var parameters = new Dictionary<string, string>();
parameters.Add("artist[0]", artist);
parameters.Add("track[0]", track);
parameters.Add("timestamp[0]", currentTimestamp);
parameters.Add("method", "track.scrobble");
parameters.Add("api_key", API_KEY);
parameters.Add("sk", sessionKey);

string signature = GetSignature(parameters);

string comboUrl = string.Concat(CORE_URL, "?method=track.scrobble", "&api_key=", API_KEY,
"&artist[0]=", artist, "&track[0]=", track, "&sk=", sessionKey,
"&timestamp[0]=", currentTimestamp,
"&api_sig=", signature);

var client = new WebClient();
client.UploadStringAsync(new Uri(comboUrl), string.Empty);
client.UploadStringCompleted += (s, e) =>
{
try
{
onCompletion(e.Result);
}
catch (WebException ex)
{
HttpWebResponse response = (HttpWebResponse)ex.Response;
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
Debug.WriteLine(reader.ReadToEnd());
}
}
};
}

The new required parameters here are the artist name, the track name, a UNIX-style timestamp and the session key that you obtained from the core authentication method. Although there is no method in C# to give you the UNIX timestamp right away, you can easily do it like this:

 using System;

namespace Beem.Utility
{
public static class DateHelper
{
public static string GetUnixTimestamp()
{
TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
return ((int)t.TotalSeconds).ToString();
}
}
}

Also notice that the parameters for the track are sent in array format. Since I am only scrobbling one track at a time, I can use the index zero [0]. Your situation might be different. ScrobbleTrack can be invoked like this:

 LastFmClient client = new LastFmClient();
client.ScrobbleTrack("Armin van Buuren", "In and Out Of Love", "SESSION_KEY",
(s) =>
{
Debug.WriteLine("Success!");
});

You should now see the track registered on Last.fm.