Как перезапустить приложение UWP программно

В некоторых приложениях (особенно в играх) приложение не может попасть в состояние, в котором его необходимо перезагрузить — возможно, после обновления лицензии или после установки загружаемого контента его кэш стал загромождён данными о предыдущем не актуальном состоянии или по какой-либо другой причине, приложение должно обновить своё состояние с нуля. В более ранних версиях ваш единственный вариант заключался  в том, чтобы побудить пользователя закрыть и перезапустить или вызвать CoreApplication.Exit — и обе опции обеспечивают неоптимальный пользовательский интерфейс.

Поэтому мы внедрили новый API, который позволяет приложению запрашивать немедленное завершение и перезапуск, а также передавать произвольные аргументы в новый экземпляр. В этой публикации мы рассмотрим как это работает и как вы можете задействовать его в своем приложении. Теперь это доступно в сборках Insider начиная с Build 16226  вместе с соответствующим SDK.

Вот пример приложения, называемое TestRestart.

Приложение предоставляет ListView городов слева, выбранный в настоящий момент город справа и TextBox для предоставления аргументов приложению при его перезапуске. Когда пользователь удаляет кнопку «Request Restart», приложение завершается и перезапускается, передавая входящие аргументы. Новый API, RequestRestartAsync, отображается как статический метод для объекта CoreApplication. Он принимает строковый параметр, который может быть любым строковым значением, которое вам нравится — включая ввод пользователем или получаемым от другого внешнего объекта. Если вы решите принять ввод таким образом, вы несете ответственность за правильность его проверки, и должны убедиться, что он соответствует любым ограничениям, которые вы навязываете. Вы должны выполнить эту проверку на входе, прежде чем передавать ее в RequestRestartAsync. В этом примере приложения мы ожидаем, что пользователь наберет название города.

  1. async private void DoRestartRequest()
  2. {
  3. bool isValidPayload = false;
  4. string payload = restartArgs.Text;
  5. if (!string.IsNullOrEmpty(payload))
  6. {
  7. foreach (ImageViewModel imageItem in imageListView.Items)
  8. {
  9. if (imageItem.Name == payload)
  10. {
  11. isValidPayload = true;
  12. break;
  13. }
  14. }
  15. }
  16. if (isValidPayload)
  17. {
  18. AppRestartFailureReason result =
  19. await CoreApplication.RequestRestartAsync(payload);
  20. if (result == AppRestartFailureReason.NotInForeground ||
  21. result == AppRestartFailureReason.RestartPending ||
  22. result == AppRestartFailureReason.Other)
  23. {
  24. Debug.WriteLine(«RequestRestartAsync failed: {0}», result);
  25. }
  26. }
  27. }

Чтобы смягчить проблемы конфиденциальности, приложение разрешено только перезапускать, если оно находится в потоке переднего плана в момент его запроса. Когда приложение перезагружается, оно перезапускается с обычным пользовательским интерфейсом, то есть в качестве обычного окна переднего плана. Если бы мы разрешили перезапуск фоновой задачи или свернутое приложение, результат был бы неожиданным для пользователя. Вот почему API реализует это как запрос. Если запрос отклонен, приложение должно будет обработать сбой — возможно, дождавшись, пока он окажется на переднем плане, и повторит попытку. Если бы вы запросили перезапуск, а затем через какой-то фокус с логикой удалось запросить его еще до того, как система запустила операцию, то вы получите результат RestartPending, хотя это крайний случай. Вы вряд ли когда-либо получите другой результат — если что-то пойдет не так, как предусмотрено платформой.

Обратите внимание, что это единственное существенное ограничение, но вы должны использовать этот API вдумчиво. Например, вы, вероятно, не должны использовать его, если ваше приложение не было первоначально запущено пользователем — например, если оно было запущено в результате операции совместного использования или выбора. Перезапуск в середине одной из этих операций контрактов безусловно запутает пользователя.

Если запрос выполнен, приложение завершается, а затем перезапускается. Существует множество способов активировать приложение: помимо обычной активации запуска приложения могут поддерживать активацию файлов, активацию протокола, активацию общего доступа или сборщика и так далее. Список указан здесь. Для случая перезапуска приложение будет активировано как при обычном запуске — точно так же, как если бы пользователь закрыл приложение вручную и нажал на его тайл, чтобы запустить его снова, но задействовал определенные аргументы, предоставленные ранее (если они есть).

В вашем классе App вы должны обработать это, переопределив метод OnActivated. Проверьте ActivationKind, и если это ActivationKind.Launch, то входящие IActivatedEventArgs будут LaunchActivatedEventArgs. Из этого вы можете получить входящие аргументы активации. Для обычного запуска, инициированного пользователем, аргументы будут пустыми, поэтому, если они не пусты, вы можете просто указать, что это активация перезапуска. Вы также можете проверить свойство PreviousExecutionState, которое для операции перезагрузки будет установлено в состояние Terminated.

Хотя аргументы, возможно, возникли из ненадежного источника (например, пользователя), вы должны были выполнить проверку перед запросом перезагрузки. Если это так, вы можете считать их надежными, когда получите их в OnActivated.

  1. protected override void OnActivated(IActivatedEventArgs args)
  2. {
  3. switch (args.Kind)
  4. {
  5. case ActivationKind.Launch:
  6. LaunchActivatedEventArgs launchArgs = args as LaunchActivatedEventArgs;
  7. string argString = launchArgs.Arguments;
  8. Frame rootFrame = Window.Current.Content as Frame;
  9. if (rootFrame == null)
  10. {
  11. rootFrame = new Frame();
  12. Window.Current.Content = rootFrame;
  13. }
  14. rootFrame.Navigate(typeof(MainPage), argString);
  15. Window.Current.Activate();
  16. break;
  17. }
  18. }

То, что вы делаете с входящими аргументами, полностью зависит от вас. В этом приложении мы просто передаем их на MainPage. В MainPage, в свою очередь, у нас есть переопределение OnNavigatedTo, которое использует строку для выбора элемента в ListView:

  1. protected override void OnNavigatedTo(NavigationEventArgs e)
  2. {
  3. string payload = e.Parameter as string;
  4. if (!string.IsNullOrEmpty(payload))
  5. {
  6. foreach (ImageViewModel imageItem in imageListView.Items)
  7. {
  8. if (imageItem.Name == payload)
  9. {
  10. imageListView.SelectedItem = imageItem;
  11. break;
  12. }
  13. }
  14. }
  15. }

Как вы можете видеть, метод CoreApplication.RequestRestartAsync — это простое API. Вы можете использовать его для немедленного прекращения работы своего приложения и перезапустить его, как если бы это было сделано пользователем, с дополнительной возможностью передачи произвольных аргументов при активации.

Пример кода

Перевод оригинальной публикации How to Restart your App Programmatically
Автор:
Перевод: Сергей Урусов

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *