? | ? | ||
(One intermediate revision by one user not shown) | |||
Line 1: | Line 1: | ||
? | [[Category: | + | [[Category:Windows Phone]][[Category:Windows Phone 8]][[Category:XAML]] |
? |
| + | {{Abstract|This article explains how to check for app updates from inside an app. }} |
? | ? | ||
? |
| ? | |
? | ? | ||
? |
| ? | |
? | {{ArticleMetaData <!-- v1.3 --> | ? | {{ArticleMetaData <!-- v1.3 --> |
? | |sourcecode= <!-- Link to example source code e.g. [[Media:The Code Example ZIP.zip]] --> | ? | |sourcecode= <!-- Link to example source code e.g. [[Media:The Code Example ZIP.zip]] --> |
? | |installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.wgt]]) --> | ? | |installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.wgt]]) --> |
? | |devices= <!-- Devices tested against - e.g. Nokia Lumia 928, Nokia Asha 501) --> | + | |devices= Nokia Lumia 920 <!-- Devices tested against - e.g. Nokia Lumia 928, Nokia Asha 501) --> |
? | |sdk= <!-- SDK(s) built and tested against (e.g. Windows Phone 8.0 SDK) --> | + | |sdk= Windows Phone 8.0 SDK <!-- SDK(s) built and tested against (e.g. Windows Phone 8.0 SDK) --> |
? | |dependencies= <!-- Any other/external dependencies e.g.: Google Maps Api v1.0 --> ? | ? | |dependencies= <!-- Any other/external dependencies e.g.: Google Maps Api v1.0 --> ? |
? | |signing=<!-- Special Signing requirements --> | ? | |signing=<!-- Special Signing requirements --> |
Line 21: | Line 18: | ||
? | |update-by= <!-- After significant update: [[User:username]]--> | ? | |update-by= <!-- After significant update: [[User:username]]--> |
? | |update-timestamp= <!-- After significant update: YYYYMMDD --> | ? | |update-timestamp= <!-- After significant update: YYYYMMDD --> |
? | |creationdate= <!-- Format YYYYMMDD --> | + | |creationdate= 20130724 <!-- Format YYYYMMDD --> |
? | |author= <!-- Enter link [[User:username]] --> | + | |author= [[User:PedroLamas]]<!-- Enter link [[User:username]] --> |
? | }} | ? | }} |
? | ? | ||
? | == Introduction == | ? | == Introduction == |
? | ? | ||
? | + | A few months ago, I started receiving some crash reports from one of my most successful apps, [http://windowsphone.com/s?appid=7ca9cfea-1b92-4ca4-8559-269936d5361e Geosense]! | |
? | ? | ||
? | + | After fixing the issue and publishing an updated version of the app, until today I still get quite a few reports from the very same old version, but none from the updated one! | |
? | ? | ||
? |
| + | This has got me to think on the reason to why people don?t update their apps! Here are some reasons: |
? | + | * No constant internet connection | |
? | + | * Removing the Store tile from the Home screen | |
? | + | * Don?t care about updating apps! | |
? | ? | ||
? | ? | ||
? |
| ? | |
? | ? | ||
? | + | The first one doesn?t make much sense to me, as the Windows Phone ecosystem makes a lot more sense as a ?always online? system! Also, Geosense requires internet connection to work and crash reports can?t be done without internet connection, so this doesn?t seem to be the main reason in my case! | |
? | ? | ||
? |
| + | I don?t see the point in it, but not caring to check and update the apps in ones phone is just a matter of personal opinion! |
? |
| + | |
? | ? | ||
? | '' | + | That leaves the middle option: having the Store tile in the Home screen will enable users to get visual notification of updates (the number of updated apps appears in the tile); without it, the only other option is that the user actually opens the Store app from the applications menu. |
? | + | ? | |
? | + | == Coding time == | |
? | + | ? | |
? | + | Wouldn?t it be nice to just get the app to notify the user that an update is available? | |
? | + | ? | |
? | + | Keeping this in mind, I opened Fiddler on my laptop, set my phone to use it as a proxy server, opened Geosense info from the store, and this is the request I could see going to Microsoft servers: | |
? | + | ? | |
? | + | http://marketplaceedgeservice.windowsphone.com/v8/catalog/apps/7ca9cfea-1b92-4ca4-8559-269936d5361e?os=8.0.9903.0&cc=GB&oc=&lang=en-GB&hw=520170499&dm=RM-821_eu_euro1&oemId=NOKIA&moId=VOD-GB&cf=99-1 | |
? | + | ? | |
? | + | I can see in the above url the application ProductId (7ca9cfea-1b92-4ca4-8559-269936d5361e) the windows phone version (os=8.0.9903.0), the store territory (cc=GB), the language (lang=en-GB) and a bunch of other stuff related to the device brand, model and version. | |
? | + | ? | |
? | + | The response is even more interesting, as it shows all the Store information about the app, including the latest available version and release date. | |
? | + | ? | |
? | + | Given we are only interested in the version, after manually clearing up the response this is what we get: | |
? | + | ? | |
? | + | <code xml> | |
? | + | <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"> | |
? | + | ? <!-- other stuff --> | |
? | + | ? | |
? | + | ? <a:entry> | |
? | + | ? ? <!-- other stuff --> | |
? | + | ? | |
? | + | ? ? <version>1.10.1.8</version> | |
? | + | ? | |
? | + | ? ? <!-- other stuff --> | |
? | + | ? </a:entry> | |
? | + | ? | |
? | + | ? <!-- other stuff --> | |
? | + | </a:feed> | |
? | + | </code> | |
? | + | ? | |
? | + | Well, we now know how to get the Store information about a particular app, we know what gets returned and how to read it, so let?s put that all together! | |
? | + | ? | |
? | + | We will need the ProductID for the current running app, and for that we can just read it from the WMAppManifest.xml file like I shown in a [http://code.msdn.microsoft.com/Generating-a-Windows-Phone-9d19f939 previous article]: | |
? | + | ? | |
? | + | <code csharp> | |
? | + | public static string GetManifestAttributeValue(string attributeName) | |
? | + | { | |
? | + | ? ? var xmlReaderSettings = new XmlReaderSettings | |
? | + | ? ? { | |
? | + | ? ? ? ? XmlResolver = new XmlXapResolver() | |
? | + | ? ? }; | |
? | + | ? | |
? | + | ? ? using (var xmlReader = XmlReader.Create("WMAppManifest.xml", xmlReaderSettings)) | |
? | + | ? ? { | |
? | + | ? ? ? ? xmlReader.ReadToDescendant("App"); | |
? | + | ? | |
? | + | ? ? ? ? return xmlReader.GetAttribute(attributeName); | |
? | + | ? ? } | |
? | + | } | |
? | + | </code> | |
? | + | ? | |
? | + | Given that there is no way in the current SDK to retrieve the Store territory, we will fallback to the CultureInfo.CurrentUICulture value for it and also for the language. | |
? | + | ? | |
? | + | Here?s the complete async method to retrieve the latest version information from the Store: | |
? | + | ? | |
? | + | <code csharp>private Task<Version> GetUpdatedVersion() | |
? | + | { | |
? | + | ? ? var cultureInfoName = CultureInfo.CurrentUICulture.Name; | |
? | + | ? | |
? | + | ? ? var url = string.Format("http://marketplaceedgeservice.windowsphone.com/v8/catalog/apps/{0}?os={1}&cc={2}&oc=&lang={3}?", | |
? | + | ? ? ? ? GetManifestAttributeValue("ProductID"), | |
? | + | ? ? ? ? Environment.OSVersion.Version, | |
? | + | ? ? ? ? cultureInfoName.Substring(cultureInfoName.Length - 2).ToUpperInvariant(), | |
? | + | ? ? ? ? cultureInfoName); | |
? | + | ? | |
? | + | ? ? var request = WebRequest.Create(url); | |
? | + | ? | |
? | + | ? ? return Task.Factory.FromAsync(request.BeginGetResponse, result => | |
? | + | ? ? { | |
? | + | ? ? ? ? var response = (HttpWebResponse)request.EndGetResponse(result); | |
? | + | ? | |
? | + | ? ? ? ? if (response.StatusCode != HttpStatusCode.OK) | |
? | + | ? ? ? ? { | |
? | + | ? ? ? ? ? ? throw new WebException("Http Error: " + response.StatusCode); | |
? | + | ? ? ? ? } | |
? | + | ? | |
? | + | ? ? ? ? using (var outputStream = response.GetResponseStream()) | |
? | + | ? ? ? ? { | |
? | + | ? ? ? ? ? ? using (var reader = XmlReader.Create(outputStream)) | |
? | + | ? ? ? ? ? ? { | |
? | + | ? ? ? ? ? ? ? ? reader.MoveToContent(); | |
? | + | ? | |
? | + | ? ? ? ? ? ? ? ? var aNamespace = reader.LookupNamespace("a"); | |
? | + | ? | |
? | + | ? ? ? ? ? ? ? ? reader.ReadToFollowing("entry", aNamespace); | |
? | + | ? | |
? | + | ? ? ? ? ? ? ? ? reader.ReadToDescendant("version"); | |
? | + | ? | |
? | + | ? ? ? ? ? ? ? ? return new Version(reader.ReadElementContentAsString()); | |
? | + | ? ? ? ? ? ? } | |
? | + | ? ? ? ? } | |
? | + | ? ? }, null); | |
? | + | } | |
? | + | </code> | |
? | + | ? | |
? | + | All you now have to do is compare it to the active app version, like in this sample code: | |
? | + | ? | |
? | + | <code csharp> | |
? | + | private async void CheckForUpdatedVersion() | |
? | + | { | |
? | + | ? ? var currentVersion = new Version(GetManifestAttributeValue("Version")); | |
? | + | ? ? var updatedVersion = await GetUpdatedVersion(); | |
? | + | ? | |
? | + | ? ? if (updatedVersion > currentVersion | |
? | + | ? ? ? ? && MessageBox.Show("Do you want to install the new version now?", "Update Available", MessageBoxButton.OKCancel) == MessageBoxResult.OK) | |
? | + | ? ? { | |
? | + | ? ? ? ? new MarketplaceDetailTask().Show(); | |
? | + | ? ? } | |
? | + | } | |
? | + | </code> | |
? | + | ? | |
? | + | At startup, just call CheckForUpdatedVersion() and it will check if a new version is available, and if so, show a confirmation message box to the user and open the Marketplace details for the updated app. | |
? | + | ? | |
? | + | == The Cimbalino alternative == | |
? | + | ? | |
? | + | If you?re using [http://cimbalino.org/ Cimbalino Windows Phone Toolkit], I?ve added the [https://github.com/Cimbalino/Cimbalino-Phone-Toolkit/blob/master/src/Cimbalino.Phone.Toolkit.Background%20%28WP71%29/Services/IMarketplaceInformationService.cs '''IMarketplaceInformationService'''] that contains all the above logic to retrieve Store information for apps, with added bonus that will work not only for WP8 but also in WP7! | |
? | + | ? | |
? | + | For the time being, this new service is only available in the '''3.1.0-rc''' version of the toolkit, so make sure to install the pre-release version! | |
? | + | ? | |
? | + | {{VersionHint}} |
Latest revision as of 21:02, 24 July 2013
This article explains how to check for app updates from inside an app.
Article Metadata
Tested with
SDK: Windows Phone 8.0 SDK
Devices(s): Nokia Lumia 920
Compatibility
Article
[edit] Introduction
A few months ago, I started receiving some crash reports from one of my most successful apps, Geosense!
After fixing the issue and publishing an updated version of the app, until today I still get quite a few reports from the very same old version, but none from the updated one!
This has got me to think on the reason to why people don?t update their apps! Here are some reasons:
- No constant internet connection
- Removing the Store tile from the Home screen
- Don?t care about updating apps!
The first one doesn?t make much sense to me, as the Windows Phone ecosystem makes a lot more sense as a ?always online? system! Also, Geosense requires internet connection to work and crash reports can?t be done without internet connection, so this doesn?t seem to be the main reason in my case!
I don?t see the point in it, but not caring to check and update the apps in ones phone is just a matter of personal opinion!
That leaves the middle option: having the Store tile in the Home screen will enable users to get visual notification of updates (the number of updated apps appears in the tile); without it, the only other option is that the user actually opens the Store app from the applications menu.
[edit] Coding time
Wouldn?t it be nice to just get the app to notify the user that an update is available?
Keeping this in mind, I opened Fiddler on my laptop, set my phone to use it as a proxy server, opened Geosense info from the store, and this is the request I could see going to Microsoft servers:
http://marketplaceedgeservice.windowsphone.com/v8/catalog/apps/7ca9cfea-1b92-4ca4-8559-269936d5361e?os=8.0.9903.0&cc=GB&oc=&lang=en-GB&hw=520170499&dm=RM-821_eu_euro1&oemId=NOKIA&moId=VOD-GB&cf=99-1
I can see in the above url the application ProductId (7ca9cfea-1b92-4ca4-8559-269936d5361e) the windows phone version (os=8.0.9903.0), the store territory (cc=GB), the language (lang=en-GB) and a bunch of other stuff related to the device brand, model and version.
The response is even more interesting, as it shows all the Store information about the app, including the latest available version and release date.
Given we are only interested in the version, after manually clearing up the response this is what we get:
<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">
<!-- other stuff -->
?
<a:entry>
<!-- other stuff -->
?
<version>1.10.1.8</version>
?
<!-- other stuff -->
</a:entry>
?
<!-- other stuff -->
</a:feed>
Well, we now know how to get the Store information about a particular app, we know what gets returned and how to read it, so let?s put that all together!
We will need the ProductID for the current running app, and for that we can just read it from the WMAppManifest.xml file like I shown in a previous article:
public static string GetManifestAttributeValue(string attributeName)
{
var xmlReaderSettings = new XmlReaderSettings
{
XmlResolver = new XmlXapResolver()
};
?
using (var xmlReader = XmlReader.Create("WMAppManifest.xml", xmlReaderSettings))
{
xmlReader.ReadToDescendant("App");
?
return xmlReader.GetAttribute(attributeName);
}
}
Given that there is no way in the current SDK to retrieve the Store territory, we will fallback to the CultureInfo.CurrentUICulture value for it and also for the language.
Here?s the complete async method to retrieve the latest version information from the Store:
private Task<Version> GetUpdatedVersion()
{
var cultureInfoName = CultureInfo.CurrentUICulture.Name;
?
var url = string.Format("http://marketplaceedgeservice.windowsphone.com/v8/catalog/apps/{0}?os={1}&cc={2}&oc=&lang={3}?",
GetManifestAttributeValue("ProductID"),
Environment.OSVersion.Version,
cultureInfoName.Substring(cultureInfoName.Length - 2).ToUpperInvariant(),
cultureInfoName);
?
var request = WebRequest.Create(url);
?
return Task.Factory.FromAsync(request.BeginGetResponse, result =>
{
var response = (HttpWebResponse)request.EndGetResponse(result);
?
if (response.StatusCode != HttpStatusCode.OK)
{
throw new WebException("Http Error: " + response.StatusCode);
}
?
using (var outputStream = response.GetResponseStream())
{
using (var reader = XmlReader.Create(outputStream))
{
reader.MoveToContent();
?
var aNamespace = reader.LookupNamespace("a");
?
reader.ReadToFollowing("entry", aNamespace);
?
reader.ReadToDescendant("version");
?
return new Version(reader.ReadElementContentAsString());
}
}
}, null);
}
All you now have to do is compare it to the active app version, like in this sample code:
private async void CheckForUpdatedVersion()
{
var currentVersion = new Version(GetManifestAttributeValue("Version"));
var updatedVersion = await GetUpdatedVersion();
?
if (updatedVersion > currentVersion
&& MessageBox.Show("Do you want to install the new version now?", "Update Available", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
{
new MarketplaceDetailTask().Show();
}
}
At startup, just call CheckForUpdatedVersion() and it will check if a new version is available, and if so, show a confirmation message box to the user and open the Marketplace details for the updated app.
[edit] The Cimbalino alternative
If you?re using Cimbalino Windows Phone Toolkit, I?ve added the IMarketplaceInformationService that contains all the above logic to retrieve Store information for apps, with added bonus that will work not only for WP8 but also in WP7!
For the time being, this new service is only available in the 3.1.0-rc version of the toolkit, so make sure to install the pre-release version!
[edit] Version Hint
Windows Phone: [[Category:Windows Phone]]
[[Category:Windows Phone 7.5]]
[[Category:Windows Phone 8]]
Nokia Asha: [[Category:Nokia Asha]]
[[Category:Nokia Asha Platform 1.0]]
Series 40: [[Category:Series 40]]
[[Category:Series 40 1st Edition]] [[Category:Series 40 2nd Edition]]
[[Category:Series 40 3rd Edition (initial release)]] [[Category:Series 40 3rd Edition FP1]] [[Category:Series 40 3rd Edition FP2]]
[[Category:Series 40 5th Edition (initial release)]] [[Category:Series 40 5th Edition FP1]]
[[Category:Series 40 6th Edition (initial release)]] [[Category:Series 40 6th Edition FP1]] [[Category:Series 40 Developer Platform 1.0]] [[Category:Series 40 Developer Platform 1.1]] [[Category:Series 40 Developer Platform 2.0]]
Symbian: [[Category:Symbian]]
[[Category:S60 1st Edition]] [[Category:S60 2nd Edition (initial release)]] [[Category:S60 2nd Edition FP1]] [[Category:S60 2nd Edition FP2]] [[Category:S60 2nd Edition FP3]]
[[Category:S60 3rd Edition (initial release)]] [[Category:S60 3rd Edition FP1]] [[Category:S60 3rd Edition FP2]]
[[Category:S60 5th Edition]]
[[Category:Symbian^3]] [[Category:Symbian Anna]] [[Category:Nokia Belle]]
Miley Cyrus Twerking Jesus Shuttlesworth Michael Hastings mac miller bruno mars Hunter Hayes Born Sinner
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.