Запуск приложения для результатов

Важные API

Узнайте, как запустить приложение из другого приложения и обмениваться данными между двумя приложениями. Это называется запуском приложения для получения результатов. В приведенном примере показано, как запустить приложение для результатов с помощью метода LaunchUriForResultsAsync.

Благодаря новым API для связи между приложениями в Windows 10 приложения для Windows (а также веб-приложения для Windows) могут запускать приложения и обмениваться данными и файлами. Это позволяет выполнять построение смешанных решений из нескольких приложений. С помощью этих новых API сложные задачи, для которых раньше приходилось использовать несколько приложений, теперь можно выполнять без проблем. Например, ваше приложение может запустить приложение социальной сети для выбора контакта или приложение для оформления заказа, чтобы завершить оплату.

Приложение, которое запускается для результатов, называется запущенным приложением. Приложение, которое запускает другое приложение, называется вызывающим приложением. В этом примере мы создадим и вызывающее, и запущенное приложение.

Шаг 1. Регистрация протокола, который будет обрабатываться в приложении, запущенном для результатов

В файле Package.appxmanifest запущенного приложения добавьте расширение протокола в <раздел Приложение> . В этом примере используется вымышленный протокол с именем test-app2app.

Атрибут ReturnResults в расширении протокола принимает одно из указанных ниже значений.

  • optional — приложение может запускаться для результатов с помощью метода LaunchUriForResultsAsync или не для результатов с помощью метода LaunchUriAsync. Если вы используете ключевое слово optional, то запущенное приложение должно определить, было ли оно запущено для результатов. Это можно сделать путем проверки аргумента события OnActivated. Если свойство аргумента IActivatedEventArgs.Kind возвращает перечисление ActivationKind.ProtocolForResults или тип аргумента события равен ProtocolActivatedEventArgs, то приложение было запущено с помощью метода LaunchUriForResultsAsync.
  • always — приложение может быть запущено только для результатов, то есть оно может реагировать только на метод LaunchUriForResultsAsync.
  • none — приложение не может быть запущено для результатов, то есть оно может реагировать только на метод LaunchUriAsync.

В этом примере расширения протокола приложение можно запустить только для результатов. Это упрощает логику в методе OnActivated, описанном ниже, так как нам придется обрабатывать только случай запуска для результатов, а не другие возможные способы активации приложения.

<Applications>
   <Application ...>

     <Extensions>
       <uap:Extension Category="windows.protocol">
         <uap:Protocol Name="test-app2app" ReturnResults="always">
           <uap:DisplayName>Test app-2-app</uap:DisplayName>
         </uap:Protocol>
       </uap:Extension>
     </Extensions>

   </Application>
</Applications>

Шаг 2. Переопределение метода Application.OnActivated в приложении, которое будет запущено для результатов

Если этого метода уже нет в запущенном приложении, создайте его внутри класса App, определенного в файле App.xaml.cs.

В приложении, которое позволяет выбирать друзей в социальной сети, эта функция может быть размещена там, где вы выбираете страницу выбора людей. В примере ниже страница с именем LaunchedForResultsPage отображается, если приложение активировано для результатов. Убедитесь, что оператор using включен в начало файла.

using Windows.ApplicationModel.Activation;
...
protected override void OnActivated(IActivatedEventArgs args)
{
    // Window management
    Frame rootFrame = Window.Current.Content as Frame;
    if (rootFrame == null)
    {
        rootFrame = new Frame();
        Window.Current.Content = rootFrame;
    }

    // Code specific to launch for results
    var protocolForResultsArgs = (ProtocolForResultsActivatedEventArgs)args;
    // Open the page that we created to handle activation for results.
    rootFrame.Navigate(typeof(LaunchedForResultsPage), protocolForResultsArgs);

    // Ensure the current window is active.
    Window.Current.Activate();
}
using namespace winrt::Windows::ApplicationModel::Activation;
...
protected override void OnActivated(IActivatedEventArgs args)
{
    // Window management
    Frame rootFrame{ nullptr };
    auto content = Window::Current().Content();
    if (content)
    {
        rootFrame = content.try_as<Frame>();
    }
    
    if (rootFrame == null)
    {
        rootFrame = Frame();
        Window::Current().Content(rootFrame);
    }

    // Code specific to launch for results
    auto protocolForResultsEventArgs{ args.as<ProtocolForResultsActivatedEventArgs>() };
    // Open the page that we created to handle activation for results.
    rootFrame.Navigate(xaml_typename<LaunchedForResultsPage>(), protocolForResultsArgs);

    // Ensure the current window is active.
    Window::Current().Activate();
}

Поскольку расширение протокола в файле Package.appxmanifest определяет ReturnResults как always, указанный код может приводить args непосредственно в ProtocolForResultsActivatedEventArgs, и мы можем быть уверенны, что только свойство ProtocolForResultsActivatedEventArgs будет передано в метод OnActivated этого приложения. Если ваше приложение может активироваться способами, отличными от запуска для результатов, можно проверить, возвращает ли свойство IActivatedEventArgs.Kind перечисление ActivationKind.ProtocolForResults, чтобы узнать, было ли приложение запущено для результатов.

Шаг 3. Добавление поля ProtocolForResultsOperation в приложение, которое запускается для результатов

private Windows.System.ProtocolForResultsOperation _operation = null;
Windows::System::ProtocolForResultsOperation _operation = nullptr;

Вы сможете использовать поле ProtocolForResultsOperation, чтобы сообщить, когда запущенное приложение будет готово вернуть результат вызывающему приложению. В этом примере поле добавлено в класс LaunchedForResultsPage, так как вы будете выполнять операцию запуска для результатов с этой страницы и вам понадобится соответствующий доступ.

Шаг 4. Переопределение метода OnNavigatedTo() в приложении, которое запускается для результатов

Переопределите метод OnNavigatedTo на странице, которая будет отображена при запуске приложения для результатов. Если этот метод отсутствует, создайте его внутри класса для страницы, определенной в файле <pagename>.xaml.cs. Убедитесь, что следующий оператор using включен в начало файла:

using Windows.ApplicationModel.Activation
using namespace winrt::Windows::ApplicationModel::Activation;

Объект NavigationEventArgs в методе OnNavigatedTo содержит данные, переданные из вызывающего приложения. Данные хранятся в объекте ValueSet, а их объем не может превышать 100 КБ.

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

using Windows.ApplicationModel.Activation;
...
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    var protocolForResultsArgs = e.Parameter as ProtocolForResultsActivatedEventArgs;
    // Set the ProtocolForResultsOperation field.
    _operation = protocolForResultsArgs.ProtocolForResultsOperation;

    if (protocolForResultsArgs.Data.ContainsKey("TestData"))
    {
        string dataFromCaller = protocolForResultsArgs.Data["TestData"] as string;
    }
}
...
private Windows.System.ProtocolForResultsOperation _operation = null;
using namespace winrt::Windows::ApplicationModel::Activation;
...
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    auto protocolForResultsArgs = e.Parameter().try_as<ProtocolForResultsActivatedEventArgs>();
    // Set the ProtocolForResultsOperation field.
    _operation = protocolForResultsArgs.ProtocolForResultsOperation();

    if (protocolForResultsArgs.Data().HasKey("TestData"))
    {
        string dataFromCaller{ unbox_value<hstring>(protocolForResultsArgs.Data().Lookup("TestData")) };
    }
}
...
Windows::System::ProtocolForResultsOperation _operation = nullptr;

Шаг 5. Написание кода для возвращения данных вызывающему приложению

В приложении, запущенном для результатов, используйте команду ProtocolForResultsOperation для возвращения данных вызывающему приложению. В этом примере кода создается объект ValueSet, который содержит значение для возвращения в вызывающее приложение. Затем для отправки значения в вызывающее приложение используется поле ProtocolForResultsOperation.

    ValueSet result = new ValueSet();
    result["ReturnedData"] = "The returned result";
    _operation.ReportCompleted(result);
    ValueSet result;
    result.Insert("ReturnedData", "The returned result");
    _operation.ReportCompleted(result);

Шаг 6. Написание кода для запуска приложения и получения возвращенных данных

Запустите приложение из асинхронного метода в вашем вызывающем приложении, как показано в примере кода ниже. Обратите внимание, что для компиляции кода требуются следующие операторы using:

using System.Threading.Tasks;
using Windows.System;
...

async Task<string> LaunchAppForResults()
{
    var testAppUri = new Uri("test-app2app:"); // The protocol handled by the launched app
    var options = new LauncherOptions();
    options.TargetApplicationPackageFamilyName = "67d987e1-e842-4229-9f7c-98cf13b5da45_yd7nk54bq29ra";

    var inputData = new ValueSet();
    inputData["TestData"] = "Test data";

    string theResult = "";
    LaunchUriResult result = await Windows.System.Launcher.LaunchUriForResultsAsync(testAppUri, options, inputData);
    if (result.Status == LaunchUriStatus.Success &&
        result.Result != null &&
        result.Result.ContainsKey("ReturnedData"))
    {
        ValueSet theValues = result.Result;
        theResult = theValues["ReturnedData"] as string;
    }
    return theResult;
}

В этом примере ValueSet с параметром TestData передается в запущенное приложение. Запущенное приложение создает ValueSet с параметром ReturnedData, который содержит результат, возвращаемый вызывающей стороне.

Перед запуском вызывающего приложения следует собрать и развернуть приложение, которое будет запущено для результатов. В противном случае LaunchUriResult.Status сообщит об ошибке LaunchUriStatus.AppUnavailable.

Вам потребуется указать имя семейства запущенного приложения, чтобы задать значение TargetApplicationPackageFamilyName. Один из способов получить имя семейства — это выполнить следующий вызов из запущенного приложения:

string familyName = Windows.ApplicationModel.Package.Current.Id.FamilyName;

Комментарии

В примере из этой инструкции представлены основы по запуску приложения для результатов. Следует помнить о том, что новый API LaunchUriForResultsAsync позволяет запускать приложение асинхронно и поддерживать связь посредством класса ValueSet. Объем передаваемых через ValueSet данных не может превышать 100 КБ. Если нужно передать больший объем данных, вы можете поделиться файлами, используя класс SharedStorageAccessManager, чтобы создать маркеры файлов, которые можно передавать между приложениями. Например, если у вас есть ValueSet с именем inputData, вы можете сохранить маркер в файле, которым нужно поделиться с запущенным приложением:

inputData["ImageFileToken"] = SharedStorageAccessManager.AddFile(myFile);

Затем передайте маркер в запущенное приложение с помощью метода LaunchUriForResultsAsync.