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.