After reading Saad Mahmood's recent post,
Check for Updates of Your App Inside Your Windows Phone Application, I've decided to provide a solution that will work for Windows Phone 8.1 applications developed using the universal app model.
The Windows Phone store allows for automatic installation of updates as they become available but not all users want to allow their mobile device to update apps, especially if they are on their network data connection. Here is a simple solution your apps that will allow you to prompt your users to download the latest update if there is one available.
Getting your app information from the Store
The Windows Phone store gets information about its apps by querying an API endpoint which then returns a response with all the store information about a given app. Using Fiddler4, it is possible to watch the traffic made on your Windows Phone's Wi-Fi connection. If you set this up, navigate to the store and pick an app to view information of, you'll notice that Fiddler records a call to the following API endpoint:
http://marketplaceedgeservice.windowsphone.com/v9/catalog/apps/1a625b44-b542-401b-bdff-52b4357c0573?os=8.10.14219.0&cc=US&lang=en-US&hw=520190979&dm=RM-821_eu_euro1_342&oemId=NOKIA&moId=tmo-gb&cf=99-1
If you take a look at the parts to that URL, you'll quickly notice a query built up with the App ID (i.e. 1a625b44-b542-401b-bdff-52b4357c0573), the version of Windows Phone OS (i.e. os=8.10.14219.0), the country store requesting from (i.e. cc=US), the language of the device (i.e. lang=en-US) and a few other fields including the OEM ID and network provider.
If you navigate to this URL using your web browser, you'll receive an XML file back containing all the information about the application which includes the current version number of the application known to the store. If you're looking to write your own Store application, here's a great place to start, however we're going to look at the important part of the XML file which is the version number.
- <?xml version="1.0" encoding="utf-8"?>
- <a:feed
- xmlns:a="http://www.w3.org/2005/Atom"
- xmlns:os="http://a9.com/-/spec/opensearch/1.1/"
- xmlns="http://schemas.zune.net/catalog/apps/2008/02">
-
- <a:entry>
- <version>0.10.4.40</version>
- </a:entry>
- </a:feed>
Getting the Store Version number in C#
Extracting all of the irrelevant information, you're left with a very simple XML file with a version number that can be easily extracted in your C# code. Here's how you can perform the query call in your application and check whether your local version number is different to the one from the store.
- public async Task<bool> IsLatestVersion()
- {
- var packageVersion = Package.Current.Id.Version;
-
- var formattedVersion = string.Format(
- "{0}.{1}.{2}.{3}",
- packageVersion.Major,
- packageVersion.Minor,
- packageVersion.Build,
- packageVersion.Revision);
-
- var appId = CurrentApp.AppId.ToString();
-
- var language = CultureInfo.CurrentUICulture.Name;
- var store = language.Substring(language.Length - 2).ToUpperInvariant();
-
- using (var client = new HttpClient(new HttpClientHandler(), true))
- {
- var queryUrl =
- string.Format(
- "http://marketplaceedgeservice.windowsphone.com/v9/catalog/apps/{0}?os=8.10.14219.0&cc={1}&lang={2}",
- appId,
- store,
- language);
-
- var data = await client.GetStringAsync(queryUrl);
-
- var versionElement = ExtractVersionNumber(data);
-
- if (versionElement != null)
- {
- var storeVersion = versionElement.Value;
-
- var currentVersion = new Version(formattedVersion);
- var foundVersion = new Version(storeVersion);
-
- if (foundVersion > currentVersion)
- {
- return false;
- }
- }
- }
-
- return true;
- }
-
- private static XElement ExtractVersionNumber(string data)
- {
- var doc = XDocument.Parse(data);
- var elements = doc.Descendants();
-
- var versionElement = elements.FirstOrDefault(x => x.Name.LocalName == "version");
- return versionElement;
- }
You can call the awaitable IsLatestVersion() method where you'd like to within your application so that you can prompt the user to navigate to the Marketplace when the returning result is false.