UPDATE 7 NOV 2011: Have a look at this post: WP7: Northern Lights WP7 Toolkit v0.0.1 for the latest version of this code example.
Inspired by the great talk of Jeff Wilcox on TechEd Australia (video here) I dediced to implement a Application Version checker for my application before I publish my first version to the marketplace.
Jeff Wilcox is the maker of 4Th & Mayor, a successful Windows Phone 7 application. In his talk on TechEd Australia he mentioned some tips&tricks for future application developers. One of those tips is to build a version checker in your app so you can notify the users when there is a new version available for your app.
He has a lot of users that are running an old version of his app and he has no way to reach out to them and inform them that there is a new version with a lot of new features.
The following code should solve this problem.
I implemented the AppVersionManager class which gets the latest version number from a text-file online and compares this with the version number stored in your WMAppManifest.xml.
AppVersionManager.c
namespace MyApp.Utils
{
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Threading;
///
/// AppVersionManager class.
///
public class AppVersionManager
{
#region Fields
private static string uri = "http://www.myapp.com/data/appversion.txt";
#endregion
#region Public methods
///
/// Check for new version of app and execute action when new version is available.
///
/// The action to execute when there is a new version available.
public static void CheckForNewVersion(Action action)
{
BackgroundWorker bgw = new BackgroundWorker();
bgw.DoWork += (sender, e) =>
{
Version appVersion = GetVersion();
DoWebRequest(AppVersionManager.uri, appVersion, action);
};
bgw.RunWorkerAsync();
}
#endregion
#region Private methods
private static Version GetVersion()
{
string version = StateManager.Get("AppVersion");
if (string.IsNullOrEmpty(version))
{
version = Utils.General.GetVersion();
StateManager.Set("AppVersion", version);
}
try
{
return new Version(version);
}
catch
{
}
return default(Version);
}
private static void DoWebRequest(string uri, Version appVersion, Action action)
{
string id = "appversionrequest";
if (action == null)
{
return;
}
Timer t = null;
int timeout = 60; // in seconds
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Accept = "*/*";
request.AllowAutoRedirect = true;
// disable caching.
request.Headers["Cache-Control"] = "no-cache";
request.Headers["Pragma"] = "no-cache";
t = new Timer(
state =>
{
if (string.Compare(state.ToString(), id, StringComparison.InvariantCultureIgnoreCase) == 0)
{
Debug.WriteLine(string.Format("Timeout reached for connection [{0}], aborting download.", id));
request.Abort();
t.Dispose();
}
},
id,
timeout * 1000,
0);
request.BeginGetResponse(
r =>
{
try
{
if (t != null)
{
t.Dispose();
}
var httpRequest = (HttpWebRequest)r.AsyncState;
var httpResponse = (HttpWebResponse)httpRequest.EndGetResponse(r);
if (httpResponse.StatusCode == HttpStatusCode.OK)
{
using (StreamReader reader = new StreamReader(httpResponse.GetResponseStream()))
{
string response = reader.ReadToEnd();
try
{
Version currentVersion = new Version(response);
if (appVersion < currentVersion)
{
action();
}
}
catch
{
}
}
}
else
{
Debug.WriteLine(string.Format("Error occured accessing endpoint: {0} [{1}]", httpResponse.StatusCode, uri));
}
}
catch
{
Debug.WriteLine(string.Format("Error occured accessing endpoint: [{0}]", uri));
}
},
request);
}
catch
{
}
}
#endregion
}
}
the Utils.General.GetVersion() implementation
public static string GetVersion()
{
Uri manifest = new Uri("WMAppManifest.xml", UriKind.Relative);
var si = Application.GetResourceStream(manifest);
if (si != null)
{
using (StreamReader sr = new StreamReader(si.Stream))
{
bool haveApp = false;
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
if (!haveApp)
{
int i = line.IndexOf("AppPlatformVersion=\"", StringComparison.InvariantCulture);
if (i >= 0)
{
haveApp = true;
line = line.Substring(i + 20);
int z = line.IndexOf("\"");
if (z >= 0)
{
// if you're interested in the app plat version at all
// AppPlatformVersion = line.Substring(0, z);
}
}
}
int y = line.IndexOf("Version=\"", StringComparison.InvariantCulture);
if (y >= 0)
{
int z = line.IndexOf("\"", y + 9, StringComparison.InvariantCulture);
if (z >= 0)
{
// We have the version, no need to read on.
return line.Substring(y + 9, z - y - 9);
}
}
}
}
}
return "Unknown";
}
The contents of the appversion.txt file
1.1.0.0
So know you can call AppVersionManager from your MainPage.xaml to check for a new version and execute whatever you want to notify the user of your new version of the application.
AppVersionManager.CheckForNewVersion(() =>
{
// notify user of new version.
});
Probably the best way is to show a popup and ask the user if he wants to upgrade and then navigate him to the MarketPlace.
Alright, that's all. I hope you like it! Feedback is welcome.
UPDATE: added 'if (action == null)' in the top of DoWebRequest method to skip webrequest when there is no action specified. Thanks to @peSHIr.

