启动应用以获取结果

重要的应用程序接口(API)

了解如何从另一个应用启动应用并在两者之间交换数据。 这称为 启动应用以获取结果。 此处的示例演示如何使用 LaunchUriForResultsAsync 启动应用以获取结果。

Windows 10 中的新应用到应用通信 API 使 Windows 应用(和 Windows Web 应用)能够启动应用并交换数据文件。 这样,便可以从多个应用生成混合解决方案。 使用这些新 API,现在可以无缝处理需要用户使用多个应用的复杂任务。 例如,你的应用可以启动社交网络应用以选择联系人,或启动结帐应用以完成付款过程。

将您启动以获取结果的应用称为已启动的应用。 启动应用的应用将称为调用应用。 在此示例中,你将同时编写调用应用和启动的应用。

步骤 1:在您将启动以获取结果的应用中注册要处理的协议。

在启动应用的 Package.appxmanifest 文件中,将协议扩展添加到 <应用程序> 部分。 此处的示例使用名为 test-app2app的虚构协议。

协议扩展中的 ReturnResults 属性接受以下值之一:

在此协议扩展示例中,应用只能为了获取结果而启动。 这简化了下面讨论的 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.xaml.cs中定义的 App 类中创建此方法。

在一个允许你在社交网络中选择好友的应用中,这个功能可能是在你打开选择好友页面时使用的。 在下一个示例中,当应用为结果激活时,将显示名为 LaunchedForResultsPage 的页面。 确保在文件顶部包含使用 的 语句。

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 指定为始终ReturnResults,因此仅显示的代码可以直接将 强制转换为 ProtocolFor 具有信心地 ResultsActivatedEventArgs,仅 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 Windows.ApplicationModel.Activation
using namespace winrt::Windows::ApplicationModel::Activation;

OnNavigatedTo 方法中的 NavigationEventArgs 对象包含从调用应用传递的数据。 数据可能不超过 100KB,并且存储在 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 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;
}

在此示例中,包含密钥 TestDataValueSet 被传递给启动的应用。 启动的应用创建一个 ValueSet,其键名为 ReturnedData,其中包含返回给调用端的结果。

在运行呼叫应用程序之前,您必须构建并部署要启动以获得结果的应用程序。 否则,LaunchUriResult.Status 将报告 LaunchUriStatus.AppUnavailable

当您设置 TargetApplicationPackageFamilyName时,您将需要已启动应用的家族名称。 获取姓氏的一种方法是在启动的应用程序中进行以下调用:

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

注解

本教程示例提供了一个“你好,世界”简介,用于启动应用程序以获取结果。 需要注意的关键是,新的 LaunchUriForResultsAsync API 允许异步启动应用并通过 ValueSet 类进行通信。 通过 ValueSet 传递数据限制为 100KB。 如果需要传递大量数据,可以使用 SharedStorageAccessManager 类来共享文件,以创建可在应用之间传递的文件令牌。 例如,给定一个名为 inputData,你可以将令牌存储在文件中,以便与已经启动的应用程序共享。

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

然后,通过 LaunchUriForResultsAsync将其传递给启动的应用。