«Хорошие художники копируют; великие художники воруют »- Стив Джобс
Каждый разработчик Windows Phone , имеющий друзей, родственников или жену, не имеющих технических знаний, с Windows Phone, знает проблему: многие пользователи не проверяют свой Магазин регулярно и просто не обновляют свои приложения — или, по крайней мере, недостаточно часто. Высокоинтеллектуальный Педро Ламас — старший инженер Nokia, автор инструментария Cimbalino для Windows Phone и мой личный спаситель, когда я столкнулся с некоторыми очень экзотическими проблемами с Nokia Music — недавно описал способ автоматической проверки наличия обновлений внутри приложения .С его разрешения я решил упаковать основную логику в поведение, очень похожее на то, что я делал с логикой оценок в моем предыдущем посте — так что вы можете перетащить это на свою главную страницу приложения и покончить с этим. Педро использовал что-то вроде мой SafeBehavior в Cimbalino, и теперь я использую часть его кода в библиотеке wp7nl на codeplex . Вот как работает сообщество. В этом свете цитата в верхней части этой статьи выбрана неудачно ?
Если вы уроните UpgradeCheckBehavior, как я это окрестил, на главную страницу вашего приложения, Blend предложит вам только две опции: заголовок окна сообщения и текст окна сообщения:
- Заголовок — это текст, который будет отображаться в окне сообщения при обнаружении новой версией поведения. Значением по умолчанию является «Новая версия!»
- Сообщение — это текст, который появится внутри окна сообщения, когда поведение обнаружит новую версию. Значение по умолчанию: «Доступна новая версия этого приложения, вы хотите обновить?»
Если вы в порядке с этим, вы закончили. Приложение будет проверять наличие обновлений автоматически при запуске приложения.
Само поведение является довольно простым SafeBehavior и выглядит так:
using System; using System.Globalization; using System.Net; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Xml; using Microsoft.Phone.Tasks; using Wp7nl.Utilities; namespace Wp7nl.Behaviors { /// <summary> /// A behavior checking from in the app if there's an update available. /// </summary> public class UpgradeCheckBehavior : SafeBehavior<Page> { private ManifestAppInfo appInfo; protected override void OnSetup() { appInfo = new ManifestAppInfo(); CheckUpgrade(); } private void CheckUpgrade() { #if !DEBUG GetLatestVersion().ContinueWith(ProcessResult); #endif } } }
Поскольку в режиме отладки приложение будет работать на вашем телефоне или эмуляторе с использованием сгенерированного временного идентификатора приложения, в любом случае невозможно будет проверить наличие новых версий, поэтому я добавил оператор #if вокруг фактической проверки.
Используя мой вспомогательный класс ManifestAppInfo, я извлекаю все метаданные приложения, которые используются GetLatestVersion — по сути, слегка измененную версию работы Педро:
/// <summary> /// This method is almost 100% stolen from /// http://www.pedrolamas.com/2013/07/24/checking-for-updates-from-inside-a-windows-phone-app/ /// </summary> private Task<Version> GetLatestVersion() { var cultureInfoName = CultureInfo.CurrentUICulture.Name; var url = string.Format( "http://marketplaceedgeservice.windowsphone.com/v8/catalog/apps/{0}?os={1}&cc={2}&oc=&lang={3}", appInfo.ProductId, Environment.OSVersion.Version, cultureInfoName.Substring(cultureInfoName.Length - 2).ToUpperInvariant(), cultureInfoName); var request = WebRequest.Create(url); return Task.Factory.FromAsync(request.BeginGetResponse, result => { try { 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()); } } } catch (Exception) { return null; } }, null); }
Я думаю, что мое единственное дополнение к этому — это попытка поймать метод, поскольку у меня, как правило, возникали некоторые странные ошибки при запуске его в Visual Studio. Этот метод ловко загружает метаданные приложения из магазина и извлекает из него версию.
И тогда, конечно, единственное, что осталось, — это сравнить полученную версию с текущей версией, а если текущая версия больше, отобразить окно с просьбой обновить пользователя:
private void ProcessResult(Task<Version> t) { if(t.IsCompleted && t.Result != null ) { var currentVersion = new Version(appInfo.Version); if (currentVersion < t.Result ) { DoShowUpgrade(); } } } private void DoShowUpgrade() { Deployment.Current.Dispatcher.BeginInvoke(() => { var result = MessageBox.Show(Message, Caption, MessageBoxButton.OKCancel); if (result == MessageBoxResult.OK) { var marketplaceReviewTask = new MarketplaceDetailTask(); try { marketplaceReviewTask.Show(); } catch (InvalidOperationException ex) { } } }); }
И это все, что нужно. Два свойства зависимости, содержащие заголовок и сообщение, были опущены для краткости. Грустная вещь блестящей идеи Педро состоит в том, что довольно сложно проверить, действительно ли это работает. Что ж, позвольте мне заверить вас, что это так, и если вы запустите демонстрационное решение в конфигурации режима релиза , оно покажет вам, действительно запрашивая обновление:
Как это возможно? Приложение, созданное Visual Studio, запускает временный идентификатор, которого даже не должно быть в Магазине! Это верно, если вы не сделаете это с реальным идентификатором. Поэтому я открыл файл WPAppManifest.xml, который находится в папке «Свойства», и немного испортил настройки:
Я изменил идентификатор приложения на идентификатор моей последней игры 2 Phone Pong в магазине и изменил номер версии на 0.9.0.0 (в то время как номер версии в Магазине, конечно, по крайней мере, 1.0.0.0). Теперь приложение думает, что спросить в магазине номер версии 2 Phone Pong, возвращает (на момент написания этой статьи) 1.0.0.0, выясняет, что она ниже текущей версии, и выдает сообщение. Если вы нажмете кнопку «ОК», это приведет вас к 2 Phone Pong в Магазине. Это доказывает, что код Педро на самом деле работает, и теперь у вас есть решение с нулевым кодом, позволяющее вашим пользователям использовать самую лучшую версию вашего приложения, и больше нет оправданий не делать этого ?
Предупреждение. Не пытайтесь развернуть отладочную версию своего приложения с помощью этого трюка с идентификатором на телефоне, на котором установлено фактическое приложение, загруженное из Магазина. Это не сработает — у вас не будет прав на запись. Я не пробовал противоположного — загружать приложение из магазина поверх приложения, развернутого из Visual Studio, — но я могу себе представить, что таким способом можно запачкать только грязные пироги.
Скоро я включу это в следующую версию моей библиотеки wp7nl на codeplex